Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/external/bsd/common/include/linux Implement find_next_ze...



details:   https://anonhg.NetBSD.org/src/rev/0ff352d330ab
branches:  trunk
changeset: 992593:0ff352d330ab
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Mon Aug 27 07:08:37 2018 +0000

description:
Implement find_next_zero_bit.  Define find_first_zero_bit in terms of it.

diffstat:

 sys/external/bsd/common/include/linux/bitops.h |  55 ++++++++++++++++++++++---
 1 files changed, 47 insertions(+), 8 deletions(-)

diffs (76 lines):

diff -r f27e182f395d -r 0ff352d330ab sys/external/bsd/common/include/linux/bitops.h
--- a/sys/external/bsd/common/include/linux/bitops.h    Mon Aug 27 07:08:20 2018 +0000
+++ b/sys/external/bsd/common/include/linux/bitops.h    Mon Aug 27 07:08:37 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bitops.h,v 1.4 2018/08/27 07:04:32 riastradh Exp $     */
+/*     $NetBSD: bitops.h,v 1.5 2018/08/27 07:08:37 riastradh Exp $     */
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -177,20 +177,59 @@
 }
 
 static inline unsigned long
-find_first_zero_bit(const unsigned long *ptr, unsigned long nbits)
+find_next_zero_bit(const unsigned long *ptr, unsigned long nbits,
+    unsigned long startbit)
 {
        const size_t bpl = (CHAR_BIT * sizeof(*ptr));
-       const unsigned long *p;
-       unsigned long result = 0;
+       const unsigned long *p = ptr + startbit/bpl;
+       unsigned long result = rounddown(startbit, bpl);
+       uint64_t word;
+
+       /*
+        * We use ffs64 because NetBSD doesn't have a handy ffsl that
+        * works on unsigned long.  This is a waste on 32-bit systems
+        * but I'd rather not maintain multiple copies of this -- the
+        * first version had enough bugs already.
+        */
 
-       for (p = ptr; bpl < nbits; nbits -= bpl, p++, result += bpl) {
+       /* Do we need to examine a partial starting word?  */
+       if (startbit % bpl) {
+               /* Are any of the first startbit%bpl bits zero?  */
+               if (~(*p | (~0UL << (startbit % bpl)))) {
+                       /* Invert the bits and convert to 64 bits.  */
+                       word = ~(uint64_t)*p;
+
+                       /* Clear the low startbit%bpl bits.  */
+                       word &= ~(~0UL << (startbit % bpl));
+
+                       /* Find the first set bit in this word. */
+                       result += ffs64(word);
+
+                       /* Clamp down to at most nbits.  */
+                       return MIN(result, nbits);
+               }
+       }
+
+       /* Find the first word with zeros in it.  */
+       for (; bpl < nbits; p++, result += bpl) {
                if (~*p)
                        break;
        }
 
-       CTASSERT(sizeof(unsigned long) <= sizeof(uint64_t));
-       result += ffs64(~(uint64_t)*p | (~0UL << MIN(nbits, bpl)));
-       return result;
+       /* Invert the bits and convert to 64 bits for ffs64.  */
+       word = ~(uint64_t)*p;
+
+       /* Find the first set bit in this word.  */
+       result += ffs64(word);
+
+       /* Clamp down to at most nbits.  */
+       return MIN(result, nbits);
+}
+
+static inline unsigned long
+find_first_zero_bit(const unsigned long *ptr, unsigned long nbits)
+{
+       return find_next_zero_bit(ptr, nbits, 0);
 }
 
 static inline unsigned



Home | Main Index | Thread Index | Old Index