Module Name:    src
Committed By:   riastradh
Date:           Mon Aug 27 14:46:23 UTC 2018

Modified Files:
        src/sys/external/bsd/common/include/linux: bitops.h

Log Message:
Give find_first/next_set/zero_bit a chance to work.

Self-review comments on the draft thrown together in a hurry two
weeks ago:

- I bet I screwed up for_each_set_bit or something.
- There might be several bits wrong in this __find_next_bit routine!
- for_each_set_bit is busted.
- Maybe I should test this stuff before I commit it.
- Hey, cool, buffer overflow here.
- What was I thinking.
- how did this even
- Was I drunk?  I'm never drunk.
- I don't even drink.
- It wasn't even that late at night...


To generate a diff of this commit:
cvs rdiff -u -r1.7 -r1.8 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.7 src/sys/external/bsd/common/include/linux/bitops.h:1.8
--- src/sys/external/bsd/common/include/linux/bitops.h:1.7	Mon Aug 27 13:54:37 2018
+++ src/sys/external/bsd/common/include/linux/bitops.h	Mon Aug 27 14:46:23 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: bitops.h,v 1.7 2018/08/27 13:54:37 riastradh Exp $	*/
+/*	$NetBSD: bitops.h,v 1.8 2018/08/27 14:46:23 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -188,7 +188,8 @@ __find_next_bit(const unsigned long *ptr
 {
 	const size_t bpl = (CHAR_BIT * sizeof(*ptr));
 	const unsigned long *p = ptr + startbit/bpl;
-	unsigned long result = rounddown(startbit, bpl);
+	size_t n = howmany(nbits, bpl);
+	unsigned long result;
 	uint64_t word;
 
 	/*
@@ -200,35 +201,42 @@ __find_next_bit(const unsigned long *ptr
 
 	/* Do we need to examine a partial starting word?  */
 	if (startbit % bpl) {
-		/* Are any of the first startbit%bpl bits zero?  */
-		if ((*p ^ toggle) & ~(~0UL << (startbit % bpl))) {
-			/* Toggle the bits and convert to 64 bits.  */
-			word = *p ^ toggle;
-
-			/* 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);
-		}
+		/* Toggle the bits and convert to 64 bits for ffs64.  */
+		word = *p ^ toggle;
+
+		/* Clear the low startbit%bpl bits.  */
+		word &= (~0UL << (startbit % bpl));
+
+		/* Are any of these bits set now?  */
+		if (word)
+			goto out;
+
+		/* Move past it.  */
+		p++;
+		n--;
 	}
 
-	/* Find the first word matching word.  */
-	for (; bpl < nbits; p++, result += bpl) {
-		if (*p ^ toggle)
-			break;
+	/* Find the first word with any bits set.  */
+	for (; n --> 0; p++) {
+		/* Toggle the bits and convert to 64 bits for ffs64. */
+		word = *p ^ toggle;
+
+		/* Are any of these bits set now?  */
+		if (word)
+			goto out;
 	}
 
-	/* Toggle the bits and convert to 64 bits for ffs64.  */
-	word = *p ^ toggle;
+	/* Nada.  */
+	return nbits;
+
+out:
+	/* Count how many words we've skipped.  */
+	result = bpl*(p - ptr);
 
-	/* Find the first set bit in this word.  */
-	result += ffs64(word);
+	/* Find the first set bit in this word, zero-based.  */
+	result += ffs64(word) - 1;
 
-	/* Clamp down to at most nbits.  */
+	/* We may have overshot, so clamp down to at most nbits.  */
 	return MIN(result, nbits);
 }
 

Reply via email to