blob: ee3df93ba69af9f5c17d811d06ac0b9a3de8c884 [file] [log] [blame]
Yury Norov8f6f19d2015-04-16 12:43:16 -07001/* bit search implementation
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
Yury Norov8f6f19d2015-04-16 12:43:16 -07006 * Copyright (C) 2008 IBM Corporation
7 * 'find_last_bit' is written by Rusty Russell <rusty@rustcorp.com.au>
8 * (Inspired by David Howell's find_next_bit implementation)
9 *
Yury Norov2c57a0e2015-04-16 12:43:13 -070010 * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease
11 * size and improve performance, 2015.
12 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version
16 * 2 of the License, or (at your option) any later version.
17 */
18
19#include <linux/bitops.h>
Yury Norov8f6f19d2015-04-16 12:43:16 -070020#include <linux/bitmap.h>
Paul Gortmaker8bc3bcc2011-11-16 21:29:17 -050021#include <linux/export.h>
Yury Norov2c57a0e2015-04-16 12:43:13 -070022#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070023
Clement Courbet0ade34c2018-02-06 15:38:34 -080024#if !defined(find_next_bit) || !defined(find_next_zero_bit) || \
25 !defined(find_next_and_bit)
Yury Norov2c57a0e2015-04-16 12:43:13 -070026
27/*
Clement Courbet0ade34c2018-02-06 15:38:34 -080028 * This is a common helper function for find_next_bit, find_next_zero_bit, and
29 * find_next_and_bit. The differences are:
30 * - The "invert" argument, which is XORed with each fetched word before
31 * searching it for one bits.
32 * - The optional "addr2", which is anded with "addr1" if present.
Yury Norov2c57a0e2015-04-16 12:43:13 -070033 */
Clement Courbet0ade34c2018-02-06 15:38:34 -080034static inline unsigned long _find_next_bit(const unsigned long *addr1,
35 const unsigned long *addr2, unsigned long nbits,
36 unsigned long start, unsigned long invert)
Yury Norov2c57a0e2015-04-16 12:43:13 -070037{
38 unsigned long tmp;
39
Matthew Wilcoxe4afd2e2017-02-24 15:00:58 -080040 if (unlikely(start >= nbits))
Yury Norov2c57a0e2015-04-16 12:43:13 -070041 return nbits;
42
Clement Courbet0ade34c2018-02-06 15:38:34 -080043 tmp = addr1[start / BITS_PER_LONG];
44 if (addr2)
45 tmp &= addr2[start / BITS_PER_LONG];
46 tmp ^= invert;
Yury Norov2c57a0e2015-04-16 12:43:13 -070047
48 /* Handle 1st word. */
49 tmp &= BITMAP_FIRST_WORD_MASK(start);
50 start = round_down(start, BITS_PER_LONG);
51
52 while (!tmp) {
53 start += BITS_PER_LONG;
54 if (start >= nbits)
55 return nbits;
56
Clement Courbet0ade34c2018-02-06 15:38:34 -080057 tmp = addr1[start / BITS_PER_LONG];
58 if (addr2)
59 tmp &= addr2[start / BITS_PER_LONG];
60 tmp ^= invert;
Yury Norov2c57a0e2015-04-16 12:43:13 -070061 }
62
63 return min(start + __ffs(tmp), nbits);
64}
65#endif
Akinobu Mitac7f612c2006-03-26 01:39:11 -080066
Akinobu Mita19de85e2011-05-26 16:26:09 -070067#ifndef find_next_bit
Alexander van Heukelum64970b62008-03-11 16:17:19 +010068/*
69 * Find the next set bit in a memory region.
Akinobu Mitac7f612c2006-03-26 01:39:11 -080070 */
Thomas Gleixnerfee4b192008-04-29 12:01:02 +020071unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
72 unsigned long offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -070073{
Clement Courbet0ade34c2018-02-06 15:38:34 -080074 return _find_next_bit(addr, NULL, size, offset, 0UL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070075}
Thomas Gleixnerfee4b192008-04-29 12:01:02 +020076EXPORT_SYMBOL(find_next_bit);
Akinobu Mita19de85e2011-05-26 16:26:09 -070077#endif
Akinobu Mitac7f612c2006-03-26 01:39:11 -080078
Akinobu Mita19de85e2011-05-26 16:26:09 -070079#ifndef find_next_zero_bit
Thomas Gleixnerfee4b192008-04-29 12:01:02 +020080unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
81 unsigned long offset)
Akinobu Mitac7f612c2006-03-26 01:39:11 -080082{
Clement Courbet0ade34c2018-02-06 15:38:34 -080083 return _find_next_bit(addr, NULL, size, offset, ~0UL);
Akinobu Mitac7f612c2006-03-26 01:39:11 -080084}
Thomas Gleixnerfee4b192008-04-29 12:01:02 +020085EXPORT_SYMBOL(find_next_zero_bit);
Akinobu Mita19de85e2011-05-26 16:26:09 -070086#endif
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +020087
Clement Courbet0ade34c2018-02-06 15:38:34 -080088#if !defined(find_next_and_bit)
89unsigned long find_next_and_bit(const unsigned long *addr1,
90 const unsigned long *addr2, unsigned long size,
91 unsigned long offset)
92{
93 return _find_next_bit(addr1, addr2, size, offset, 0UL);
94}
95EXPORT_SYMBOL(find_next_and_bit);
96#endif
97
Akinobu Mita19de85e2011-05-26 16:26:09 -070098#ifndef find_first_bit
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +020099/*
100 * Find the first set bit in a memory region.
101 */
Thomas Gleixnerfee4b192008-04-29 12:01:02 +0200102unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +0200103{
Yury Norov2c57a0e2015-04-16 12:43:13 -0700104 unsigned long idx;
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +0200105
Yury Norov2c57a0e2015-04-16 12:43:13 -0700106 for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
107 if (addr[idx])
108 return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size);
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +0200109 }
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +0200110
Yury Norov2c57a0e2015-04-16 12:43:13 -0700111 return size;
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +0200112}
Thomas Gleixnerfee4b192008-04-29 12:01:02 +0200113EXPORT_SYMBOL(find_first_bit);
Akinobu Mita19de85e2011-05-26 16:26:09 -0700114#endif
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +0200115
Akinobu Mita19de85e2011-05-26 16:26:09 -0700116#ifndef find_first_zero_bit
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +0200117/*
118 * Find the first cleared bit in a memory region.
119 */
Thomas Gleixnerfee4b192008-04-29 12:01:02 +0200120unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +0200121{
Yury Norov2c57a0e2015-04-16 12:43:13 -0700122 unsigned long idx;
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +0200123
Yury Norov2c57a0e2015-04-16 12:43:13 -0700124 for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
125 if (addr[idx] != ~0UL)
126 return min(idx * BITS_PER_LONG + ffz(addr[idx]), size);
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +0200127 }
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +0200128
Yury Norov2c57a0e2015-04-16 12:43:13 -0700129 return size;
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +0200130}
Thomas Gleixnerfee4b192008-04-29 12:01:02 +0200131EXPORT_SYMBOL(find_first_zero_bit);
Akinobu Mita19de85e2011-05-26 16:26:09 -0700132#endif
Akinobu Mita930ae742006-03-26 01:39:15 -0800133
Yury Norov8f6f19d2015-04-16 12:43:16 -0700134#ifndef find_last_bit
135unsigned long find_last_bit(const unsigned long *addr, unsigned long size)
136{
137 if (size) {
138 unsigned long val = BITMAP_LAST_WORD_MASK(size);
139 unsigned long idx = (size-1) / BITS_PER_LONG;
140
141 do {
142 val &= addr[idx];
143 if (val)
144 return idx * BITS_PER_LONG + __fls(val);
145
146 val = ~0ul;
147 } while (idx--);
148 }
149 return size;
150}
151EXPORT_SYMBOL(find_last_bit);
152#endif
153
Akinobu Mita930ae742006-03-26 01:39:15 -0800154#ifdef __BIG_ENDIAN
155
156/* include/linux/byteorder does not support "unsigned long" type */
Akinobu Mita930ae742006-03-26 01:39:15 -0800157static inline unsigned long ext2_swab(const unsigned long y)
158{
159#if BITS_PER_LONG == 64
160 return (unsigned long) __swab64((u64) y);
161#elif BITS_PER_LONG == 32
162 return (unsigned long) __swab32((u32) y);
163#else
164#error BITS_PER_LONG not defined
165#endif
166}
167
Yury Norov2c57a0e2015-04-16 12:43:13 -0700168#if !defined(find_next_bit_le) || !defined(find_next_zero_bit_le)
Clement Courbet0ade34c2018-02-06 15:38:34 -0800169static inline unsigned long _find_next_bit_le(const unsigned long *addr1,
170 const unsigned long *addr2, unsigned long nbits,
171 unsigned long start, unsigned long invert)
Yury Norov2c57a0e2015-04-16 12:43:13 -0700172{
173 unsigned long tmp;
174
Matthew Wilcoxe4afd2e2017-02-24 15:00:58 -0800175 if (unlikely(start >= nbits))
Yury Norov2c57a0e2015-04-16 12:43:13 -0700176 return nbits;
177
Clement Courbet0ade34c2018-02-06 15:38:34 -0800178 tmp = addr1[start / BITS_PER_LONG];
179 if (addr2)
180 tmp &= addr2[start / BITS_PER_LONG];
181 tmp ^= invert;
Yury Norov2c57a0e2015-04-16 12:43:13 -0700182
183 /* Handle 1st word. */
184 tmp &= ext2_swab(BITMAP_FIRST_WORD_MASK(start));
185 start = round_down(start, BITS_PER_LONG);
186
187 while (!tmp) {
188 start += BITS_PER_LONG;
189 if (start >= nbits)
190 return nbits;
191
Clement Courbet0ade34c2018-02-06 15:38:34 -0800192 tmp = addr1[start / BITS_PER_LONG];
193 if (addr2)
194 tmp &= addr2[start / BITS_PER_LONG];
195 tmp ^= invert;
Yury Norov2c57a0e2015-04-16 12:43:13 -0700196 }
197
198 return min(start + __ffs(ext2_swab(tmp)), nbits);
199}
200#endif
201
Akinobu Mita19de85e2011-05-26 16:26:09 -0700202#ifndef find_next_zero_bit_le
Akinobu Mitaa56560b2011-03-23 16:41:50 -0700203unsigned long find_next_zero_bit_le(const void *addr, unsigned
Akinobu Mita930ae742006-03-26 01:39:15 -0800204 long size, unsigned long offset)
205{
Clement Courbet0ade34c2018-02-06 15:38:34 -0800206 return _find_next_bit_le(addr, NULL, size, offset, ~0UL);
Akinobu Mita930ae742006-03-26 01:39:15 -0800207}
Akinobu Mitac4945b92011-03-23 16:41:47 -0700208EXPORT_SYMBOL(find_next_zero_bit_le);
Akinobu Mita19de85e2011-05-26 16:26:09 -0700209#endif
Akinobu Mita930ae742006-03-26 01:39:15 -0800210
Akinobu Mita19de85e2011-05-26 16:26:09 -0700211#ifndef find_next_bit_le
Akinobu Mitaa56560b2011-03-23 16:41:50 -0700212unsigned long find_next_bit_le(const void *addr, unsigned
Aneesh Kumar K.Vaa02ad62008-01-28 23:58:27 -0500213 long size, unsigned long offset)
214{
Clement Courbet0ade34c2018-02-06 15:38:34 -0800215 return _find_next_bit_le(addr, NULL, size, offset, 0UL);
Aneesh Kumar K.Vaa02ad62008-01-28 23:58:27 -0500216}
Akinobu Mitac4945b92011-03-23 16:41:47 -0700217EXPORT_SYMBOL(find_next_bit_le);
Akinobu Mita19de85e2011-05-26 16:26:09 -0700218#endif
Akinobu Mita06649962011-03-23 16:41:59 -0700219
Akinobu Mita930ae742006-03-26 01:39:15 -0800220#endif /* __BIG_ENDIAN */