hc
2024-03-26 e9199a72d842cbda78ac614eee5db7cdaa6f2530
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// SPDX-License-Identifier: GPL-2.0-or-later
/* bit search implementation
 *
 * Copied from lib/find_bit.c to tools/lib/find_bit.c
 *
 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 *
 * Copyright (C) 2008 IBM Corporation
 * 'find_last_bit' is written by Rusty Russell <rusty@rustcorp.com.au>
 * (Inspired by David Howell's find_next_bit implementation)
 *
 * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease
 * size and improve performance, 2015.
 */
 
#include <linux/bitops.h>
#include <linux/bitmap.h>
#include <linux/kernel.h>
 
#if !defined(find_next_bit) || !defined(find_next_zero_bit) || \
       !defined(find_next_and_bit)
 
/*
 * This is a common helper function for find_next_bit, find_next_zero_bit, and
 * find_next_and_bit. The differences are:
 *  - The "invert" argument, which is XORed with each fetched word before
 *    searching it for one bits.
 *  - The optional "addr2", which is anded with "addr1" if present.
 */
static inline unsigned long _find_next_bit(const unsigned long *addr1,
       const unsigned long *addr2, unsigned long nbits,
       unsigned long start, unsigned long invert)
{
   unsigned long tmp;
 
   if (unlikely(start >= nbits))
       return nbits;
 
   tmp = addr1[start / BITS_PER_LONG];
   if (addr2)
       tmp &= addr2[start / BITS_PER_LONG];
   tmp ^= invert;
 
   /* Handle 1st word. */
   tmp &= BITMAP_FIRST_WORD_MASK(start);
   start = round_down(start, BITS_PER_LONG);
 
   while (!tmp) {
       start += BITS_PER_LONG;
       if (start >= nbits)
           return nbits;
 
       tmp = addr1[start / BITS_PER_LONG];
       if (addr2)
           tmp &= addr2[start / BITS_PER_LONG];
       tmp ^= invert;
   }
 
   return min(start + __ffs(tmp), nbits);
}
#endif
 
#ifndef find_next_bit
/*
 * Find the next set bit in a memory region.
 */
unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
               unsigned long offset)
{
   return _find_next_bit(addr, NULL, size, offset, 0UL);
}
#endif
 
#ifndef find_first_bit
/*
 * Find the first set bit in a memory region.
 */
unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
{
   unsigned long idx;
 
   for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
       if (addr[idx])
           return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size);
   }
 
   return size;
}
#endif
 
#ifndef find_first_zero_bit
/*
 * Find the first cleared bit in a memory region.
 */
unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
{
   unsigned long idx;
 
   for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
       if (addr[idx] != ~0UL)
           return min(idx * BITS_PER_LONG + ffz(addr[idx]), size);
   }
 
   return size;
}
#endif
 
#ifndef find_next_zero_bit
unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
                unsigned long offset)
{
   return _find_next_bit(addr, NULL, size, offset, ~0UL);
}
#endif
 
#ifndef find_next_and_bit
unsigned long find_next_and_bit(const unsigned long *addr1,
       const unsigned long *addr2, unsigned long size,
       unsigned long offset)
{
   return _find_next_bit(addr1, addr2, size, offset, 0UL);
}
#endif