diff --git a/sys/bitfield/Makefile b/sys/bitfield/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/sys/bitfield/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/sys/bitfield/bitfield.c b/sys/bitfield/bitfield.c new file mode 100644 index 0000000000..110967dba1 --- /dev/null +++ b/sys/bitfield/bitfield.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2015 Kaspar Schleiser + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup sys_util + * @{ + * + * @file + * @brief Bitfield auxillary functions + * + * @author Kaspar Schleiser + * + * @} + */ + +#include +#include "bitfield.h" +#include "irq.h" + +int bf_get_unset(uint8_t field[], int size) +{ + int result = -1; + int nbytes = (size + 7) / 8; + int i = 0; + + unsigned state = disableIRQ(); + + /* skip full bytes */ + for (int j = 0; (j < nbytes) && (field[j] == 255); j++) { + i += 8; + } + + for (; i < size; i++) { + if (!bf_isset(field, i)) { + bf_set(field, i); + result = i; + break; + } + } + + restoreIRQ(state); + return(result); +} diff --git a/sys/include/bitfield.h b/sys/include/bitfield.h index 4d13a3b4cd..a0e89acd62 100644 --- a/sys/include/bitfield.h +++ b/sys/include/bitfield.h @@ -85,6 +85,19 @@ static inline bool bf_isset(uint8_t field[], size_t idx) return (field[idx / 8] & (1u << (idx % 8))); } +/** + * @brief Atomically get the number of an unset bit and set it + * + * This function can be used to record e.g., empty entries in an array. + * + * @param[in,out] field The bitfield + * @param[in] size The size of the bitfield + * + * @return number of bit that was set + * @return -1 if no bit was unset + */ +int bf_get_unset(uint8_t field[], int size); + #ifdef __cplusplus } #endif