1 | /* $NetBSD: bitops.h,v 1.11 2015/10/13 00:42:59 riastradh Exp $ */ |
2 | |
3 | /*- |
4 | * Copyright (c) 2013 The NetBSD Foundation, Inc. |
5 | * All rights reserved. |
6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Taylor R. Campbell. |
9 | * |
10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions |
12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. |
18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ |
31 | |
32 | #ifndef _LINUX_BITOPS_H_ |
33 | #define _LINUX_BITOPS_H_ |
34 | |
35 | #include <sys/cdefs.h> |
36 | #include <sys/types.h> |
37 | #include <sys/param.h> |
38 | #include <sys/atomic.h> |
39 | #include <sys/bitops.h> |
40 | |
41 | #include <machine/limits.h> |
42 | |
43 | #include <lib/libkern/libkern.h> |
44 | |
45 | /* |
46 | * Linux __ffs/__ffs64 is zero-based; zero input is undefined. Our |
47 | * ffs/ffs64 is one-based; zero input yields zero. |
48 | */ |
49 | static inline unsigned long |
50 | __ffs(unsigned long x) |
51 | { |
52 | |
53 | KASSERT(x != 0); |
54 | return ffs64(x) - 1; |
55 | } |
56 | |
57 | static inline unsigned long |
58 | __ffs64(uint64_t x) |
59 | { |
60 | |
61 | KASSERT(x != 0); |
62 | return ffs64(x) - 1; |
63 | } |
64 | |
65 | static inline unsigned int |
66 | hweight16(uint16_t n) |
67 | { |
68 | return popcount32(n); |
69 | } |
70 | |
71 | static inline unsigned int |
72 | hweight32(uint16_t n) |
73 | { |
74 | return popcount32(n); |
75 | } |
76 | |
77 | /* |
78 | * XXX Don't define BITS_PER_LONG as sizeof(unsigned long)*CHAR_BIT |
79 | * because that won't work in preprocessor conditionals, where it often |
80 | * turns up. |
81 | */ |
82 | |
83 | #define BITS_TO_LONGS(n) \ |
84 | roundup2((n), (sizeof(unsigned long) * CHAR_BIT)) |
85 | |
86 | #define BIT(n) ((uintmax_t)1 << (n)) |
87 | |
88 | static inline int |
89 | test_bit(unsigned int n, const volatile unsigned long *p) |
90 | { |
91 | const unsigned units = (sizeof(unsigned long) * CHAR_BIT); |
92 | |
93 | return ((p[n / units] & (1UL << (n % units))) != 0); |
94 | } |
95 | |
96 | static inline void |
97 | __set_bit(unsigned int n, volatile unsigned long *p) |
98 | { |
99 | const unsigned units = (sizeof(unsigned long) * CHAR_BIT); |
100 | |
101 | p[n / units] |= (1UL << (n % units)); |
102 | } |
103 | |
104 | static inline void |
105 | __clear_bit(unsigned int n, volatile unsigned long *p) |
106 | { |
107 | const unsigned units = (sizeof(unsigned long) * CHAR_BIT); |
108 | |
109 | p[n / units] &= ~(1UL << (n % units)); |
110 | } |
111 | |
112 | static inline void |
113 | __change_bit(unsigned int n, volatile unsigned long *p) |
114 | { |
115 | const unsigned units = (sizeof(unsigned long) * CHAR_BIT); |
116 | |
117 | p[n / units] ^= (1UL << (n % units)); |
118 | } |
119 | |
120 | static inline unsigned long |
121 | __test_and_set_bit(unsigned int bit, volatile unsigned long *ptr) |
122 | { |
123 | const unsigned int units = (sizeof(*ptr) * CHAR_BIT); |
124 | volatile unsigned long *const p = &ptr[bit / units]; |
125 | const unsigned long mask = (1UL << (bit % units)); |
126 | unsigned long v; |
127 | |
128 | v = *p; |
129 | *p |= mask; |
130 | |
131 | return ((v & mask) != 0); |
132 | } |
133 | |
134 | static inline unsigned long |
135 | __test_and_clear_bit(unsigned int bit, volatile unsigned long *ptr) |
136 | { |
137 | const unsigned int units = (sizeof(*ptr) * CHAR_BIT); |
138 | volatile unsigned long *const p = &ptr[bit / units]; |
139 | const unsigned long mask = (1UL << (bit % units)); |
140 | unsigned long v; |
141 | |
142 | v = *p; |
143 | *p &= ~mask; |
144 | |
145 | return ((v & mask) != 0); |
146 | } |
147 | |
148 | static inline unsigned long |
149 | __test_and_change_bit(unsigned int bit, volatile unsigned long *ptr) |
150 | { |
151 | const unsigned int units = (sizeof(*ptr) * CHAR_BIT); |
152 | volatile unsigned long *const p = &ptr[bit / units]; |
153 | const unsigned long mask = (1UL << (bit % units)); |
154 | unsigned long v; |
155 | |
156 | v = *p; |
157 | *p ^= mask; |
158 | |
159 | return ((v & mask) != 0); |
160 | } |
161 | |
162 | static inline unsigned long |
163 | find_first_zero_bit(const unsigned long *ptr, unsigned long nbits) |
164 | { |
165 | const size_t bpl = (CHAR_BIT * sizeof(*ptr)); |
166 | const unsigned long *p; |
167 | unsigned long result = 0; |
168 | |
169 | for (p = ptr; bpl < nbits; nbits -= bpl, p++, result += bpl) { |
170 | if (~*p) |
171 | break; |
172 | } |
173 | |
174 | result += ffs(~*p | (~0UL << MIN(nbits, bpl))); |
175 | return result; |
176 | } |
177 | |
178 | static inline unsigned |
179 | hweight8(unsigned w) |
180 | { |
181 | |
182 | return popcount(w & 0xff); |
183 | } |
184 | |
185 | #endif /* _LINUX_BITOPS_H_ */ |
186 | |