blob: cbea5ef843aa560638da8b9a4c00683d86f8accb [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* find_next_bit.c: fallback find next bit implementation
2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
Yury Norov2c57a0e2015-04-16 12:43:13 -07006 * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease
7 * size and improve performance, 2015.
8 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14
15#include <linux/bitops.h>
Paul Gortmaker8bc3bcc2011-11-16 21:29:17 -050016#include <linux/export.h>
Yury Norov2c57a0e2015-04-16 12:43:13 -070017#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
Yury Norov2c57a0e2015-04-16 12:43:13 -070019#if !defined(find_next_bit) || !defined(find_next_zero_bit)
20
21/*
22 * This is a common helper function for find_next_bit and
23 * find_next_zero_bit. The difference is the "invert" argument, which
24 * is XORed with each fetched word before searching it for one bits.
25 */
26static unsigned long _find_next_bit(const unsigned long *addr,
27 unsigned long nbits, unsigned long start, unsigned long invert)
28{
29 unsigned long tmp;
30
31 if (!nbits || start >= nbits)
32 return nbits;
33
34 tmp = addr[start / BITS_PER_LONG] ^ invert;
35
36 /* Handle 1st word. */
37 tmp &= BITMAP_FIRST_WORD_MASK(start);
38 start = round_down(start, BITS_PER_LONG);
39
40 while (!tmp) {
41 start += BITS_PER_LONG;
42 if (start >= nbits)
43 return nbits;
44
45 tmp = addr[start / BITS_PER_LONG] ^ invert;
46 }
47
48 return min(start + __ffs(tmp), nbits);
49}
50#endif
Akinobu Mitac7f612c2006-03-26 01:39:11 -080051
Akinobu Mita19de85e2011-05-26 16:26:09 -070052#ifndef find_next_bit
Alexander van Heukelum64970b62008-03-11 16:17:19 +010053/*
54 * Find the next set bit in a memory region.
Akinobu Mitac7f612c2006-03-26 01:39:11 -080055 */
Thomas Gleixnerfee4b192008-04-29 12:01:02 +020056unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
57 unsigned long offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -070058{
Yury Norov2c57a0e2015-04-16 12:43:13 -070059 return _find_next_bit(addr, size, offset, 0UL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070060}
Thomas Gleixnerfee4b192008-04-29 12:01:02 +020061EXPORT_SYMBOL(find_next_bit);
Akinobu Mita19de85e2011-05-26 16:26:09 -070062#endif
Akinobu Mitac7f612c2006-03-26 01:39:11 -080063
Akinobu Mita19de85e2011-05-26 16:26:09 -070064#ifndef find_next_zero_bit
Thomas Gleixnerfee4b192008-04-29 12:01:02 +020065unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
66 unsigned long offset)
Akinobu Mitac7f612c2006-03-26 01:39:11 -080067{
Yury Norov2c57a0e2015-04-16 12:43:13 -070068 return _find_next_bit(addr, size, offset, ~0UL);
Akinobu Mitac7f612c2006-03-26 01:39:11 -080069}
Thomas Gleixnerfee4b192008-04-29 12:01:02 +020070EXPORT_SYMBOL(find_next_zero_bit);
Akinobu Mita19de85e2011-05-26 16:26:09 -070071#endif
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +020072
Akinobu Mita19de85e2011-05-26 16:26:09 -070073#ifndef find_first_bit
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +020074/*
75 * Find the first set bit in a memory region.
76 */
Thomas Gleixnerfee4b192008-04-29 12:01:02 +020077unsigned long find_first_bit(const unsigned long *addr, unsigned long size)
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +020078{
Yury Norov2c57a0e2015-04-16 12:43:13 -070079 unsigned long idx;
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +020080
Yury Norov2c57a0e2015-04-16 12:43:13 -070081 for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
82 if (addr[idx])
83 return min(idx * BITS_PER_LONG + __ffs(addr[idx]), size);
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +020084 }
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +020085
Yury Norov2c57a0e2015-04-16 12:43:13 -070086 return size;
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +020087}
Thomas Gleixnerfee4b192008-04-29 12:01:02 +020088EXPORT_SYMBOL(find_first_bit);
Akinobu Mita19de85e2011-05-26 16:26:09 -070089#endif
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +020090
Akinobu Mita19de85e2011-05-26 16:26:09 -070091#ifndef find_first_zero_bit
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +020092/*
93 * Find the first cleared bit in a memory region.
94 */
Thomas Gleixnerfee4b192008-04-29 12:01:02 +020095unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size)
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +020096{
Yury Norov2c57a0e2015-04-16 12:43:13 -070097 unsigned long idx;
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +020098
Yury Norov2c57a0e2015-04-16 12:43:13 -070099 for (idx = 0; idx * BITS_PER_LONG < size; idx++) {
100 if (addr[idx] != ~0UL)
101 return min(idx * BITS_PER_LONG + ffz(addr[idx]), size);
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +0200102 }
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +0200103
Yury Norov2c57a0e2015-04-16 12:43:13 -0700104 return size;
Alexander van Heukelum77b9bd92008-04-01 11:46:19 +0200105}
Thomas Gleixnerfee4b192008-04-29 12:01:02 +0200106EXPORT_SYMBOL(find_first_zero_bit);
Akinobu Mita19de85e2011-05-26 16:26:09 -0700107#endif
Akinobu Mita930ae742006-03-26 01:39:15 -0800108
109#ifdef __BIG_ENDIAN
110
111/* include/linux/byteorder does not support "unsigned long" type */
Akinobu Mita930ae742006-03-26 01:39:15 -0800112static inline unsigned long ext2_swab(const unsigned long y)
113{
114#if BITS_PER_LONG == 64
115 return (unsigned long) __swab64((u64) y);
116#elif BITS_PER_LONG == 32
117 return (unsigned long) __swab32((u32) y);
118#else
119#error BITS_PER_LONG not defined
120#endif
121}
122
Yury Norov2c57a0e2015-04-16 12:43:13 -0700123#if !defined(find_next_bit_le) || !defined(find_next_zero_bit_le)
124static unsigned long _find_next_bit_le(const unsigned long *addr,
125 unsigned long nbits, unsigned long start, unsigned long invert)
126{
127 unsigned long tmp;
128
129 if (!nbits || start >= nbits)
130 return nbits;
131
132 tmp = addr[start / BITS_PER_LONG] ^ invert;
133
134 /* Handle 1st word. */
135 tmp &= ext2_swab(BITMAP_FIRST_WORD_MASK(start));
136 start = round_down(start, BITS_PER_LONG);
137
138 while (!tmp) {
139 start += BITS_PER_LONG;
140 if (start >= nbits)
141 return nbits;
142
143 tmp = addr[start / BITS_PER_LONG] ^ invert;
144 }
145
146 return min(start + __ffs(ext2_swab(tmp)), nbits);
147}
148#endif
149
Akinobu Mita19de85e2011-05-26 16:26:09 -0700150#ifndef find_next_zero_bit_le
Akinobu Mitaa56560b2011-03-23 16:41:50 -0700151unsigned long find_next_zero_bit_le(const void *addr, unsigned
Akinobu Mita930ae742006-03-26 01:39:15 -0800152 long size, unsigned long offset)
153{
Yury Norov2c57a0e2015-04-16 12:43:13 -0700154 return _find_next_bit_le(addr, size, offset, ~0UL);
Akinobu Mita930ae742006-03-26 01:39:15 -0800155}
Akinobu Mitac4945b92011-03-23 16:41:47 -0700156EXPORT_SYMBOL(find_next_zero_bit_le);
Akinobu Mita19de85e2011-05-26 16:26:09 -0700157#endif
Akinobu Mita930ae742006-03-26 01:39:15 -0800158
Akinobu Mita19de85e2011-05-26 16:26:09 -0700159#ifndef find_next_bit_le
Akinobu Mitaa56560b2011-03-23 16:41:50 -0700160unsigned long find_next_bit_le(const void *addr, unsigned
Aneesh Kumar K.Vaa02ad62008-01-28 23:58:27 -0500161 long size, unsigned long offset)
162{
Yury Norov2c57a0e2015-04-16 12:43:13 -0700163 return _find_next_bit_le(addr, size, offset, 0UL);
Aneesh Kumar K.Vaa02ad62008-01-28 23:58:27 -0500164}
Akinobu Mitac4945b92011-03-23 16:41:47 -0700165EXPORT_SYMBOL(find_next_bit_le);
Akinobu Mita19de85e2011-05-26 16:26:09 -0700166#endif
Akinobu Mita06649962011-03-23 16:41:59 -0700167
Akinobu Mita930ae742006-03-26 01:39:15 -0800168#endif /* __BIG_ENDIAN */