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