Module Name: src
Committed By: riastradh
Date: Mon Aug 27 07:08:37 UTC 2018
Modified Files:
src/sys/external/bsd/common/include/linux: bitops.h
Log Message:
Implement find_next_zero_bit. Define find_first_zero_bit in terms of it.
To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/sys/external/bsd/common/include/linux/bitops.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/external/bsd/common/include/linux/bitops.h
diff -u src/sys/external/bsd/common/include/linux/bitops.h:1.4 src/sys/external/bsd/common/include/linux/bitops.h:1.5
--- src/sys/external/bsd/common/include/linux/bitops.h:1.4 Mon Aug 27 07:04:32 2018
+++ src/sys/external/bsd/common/include/linux/bitops.h Mon Aug 27 07:08:37 2018
@@ -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 @@ __test_and_change_bit(unsigned int bit,
}
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.
+ */
+
+ /* 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);
+ }
+ }
- for (p = ptr; bpl < nbits; nbits -= bpl, p++, result += bpl) {
+ /* 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