# 2019q1W7上: 鄭珮彣 ###### tags: `linux2019` ## 測驗 `1` ```cpp static inline size_t find_next_bit(const unsigned long *bitmap, size_t bits, size_t start) { unsigned long t; size_t l = BITS_TO_LONGS(bits); size_t first_long = start / BITS_PER_LONG; size_t long_lower = start - (start % BITS_PER_LONG); if (start >= bits) return bits; t = bitmap[first_long] & BITMAP_FIRST_WORD_MASK(start); for (size_t i = first_long + 1; !t && i < l; i++) { long_lower += BITS_PER_LONG; t = bitmap[i]; } if (!t) return bits; size_t pos; pos = long_lower + bitops_ffs(t) - 1; if (pos >= bits) return bits; return pos; } ``` ## 測驗 `2` ```clike #include <time.h> #include <stdlib.h> int main(void) { unsigned long test[BITS_TO_LONGS(MAX_TEST_BITS)]; int i, j; srand(time(NULL)); for (i = 0; i < BITS_TO_LONGS(MAX_TEST_BITS); i++) { test[i] = rand() % BITS_TO_LONGS(MAX_TEST_BITS); for (j = i - 1; j >= 0; j--) if (test[i] == test[j]) i--; } for (int i = 1; i < MAX_TEST_BITS; i++) { bitmap_fill(test, i); assert(find_next_bit(test, i, 0) == 0); bitmap_zero(test, i); assert(find_next_bit(test, i, 0) == i); } return 0; } ``` ## 測驗 `3` :::info 參見 [Kernel’s Bug Reporting](https://lkw.readthedocs.io/en/latest/doc/06_kernel_bug_reporting.html) 和 [BUG 使用的討論](https://yarchive.net/comp/linux/BUG.html) ::: ```clike #include <assert.h> #include <stdbool.h> #include <stddef.h> #include <stdint.h> #include <string.h> #include <stdio.h> #define BITS_PER_BYTE 8 #define BITOPS_BUILD_BUG_ON(e) ((void)sizeof(char[1 - 2 * !!(e)])) #define BITS_PER_LONG (sizeof(unsigned long) * BITS_PER_BYTE) /** * bitops_ffs() - find (least significant) first set bit plus one * @x: unsigned long to check * Return: plus-one index of first set bit; zero when x is zero */ static inline size_t bitops_ffs(unsigned long x) { size_t i = 1; BITOPS_BUILD_BUG_ON(BITS_PER_LONG != 32 && BITS_PER_LONG != 64); if (x == 0) return 0; if (BITS_PER_LONG == 64) { if ((0x00000000fffffffful & x) == 0) { i += 32; x >>= 32; } } if ((0x0000fffful & x) == 0) { i += 16; x >>= 16; } if ((0x00fful & x) == 0) { i += 8; x >>= 8; } if ((0x0ful & x) == 0) { i += 4; x >>= 4; } if ((0x3ul & x) == 0) { i += 2; x >>= 2; } if ((0x1ul & x) == 0) { i += 1; x >>= 1; } return i; } int main() { unsigned long x ; x=16;//x=10000 bitops_ffs(x); printf("%ld\n", bitops_ffs(x)); } ``` >輸出結果 ``` 5 ``` ## 測驗 `4` ```clike #include <assert.h> #include <stdbool.h> #include <stddef.h> #include <stdint.h> #include <string.h> #include <stdio.h> #include <limits.h> #define BITS_PER_BYTE 8 #define BITOPS_BUILD_BUG_ON(e) ((void)sizeof(char[1 - 2 * !!(e)])) #define BITS_PER_LONG (sizeof(unsigned long) * BITS_PER_BYTE) /** * bitops_ffz() - find (least significant) first zero bit plus one * @x: unsigned long to check * * Return: plus-one index of first zero bit; zero when x is ULONG_MAX */ static inline size_t bitops_ffz(unsigned long x) { x=~x; size_t i = 1; BITOPS_BUILD_BUG_ON(BITS_PER_LONG != 32 && BITS_PER_LONG != 64); if (~x == ULONG_MAX) return 0; if (x == 0) return 1; if (BITS_PER_LONG == 64) { if ((0x00000000fffffffful & x) == 0) { i += 32; x >>= 32; } } if ((0x0000fffful & x) == 0) { i += 16; x >>= 16; } if ((0x00fful & x) == 0) { i += 8; x >>= 8; } if ((0x0ful & x) == 0) { i += 4; x >>= 4; } if ((0x3ul & x) == 0) { i += 2; x >>= 2; } if ((0x1ul & x) == 0) { i += 1; x >>= 1; } return i; } int main() { unsigned long x ; x=7;//x=0111 bitops_ffz(x); printf("%ld\n", bitops_ffz(x)); } ``` >輸出結果 ``` 4 ```