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