|
|
@@ -0,0 +1,80 @@
|
|
|
+#include "bitmap.h"
|
|
|
+#include "../string.h"
|
|
|
+#include "../../kernel/debug.h"
|
|
|
+
|
|
|
+void bitmap_init(Bitmap *pb)
|
|
|
+{
|
|
|
+ _memset(pb->bits, 0, pb->btmp_bytes_len);
|
|
|
+}
|
|
|
+bool bitmap_scan_test(Bitmap *pb, uint32_t bit_idx)
|
|
|
+{
|
|
|
+ // 判断位图中 bit_idx 位是否为 1
|
|
|
+ uint32_t byte_idx = bit_idx / 8; // 向下取整用于索引数组下标
|
|
|
+ uint32_t bit_odd = bit_idx % 8; // 取余用于索引数组内的位
|
|
|
+ return (pb->bits[byte_idx] & (BITMAP_MASK << bit_odd));
|
|
|
+}
|
|
|
+// 在位图中申请连续 cnt 个位,成功则返回起始位下标,失败返回-1
|
|
|
+int bitmap_scan(Bitmap *pb, uint32_t cnt)
|
|
|
+{
|
|
|
+ uint32_t idx_byte = 0; // 用于记录空闲位所在的字节
|
|
|
+ while ((0xff == pb->bits[idx_byte]) && (idx_byte < pb->btmp_bytes_len))
|
|
|
+ { // 如果字节为 0xff,表示该字节已经被占用,继续向下一个字节查找
|
|
|
+ idx_byte++;
|
|
|
+ }
|
|
|
+ ASSERT(idx_byte < pb->btmp_bytes_len);
|
|
|
+ if (idx_byte == pb->btmp_bytes_len)
|
|
|
+ { // 该内存池找不到可用空间
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 若在位图数组范围内的某字节内找到了空闲位,则在字节内逐位查找空闲位的索引
|
|
|
+ int idx_bit = 0;
|
|
|
+ // 和 pb->bits[idx_byte] 这个字节逐位对比
|
|
|
+ while ((uint8_t)(BITMAP_MASK << idx_bit) & pb->bits[idx_byte])
|
|
|
+ { // 1 << idx_bit 生成 00010000 这样的数,和 pb->bits[idx_byte]逐位与操作
|
|
|
+ idx_bit++;
|
|
|
+ }
|
|
|
+ int bit_idx_start = idx_byte * 8 + idx_bit; // 空闲位在位图内的下标
|
|
|
+ if (cnt == 1)
|
|
|
+ {
|
|
|
+ return bit_idx_start;
|
|
|
+ }
|
|
|
+ uint32_t bit_left = (pb->btmp_bytes_len * 8 - bit_idx_start); // 记录还有多少位可以判断
|
|
|
+ uint32_t next_bit = bit_idx_start + 1;
|
|
|
+ uint32_t count = 1; // 用于记录找到的空闲位的个数
|
|
|
+
|
|
|
+ bit_idx_start = -1; // 先将其置为-1,若找不到连续的位就直接返回
|
|
|
+ while (bit_left-- > 0)
|
|
|
+ {
|
|
|
+ if (!(bitmap_scan_test(pb, next_bit)))
|
|
|
+ { // 若 next_bit 为 0
|
|
|
+ count++;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ count = 0;
|
|
|
+ }
|
|
|
+ if (count == cnt)
|
|
|
+ { // 若找到连续的 cnt 个空闲位
|
|
|
+ bit_idx_start = next_bit - cnt + 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ next_bit++;
|
|
|
+ }
|
|
|
+ return bit_idx_start;
|
|
|
+}
|
|
|
+void bitmap_set(Bitmap *pb, uint32_t bit_idx, int8_t value)
|
|
|
+{
|
|
|
+ ASSERT((value == 0) || (value == 1));
|
|
|
+ uint32_t byte_idx = bit_idx / 8; // 向下取整用于索引数组下标
|
|
|
+ uint32_t bit_odd = bit_idx % 8; // 取余用于索引数组内的位
|
|
|
+
|
|
|
+ if (value)
|
|
|
+ { // 若 value 为 1, 则 OR 1 到 bitmap[byte_idx] 的 bit_odd 位上
|
|
|
+ pb->bits[byte_idx] |= (BITMAP_MASK << bit_odd);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ { // 若 value 为 0, 则 AND 0 到 bitmap[byte_idx] 的 bit_odd 位上
|
|
|
+ pb->bits[byte_idx] &= ~(BITMAP_MASK << bit_odd);
|
|
|
+ }
|
|
|
+}
|