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
17 #ifndef __CUTILS_BITOPS_H
18 #define __CUTILS_BITOPS_H
19
20 #include <stdbool.h>
21 #include <string.h>
22 #include <strings.h>
23 #include <sys/cdefs.h>
24
25 __BEGIN_DECLS
26
27 /*
28 * Bitmask Operations
29 *
30 * Note this doesn't provide any locking/exclusion, and isn't atomic.
31 * Additionally no bounds checking is done on the bitmask array.
32 *
33 * Example:
34 *
35 * int num_resources;
36 * unsigned int resource_bits[BITS_TO_WORDS(num_resources)];
37 * bitmask_init(resource_bits, num_resources);
38 * ...
39 * int bit = bitmask_ffz(resource_bits, num_resources);
40 * bitmask_set(resource_bits, bit);
41 * ...
42 * if (bitmask_test(resource_bits, bit)) { ... }
43 * ...
44 * bitmask_clear(resource_bits, bit);
45 *
46 */
47
48 #define BITS_PER_WORD (sizeof(unsigned int) * 8)
49 #define BITS_TO_WORDS(x) (((x) + BITS_PER_WORD - 1) / BITS_PER_WORD)
50 #define BIT_IN_WORD(x) ((x) % BITS_PER_WORD)
51 #define BIT_WORD(x) ((x) / BITS_PER_WORD)
52 #define BIT_MASK(x) (1 << BIT_IN_WORD(x))
53
bitmask_init(unsigned int * bitmask,int num_bits)54 static inline void bitmask_init(unsigned int *bitmask, int num_bits)
55 {
56 memset(bitmask, 0, BITS_TO_WORDS(num_bits)*sizeof(unsigned int));
57 }
58
bitmask_ffz(unsigned int * bitmask,int num_bits)59 static inline int bitmask_ffz(unsigned int *bitmask, int num_bits)
60 {
61 int bit, result;
62 size_t i;
63
64 for (i = 0; i < BITS_TO_WORDS(num_bits); i++) {
65 bit = ffs(~bitmask[i]);
66 if (bit) {
67 // ffs is 1-indexed, return 0-indexed result
68 bit--;
69 result = BITS_PER_WORD * i + bit;
70 if (result >= num_bits)
71 return -1;
72 return result;
73 }
74 }
75 return -1;
76 }
77
bitmask_weight(unsigned int * bitmask,int num_bits)78 static inline int bitmask_weight(unsigned int *bitmask, int num_bits)
79 {
80 size_t i;
81 int weight = 0;
82
83 for (i = 0; i < BITS_TO_WORDS(num_bits); i++)
84 weight += __builtin_popcount(bitmask[i]);
85 return weight;
86 }
87
bitmask_set(unsigned int * bitmask,int bit)88 static inline void bitmask_set(unsigned int *bitmask, int bit)
89 {
90 bitmask[BIT_WORD(bit)] |= BIT_MASK(bit);
91 }
92
bitmask_clear(unsigned int * bitmask,int bit)93 static inline void bitmask_clear(unsigned int *bitmask, int bit)
94 {
95 bitmask[BIT_WORD(bit)] &= ~BIT_MASK(bit);
96 }
97
bitmask_test(unsigned int * bitmask,int bit)98 static inline bool bitmask_test(unsigned int *bitmask, int bit)
99 {
100 return bitmask[BIT_WORD(bit)] & BIT_MASK(bit);
101 }
102
popcount(unsigned int x)103 static inline int popcount(unsigned int x)
104 {
105 return __builtin_popcount(x);
106 }
107
popcountl(unsigned long x)108 static inline int popcountl(unsigned long x)
109 {
110 return __builtin_popcountl(x);
111 }
112
popcountll(unsigned long long x)113 static inline int popcountll(unsigned long long x)
114 {
115 return __builtin_popcountll(x);
116 }
117
118 __END_DECLS
119
120 #endif /* __CUTILS_BITOPS_H */
121