xref: /netbsd-src/sys/external/bsd/common/include/linux/bitops.h (revision 70876abcb1207d7177d39dd170979d3d251013b9)
1*70876abcSrin /*	$NetBSD: bitops.h,v 1.17 2024/10/02 01:56:02 rin Exp $	*/
2922889e3Sriastradh 
3922889e3Sriastradh /*-
4922889e3Sriastradh  * Copyright (c) 2013 The NetBSD Foundation, Inc.
5922889e3Sriastradh  * All rights reserved.
6922889e3Sriastradh  *
7922889e3Sriastradh  * This code is derived from software contributed to The NetBSD Foundation
8922889e3Sriastradh  * by Taylor R. Campbell.
9922889e3Sriastradh  *
10922889e3Sriastradh  * Redistribution and use in source and binary forms, with or without
11922889e3Sriastradh  * modification, are permitted provided that the following conditions
12922889e3Sriastradh  * are met:
13922889e3Sriastradh  * 1. Redistributions of source code must retain the above copyright
14922889e3Sriastradh  *    notice, this list of conditions and the following disclaimer.
15922889e3Sriastradh  * 2. Redistributions in binary form must reproduce the above copyright
16922889e3Sriastradh  *    notice, this list of conditions and the following disclaimer in the
17922889e3Sriastradh  *    documentation and/or other materials provided with the distribution.
18922889e3Sriastradh  *
19922889e3Sriastradh  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20922889e3Sriastradh  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21922889e3Sriastradh  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22922889e3Sriastradh  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23922889e3Sriastradh  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24922889e3Sriastradh  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25922889e3Sriastradh  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26922889e3Sriastradh  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27922889e3Sriastradh  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28922889e3Sriastradh  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29922889e3Sriastradh  * POSSIBILITY OF SUCH DAMAGE.
30922889e3Sriastradh  */
31922889e3Sriastradh 
32922889e3Sriastradh #ifndef _LINUX_BITOPS_H_
33922889e3Sriastradh #define _LINUX_BITOPS_H_
34922889e3Sriastradh 
35922889e3Sriastradh #include <sys/cdefs.h>
36922889e3Sriastradh #include <sys/types.h>
37922889e3Sriastradh #include <sys/param.h>
38922889e3Sriastradh #include <sys/atomic.h>
39922889e3Sriastradh #include <sys/bitops.h>
40922889e3Sriastradh 
41922889e3Sriastradh #include <machine/limits.h>
42922889e3Sriastradh 
43922889e3Sriastradh #include <lib/libkern/libkern.h>
44130a03cdSriastradh 
45130a03cdSriastradh #include <asm/barrier.h>
46130a03cdSriastradh 
47d87b8e70Sriastradh #include <linux/bits.h>
48922889e3Sriastradh 
49922889e3Sriastradh /*
50922889e3Sriastradh  * Linux __ffs/__ffs64 is zero-based; zero input is undefined.  Our
51922889e3Sriastradh  * ffs/ffs64 is one-based; zero input yields zero.
52922889e3Sriastradh  */
53922889e3Sriastradh static inline unsigned long
54922889e3Sriastradh __ffs(unsigned long x)
55922889e3Sriastradh {
56922889e3Sriastradh 
57922889e3Sriastradh 	KASSERT(x != 0);
58922889e3Sriastradh 	return ffs64(x) - 1;
59922889e3Sriastradh }
60922889e3Sriastradh 
61922889e3Sriastradh static inline unsigned long
62922889e3Sriastradh __ffs64(uint64_t x)
63922889e3Sriastradh {
64922889e3Sriastradh 
65922889e3Sriastradh 	KASSERT(x != 0);
66922889e3Sriastradh 	return ffs64(x) - 1;
67922889e3Sriastradh }
68922889e3Sriastradh 
69d839e507Sriastradh /*
70d839e507Sriastradh  * Linux fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32, so it matches
71d839e507Sriastradh  * our fls semantics.
72d839e507Sriastradh  */
73d839e507Sriastradh static inline int
74d839e507Sriastradh fls(int x)
75d839e507Sriastradh {
76d839e507Sriastradh 	return fls32(x);
77d839e507Sriastradh }
78d839e507Sriastradh 
79922889e3Sriastradh static inline unsigned int
80be1fbc26Sriastradh hweight8(uint8_t w)
81be1fbc26Sriastradh {
82be1fbc26Sriastradh 	return popcount(w & 0xff);
83be1fbc26Sriastradh }
84be1fbc26Sriastradh 
85be1fbc26Sriastradh static inline unsigned int
86922889e3Sriastradh hweight16(uint16_t n)
87922889e3Sriastradh {
88922889e3Sriastradh 	return popcount32(n);
89922889e3Sriastradh }
90922889e3Sriastradh 
91922889e3Sriastradh static inline unsigned int
92922889e3Sriastradh hweight32(uint32_t n)
93922889e3Sriastradh {
94922889e3Sriastradh 	return popcount32(n);
95922889e3Sriastradh }
96922889e3Sriastradh 
977174c430Sriastradh static inline unsigned int
987174c430Sriastradh hweight64(uint64_t n)
997174c430Sriastradh {
1007174c430Sriastradh 	return popcount64(n);
1017174c430Sriastradh }
1027174c430Sriastradh 
10361003359Sriastradh static inline int64_t
10461003359Sriastradh sign_extend64(uint64_t x, unsigned n)
10561003359Sriastradh {
10661003359Sriastradh 	return (int64_t)(x << (63 - n)) >> (63 - n);
10761003359Sriastradh }
10861003359Sriastradh 
109922889e3Sriastradh #define	BITS_TO_LONGS(n)						\
110*70876abcSrin 	howmany((n), (sizeof(unsigned long) * CHAR_BIT))
111922889e3Sriastradh 
1124eebc6bdSriastradh #define	BITS_PER_TYPE(type)	(sizeof(type) * NBBY)
113b2d25b3fSriastradh #define	BITS_PER_BYTE		NBBY
1141f672123Sriastradh #define	BITS_PER_LONG		(__SIZEOF_LONG__ * CHAR_BIT)
115b2d25b3fSriastradh 
116b2d25b3fSriastradh #define	BIT(n)		((unsigned long)__BIT(n))
117b2d25b3fSriastradh #define	BIT_ULL(n)	((unsigned long long)__BIT(n))
11861003359Sriastradh #define	GENMASK(h,l)	((unsigned long)__BITS(h,l))
11961003359Sriastradh #define	GENMASK_ULL(h,l)((unsigned long long)__BITS(h,l))
120922889e3Sriastradh 
121922889e3Sriastradh static inline int
122922889e3Sriastradh test_bit(unsigned int n, const volatile unsigned long *p)
123922889e3Sriastradh {
124922889e3Sriastradh 	const unsigned units = (sizeof(unsigned long) * CHAR_BIT);
125922889e3Sriastradh 
126922889e3Sriastradh 	return ((p[n / units] & (1UL << (n % units))) != 0);
127922889e3Sriastradh }
128922889e3Sriastradh 
129922889e3Sriastradh static inline void
130922889e3Sriastradh __set_bit(unsigned int n, volatile unsigned long *p)
131922889e3Sriastradh {
132922889e3Sriastradh 	const unsigned units = (sizeof(unsigned long) * CHAR_BIT);
133922889e3Sriastradh 
134922889e3Sriastradh 	p[n / units] |= (1UL << (n % units));
135922889e3Sriastradh }
136922889e3Sriastradh 
137922889e3Sriastradh static inline void
138922889e3Sriastradh __clear_bit(unsigned int n, volatile unsigned long *p)
139922889e3Sriastradh {
140922889e3Sriastradh 	const unsigned units = (sizeof(unsigned long) * CHAR_BIT);
141922889e3Sriastradh 
142922889e3Sriastradh 	p[n / units] &= ~(1UL << (n % units));
143922889e3Sriastradh }
144922889e3Sriastradh 
145922889e3Sriastradh static inline void
146922889e3Sriastradh __change_bit(unsigned int n, volatile unsigned long *p)
147922889e3Sriastradh {
148922889e3Sriastradh 	const unsigned units = (sizeof(unsigned long) * CHAR_BIT);
149922889e3Sriastradh 
150922889e3Sriastradh 	p[n / units] ^= (1UL << (n % units));
151922889e3Sriastradh }
152922889e3Sriastradh 
153922889e3Sriastradh static inline unsigned long
154922889e3Sriastradh __test_and_set_bit(unsigned int bit, volatile unsigned long *ptr)
155922889e3Sriastradh {
156922889e3Sriastradh 	const unsigned int units = (sizeof(*ptr) * CHAR_BIT);
157922889e3Sriastradh 	volatile unsigned long *const p = &ptr[bit / units];
158922889e3Sriastradh 	const unsigned long mask = (1UL << (bit % units));
159922889e3Sriastradh 	unsigned long v;
160922889e3Sriastradh 
161922889e3Sriastradh 	v = *p;
162922889e3Sriastradh 	*p |= mask;
163922889e3Sriastradh 
164922889e3Sriastradh 	return ((v & mask) != 0);
165922889e3Sriastradh }
166922889e3Sriastradh 
167922889e3Sriastradh static inline unsigned long
168922889e3Sriastradh __test_and_clear_bit(unsigned int bit, volatile unsigned long *ptr)
169922889e3Sriastradh {
170922889e3Sriastradh 	const unsigned int units = (sizeof(*ptr) * CHAR_BIT);
171922889e3Sriastradh 	volatile unsigned long *const p = &ptr[bit / units];
172922889e3Sriastradh 	const unsigned long mask = (1UL << (bit % units));
173922889e3Sriastradh 	unsigned long v;
174922889e3Sriastradh 
175922889e3Sriastradh 	v = *p;
176922889e3Sriastradh 	*p &= ~mask;
177922889e3Sriastradh 
178922889e3Sriastradh 	return ((v & mask) != 0);
179922889e3Sriastradh }
180922889e3Sriastradh 
181922889e3Sriastradh static inline unsigned long
182922889e3Sriastradh __test_and_change_bit(unsigned int bit, volatile unsigned long *ptr)
183922889e3Sriastradh {
184922889e3Sriastradh 	const unsigned int units = (sizeof(*ptr) * CHAR_BIT);
185922889e3Sriastradh 	volatile unsigned long *const p = &ptr[bit / units];
186922889e3Sriastradh 	const unsigned long mask = (1UL << (bit % units));
187922889e3Sriastradh 	unsigned long v;
188922889e3Sriastradh 
189922889e3Sriastradh 	v = *p;
190922889e3Sriastradh 	*p ^= mask;
191922889e3Sriastradh 
192922889e3Sriastradh 	return ((v & mask) != 0);
193922889e3Sriastradh }
194922889e3Sriastradh 
195922889e3Sriastradh static inline unsigned long
196e0feb6feSriastradh __find_next_bit(const unsigned long *ptr, unsigned long nbits,
197e0feb6feSriastradh     unsigned long startbit, unsigned long toggle)
198922889e3Sriastradh {
199922889e3Sriastradh 	const size_t bpl = (CHAR_BIT * sizeof(*ptr));
200aa831e2bSriastradh 	const unsigned long *p = ptr + startbit/bpl;
201d60c790dSriastradh 	size_t n = howmany(nbits, bpl);
202d60c790dSriastradh 	unsigned long result;
203aa831e2bSriastradh 	uint64_t word;
204922889e3Sriastradh 
205aa831e2bSriastradh 	/*
206aa831e2bSriastradh 	 * We use ffs64 because NetBSD doesn't have a handy ffsl that
207aa831e2bSriastradh 	 * works on unsigned long.  This is a waste on 32-bit systems
208aa831e2bSriastradh 	 * but I'd rather not maintain multiple copies of this -- the
209aa831e2bSriastradh 	 * first version had enough bugs already.
210aa831e2bSriastradh 	 */
211aa831e2bSriastradh 
212aa831e2bSriastradh 	/* Do we need to examine a partial starting word?  */
213aa831e2bSriastradh 	if (startbit % bpl) {
214e0feb6feSriastradh 		/* Toggle the bits and convert to 64 bits for ffs64.  */
215e0feb6feSriastradh 		word = *p ^ toggle;
216aa831e2bSriastradh 
217d60c790dSriastradh 		/* Clear the low startbit%bpl bits.  */
218d60c790dSriastradh 		word &= (~0UL << (startbit % bpl));
219aa831e2bSriastradh 
220d60c790dSriastradh 		/* Are any of these bits set now?  */
221d60c790dSriastradh 		if (word)
222d60c790dSriastradh 			goto out;
223d60c790dSriastradh 
224d60c790dSriastradh 		/* Move past it.  */
225d60c790dSriastradh 		p++;
226d60c790dSriastradh 		n--;
227d60c790dSriastradh 	}
228d60c790dSriastradh 
229d60c790dSriastradh 	/* Find the first word with any bits set.  */
230d60c790dSriastradh 	for (; n --> 0; p++) {
231d60c790dSriastradh 		/* Toggle the bits and convert to 64 bits for ffs64. */
232d60c790dSriastradh 		word = *p ^ toggle;
233d60c790dSriastradh 
234d60c790dSriastradh 		/* Are any of these bits set now?  */
235d60c790dSriastradh 		if (word)
236d60c790dSriastradh 			goto out;
237d60c790dSriastradh 	}
238d60c790dSriastradh 
239d60c790dSriastradh 	/* Nada.  */
240d60c790dSriastradh 	return nbits;
241d60c790dSriastradh 
242d60c790dSriastradh out:
243d60c790dSriastradh 	/* Count how many words we've skipped.  */
244d60c790dSriastradh 	result = bpl*(p - ptr);
245d60c790dSriastradh 
246d60c790dSriastradh 	/* Find the first set bit in this word, zero-based.  */
247d60c790dSriastradh 	result += ffs64(word) - 1;
248d60c790dSriastradh 
249d60c790dSriastradh 	/* We may have overshot, so clamp down to at most nbits.  */
250aa831e2bSriastradh 	return MIN(result, nbits);
251aa831e2bSriastradh }
252aa831e2bSriastradh 
253aa831e2bSriastradh static inline unsigned long
254e0feb6feSriastradh find_next_bit(const unsigned long *ptr, unsigned long nbits,
255e0feb6feSriastradh     unsigned long startbit)
256e0feb6feSriastradh {
257e0feb6feSriastradh 	return __find_next_bit(ptr, nbits, startbit, 0);
258e0feb6feSriastradh }
259e0feb6feSriastradh 
260e0feb6feSriastradh static inline unsigned long
261e0feb6feSriastradh find_first_bit(const unsigned long *ptr, unsigned long nbits)
262e0feb6feSriastradh {
263e0feb6feSriastradh 	return find_next_bit(ptr, nbits, 0);
264e0feb6feSriastradh }
265e0feb6feSriastradh 
266e0feb6feSriastradh static inline unsigned long
267e0feb6feSriastradh find_next_zero_bit(const unsigned long *ptr, unsigned long nbits,
268e0feb6feSriastradh     unsigned long startbit)
269e0feb6feSriastradh {
270e0feb6feSriastradh 	return __find_next_bit(ptr, nbits, startbit, ~0UL);
271e0feb6feSriastradh }
272e0feb6feSriastradh 
273e0feb6feSriastradh static inline unsigned long
274aa831e2bSriastradh find_first_zero_bit(const unsigned long *ptr, unsigned long nbits)
275aa831e2bSriastradh {
276aa831e2bSriastradh 	return find_next_zero_bit(ptr, nbits, 0);
277922889e3Sriastradh }
278922889e3Sriastradh 
279e0feb6feSriastradh #define	for_each_set_bit(BIT, PTR, NBITS)				      \
280e0feb6feSriastradh 	for ((BIT) = find_first_bit((PTR), (NBITS));			      \
281e0feb6feSriastradh 	     (BIT) < (NBITS);						      \
282e0feb6feSriastradh 	     (BIT) = find_next_bit((PTR), (NBITS), (BIT) + 1))
283e0feb6feSriastradh 
28461003359Sriastradh #define	for_each_clear_bit(BIT, PTR, NBITS)				      \
28561003359Sriastradh 	for ((BIT) = find_first_zero_bit((PTR), (NBITS));		      \
28661003359Sriastradh 	     (BIT) < (NBITS);						      \
28761003359Sriastradh 	     (BIT) = find_next_zero_bit((PTR), (NBITS), (BIT) + 1))
28861003359Sriastradh 
289130a03cdSriastradh static inline void
290130a03cdSriastradh set_bit(unsigned int bit, volatile unsigned long *ptr)
291130a03cdSriastradh {
292130a03cdSriastradh 	const unsigned int units = (sizeof(*ptr) * CHAR_BIT);
293130a03cdSriastradh 
294130a03cdSriastradh 	/* no memory barrier */
295130a03cdSriastradh 	atomic_or_ulong(&ptr[bit / units], (1UL << (bit % units)));
296130a03cdSriastradh }
297130a03cdSriastradh 
298130a03cdSriastradh static inline void
299130a03cdSriastradh clear_bit(unsigned int bit, volatile unsigned long *ptr)
300130a03cdSriastradh {
301130a03cdSriastradh 	const unsigned int units = (sizeof(*ptr) * CHAR_BIT);
302130a03cdSriastradh 
303130a03cdSriastradh 	/* no memory barrier */
304130a03cdSriastradh 	atomic_and_ulong(&ptr[bit / units], ~(1UL << (bit % units)));
305130a03cdSriastradh }
306130a03cdSriastradh 
307130a03cdSriastradh static inline void
308130a03cdSriastradh clear_bit_unlock(unsigned int bit, volatile unsigned long *ptr)
309130a03cdSriastradh {
310130a03cdSriastradh 	const unsigned int units = (sizeof(*ptr) * CHAR_BIT);
311130a03cdSriastradh 
312130a03cdSriastradh 	/* store-release */
313130a03cdSriastradh 	smp_mb__before_atomic();
314130a03cdSriastradh 	atomic_and_ulong(&ptr[bit / units], ~(1UL << (bit % units)));
315130a03cdSriastradh }
316130a03cdSriastradh 
317130a03cdSriastradh static inline void
318130a03cdSriastradh change_bit(unsigned int bit, volatile unsigned long *ptr)
319130a03cdSriastradh {
320130a03cdSriastradh 	const unsigned int units = (sizeof(*ptr) * CHAR_BIT);
321130a03cdSriastradh 	volatile unsigned long *const p = &ptr[bit / units];
322130a03cdSriastradh 	const unsigned long mask = (1UL << (bit % units));
323130a03cdSriastradh 	unsigned long v;
324130a03cdSriastradh 
325130a03cdSriastradh 	/* no memory barrier */
326130a03cdSriastradh 	do v = *p; while (atomic_cas_ulong(p, v, (v ^ mask)) != v);
327130a03cdSriastradh }
328130a03cdSriastradh 
329130a03cdSriastradh static inline int
330130a03cdSriastradh test_and_set_bit(unsigned int bit, volatile unsigned long *ptr)
331130a03cdSriastradh {
332130a03cdSriastradh 	const unsigned int units = (sizeof(*ptr) * CHAR_BIT);
333130a03cdSriastradh 	volatile unsigned long *const p = &ptr[bit / units];
334130a03cdSriastradh 	const unsigned long mask = (1UL << (bit % units));
335130a03cdSriastradh 	unsigned long v;
336130a03cdSriastradh 
337130a03cdSriastradh 	smp_mb__before_atomic();
338130a03cdSriastradh 	do v = *p; while (atomic_cas_ulong(p, v, (v | mask)) != v);
339130a03cdSriastradh 	smp_mb__after_atomic();
340130a03cdSriastradh 
341130a03cdSriastradh 	return ((v & mask) != 0);
342130a03cdSriastradh }
343130a03cdSriastradh 
344130a03cdSriastradh static inline int
345130a03cdSriastradh test_and_clear_bit(unsigned int bit, volatile unsigned long *ptr)
346130a03cdSriastradh {
347130a03cdSriastradh 	const unsigned int units = (sizeof(*ptr) * CHAR_BIT);
348130a03cdSriastradh 	volatile unsigned long *const p = &ptr[bit / units];
349130a03cdSriastradh 	const unsigned long mask = (1UL << (bit % units));
350130a03cdSriastradh 	unsigned long v;
351130a03cdSriastradh 
352130a03cdSriastradh 	smp_mb__before_atomic();
353130a03cdSriastradh 	do v = *p; while (atomic_cas_ulong(p, v, (v & ~mask)) != v);
354130a03cdSriastradh 	smp_mb__after_atomic();
355130a03cdSriastradh 
356130a03cdSriastradh 	return ((v & mask) != 0);
357130a03cdSriastradh }
358130a03cdSriastradh 
359130a03cdSriastradh static inline int
360130a03cdSriastradh test_and_change_bit(unsigned int bit, volatile unsigned long *ptr)
361130a03cdSriastradh {
362130a03cdSriastradh 	const unsigned int units = (sizeof(*ptr) * CHAR_BIT);
363130a03cdSriastradh 	volatile unsigned long *const p = &ptr[bit / units];
364130a03cdSriastradh 	const unsigned long mask = (1UL << (bit % units));
365130a03cdSriastradh 	unsigned long v;
366130a03cdSriastradh 
367130a03cdSriastradh 	smp_mb__before_atomic();
368130a03cdSriastradh 	do v = *p; while (atomic_cas_ulong(p, v, (v ^ mask)) != v);
369130a03cdSriastradh 	smp_mb__after_atomic();
370130a03cdSriastradh 
371130a03cdSriastradh 	return ((v & mask) != 0);
372130a03cdSriastradh }
373130a03cdSriastradh 
374922889e3Sriastradh #endif  /* _LINUX_BITOPS_H_ */
375