bitmap.c 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. #include "bitmap.h"
  2. #include "../string.h"
  3. #include "../../kernel/debug.h"
  4. void bitmap_init(Bitmap *pb)
  5. {
  6. _memset(pb->bits, 0, pb->btmp_bytes_len);
  7. }
  8. bool bitmap_scan_test(Bitmap *pb, uint32_t bit_idx)
  9. {
  10. // 判断位图中 bit_idx 位是否为 1
  11. uint32_t byte_idx = bit_idx / 8; // 向下取整用于索引数组下标
  12. uint32_t bit_odd = bit_idx % 8; // 取余用于索引数组内的位
  13. return (pb->bits[byte_idx] & (BITMAP_MASK << bit_odd));
  14. }
  15. // 在位图中申请连续 cnt 个位,成功则返回起始位下标,失败返回-1
  16. int bitmap_scan(Bitmap *pb, uint32_t cnt)
  17. {
  18. uint32_t idx_byte = 0; // 用于记录空闲位所在的字节
  19. while ((0xff == pb->bits[idx_byte]) && (idx_byte < pb->btmp_bytes_len))
  20. { // 如果字节为 0xff,表示该字节已经被占用,继续向下一个字节查找
  21. idx_byte++;
  22. }
  23. ASSERT(idx_byte < pb->btmp_bytes_len);
  24. if (idx_byte == pb->btmp_bytes_len)
  25. { // 该内存池找不到可用空间
  26. return -1;
  27. }
  28. // 若在位图数组范围内的某字节内找到了空闲位,则在字节内逐位查找空闲位的索引
  29. int idx_bit = 0;
  30. // 和 pb->bits[idx_byte] 这个字节逐位对比
  31. while ((uint8_t)(BITMAP_MASK << idx_bit) & pb->bits[idx_byte])
  32. { // 1 << idx_bit 生成 00010000 这样的数,和 pb->bits[idx_byte]逐位与操作
  33. idx_bit++;
  34. }
  35. int bit_idx_start = idx_byte * 8 + idx_bit; // 空闲位在位图内的下标
  36. if (cnt == 1)
  37. {
  38. return bit_idx_start;
  39. }
  40. uint32_t bit_left = (pb->btmp_bytes_len * 8 - bit_idx_start); // 记录还有多少位可以判断
  41. uint32_t next_bit = bit_idx_start + 1;
  42. uint32_t count = 1; // 用于记录找到的空闲位的个数
  43. bit_idx_start = -1; // 先将其置为-1,若找不到连续的位就直接返回
  44. while (bit_left-- > 0)
  45. {
  46. if (!(bitmap_scan_test(pb, next_bit)))
  47. { // 若 next_bit 为 0
  48. count++;
  49. }
  50. else
  51. {
  52. count = 0;
  53. }
  54. if (count == cnt)
  55. { // 若找到连续的 cnt 个空闲位
  56. bit_idx_start = next_bit - cnt + 1;
  57. break;
  58. }
  59. next_bit++;
  60. }
  61. return bit_idx_start;
  62. }
  63. void bitmap_set(Bitmap *pb, uint32_t bit_idx, int8_t value)
  64. {
  65. ASSERT((value == 0) || (value == 1));
  66. uint32_t byte_idx = bit_idx / 8; // 向下取整用于索引数组下标
  67. uint32_t bit_odd = bit_idx % 8; // 取余用于索引数组内的位
  68. if (value)
  69. { // 若 value 为 1, 则 OR 1 到 bitmap[byte_idx] 的 bit_odd 位上
  70. pb->bits[byte_idx] |= (BITMAP_MASK << bit_odd);
  71. }
  72. else
  73. { // 若 value 为 0, 则 AND 0 到 bitmap[byte_idx] 的 bit_odd 位上
  74. pb->bits[byte_idx] &= ~(BITMAP_MASK << bit_odd);
  75. }
  76. }