ronnie
2022-10-23 2280391f734323844a8b99655425ae0147571886
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
/* 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.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */
 
#include <linux/bitops.h>
#include <linux/bitmap.h>
#include <linux/kernel.h>
 
#if !defined(find_next_bit)
 
/*
 * This is a common helper function for find_next_bit and
 * find_next_zero_bit.  The difference is the "invert" argument, which
 * is XORed with each fetched word before searching it for one bits.
 */
static unsigned long _find_next_bit(const unsigned long *addr,
       unsigned long nbits, unsigned long start, unsigned long invert)
{
   unsigned long tmp;
 
   if (!nbits || start >= nbits)
       return nbits;
 
   tmp = addr[start / BITS_PER_LONG] ^ 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 = addr[start / BITS_PER_LONG] ^ 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, 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, size, offset, ~0UL);
}
#endif