1
0

bitops.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * Copyright (C) 2011 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef COCOS_CUTILS_BITOPS_H
  17. #define COCOS_CUTILS_BITOPS_H
  18. #include <stdbool.h>
  19. #include <string.h>
  20. #include <strings.h>
  21. #include <sys/cdefs.h>
  22. __BEGIN_DECLS
  23. /*
  24. * Bitmask Operations
  25. *
  26. * Note this doesn't provide any locking/exclusion, and isn't atomic.
  27. * Additionally no bounds checking is done on the bitmask array.
  28. *
  29. * Example:
  30. *
  31. * int num_resources;
  32. * unsigned int resource_bits[BITS_TO_WORDS(num_resources)];
  33. * bitmask_init(resource_bits, num_resources);
  34. * ...
  35. * int bit = bitmask_ffz(resource_bits, num_resources);
  36. * bitmask_set(resource_bits, bit);
  37. * ...
  38. * if (bitmask_test(resource_bits, bit)) { ... }
  39. * ...
  40. * bitmask_clear(resource_bits, bit);
  41. *
  42. */
  43. #define BITS_PER_WORD (sizeof(unsigned int) * 8)
  44. #define BITS_TO_WORDS(x) (((x) + BITS_PER_WORD - 1) / BITS_PER_WORD)
  45. #define BIT_IN_WORD(x) ((x) % BITS_PER_WORD)
  46. #define BIT_WORD(x) ((x) / BITS_PER_WORD)
  47. #define BIT_MASK(x) (1 << BIT_IN_WORD(x))
  48. static inline void bitmask_init(unsigned int *bitmask, int num_bits)
  49. {
  50. memset(bitmask, 0, BITS_TO_WORDS(num_bits)*sizeof(unsigned int));
  51. }
  52. static inline int bitmask_ffz(unsigned int *bitmask, int num_bits)
  53. {
  54. int bit, result;
  55. size_t i;
  56. for (i = 0; i < BITS_TO_WORDS(num_bits); i++) {
  57. bit = ffs(~bitmask[i]);
  58. if (bit) {
  59. // ffs is 1-indexed, return 0-indexed result
  60. bit--;
  61. result = BITS_PER_WORD * i + bit;
  62. if (result >= num_bits)
  63. return -1;
  64. return result;
  65. }
  66. }
  67. return -1;
  68. }
  69. static inline int bitmask_weight(unsigned int *bitmask, int num_bits)
  70. {
  71. size_t i;
  72. int weight = 0;
  73. for (i = 0; i < BITS_TO_WORDS(num_bits); i++)
  74. weight += __builtin_popcount(bitmask[i]);
  75. return weight;
  76. }
  77. static inline void bitmask_set(unsigned int *bitmask, int bit)
  78. {
  79. bitmask[BIT_WORD(bit)] |= BIT_MASK(bit);
  80. }
  81. static inline void bitmask_clear(unsigned int *bitmask, int bit)
  82. {
  83. bitmask[BIT_WORD(bit)] &= ~BIT_MASK(bit);
  84. }
  85. static inline bool bitmask_test(unsigned int *bitmask, int bit)
  86. {
  87. return bitmask[BIT_WORD(bit)] & BIT_MASK(bit);
  88. }
  89. static inline int popcount(unsigned int x)
  90. {
  91. return __builtin_popcount(x);
  92. }
  93. static inline int popcountl(unsigned long x)
  94. {
  95. return __builtin_popcountl(x);
  96. }
  97. static inline int popcountll(unsigned long long x)
  98. {
  99. return __builtin_popcountll(x);
  100. }
  101. __END_DECLS
  102. #endif /* COCOS_CUTILS_BITOPS_H */