bitops.h revision 277396
1178620Smarcel/*-
2178620Smarcel * Copyright (c) 2010 Isilon Systems, Inc.
3178620Smarcel * Copyright (c) 2010 iX Systems, Inc.
4178620Smarcel * Copyright (c) 2010 Panasas, Inc.
5178620Smarcel * Copyright (c) 2013, 2014 Mellanox Technologies, Ltd.
6178620Smarcel * All rights reserved.
7178620Smarcel *
8178620Smarcel * Redistribution and use in source and binary forms, with or without
9178620Smarcel * modification, are permitted provided that the following conditions
10178620Smarcel * are met:
11178620Smarcel * 1. Redistributions of source code must retain the above copyright
12178620Smarcel *    notice unmodified, this list of conditions, and the following
13178620Smarcel *    disclaimer.
14178620Smarcel * 2. Redistributions in binary form must reproduce the above copyright
15178620Smarcel *    notice, this list of conditions and the following disclaimer in the
16178620Smarcel *    documentation and/or other materials provided with the distribution.
17178620Smarcel *
18178620Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19178620Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20178620Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21178620Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22178620Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23178620Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24178620Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25178620Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26178620Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27178620Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28178620Smarcel */
29178620Smarcel#ifndef	_LINUX_BITOPS_H_
30178620Smarcel#define	_LINUX_BITOPS_H_
31178620Smarcel
32178620Smarcel#ifdef __LP64__
33178620Smarcel#define	BITS_PER_LONG		64
34178620Smarcel#else
35178620Smarcel#define	BITS_PER_LONG		32
36178620Smarcel#endif
37178620Smarcel#define	BIT_MASK(n)		(~0UL >> (BITS_PER_LONG - (n)))
38178620Smarcel#define	BITS_TO_LONGS(n)	howmany((n), BITS_PER_LONG)
39178620Smarcel#define BIT_WORD(nr)		((nr) / BITS_PER_LONG)
40178620Smarcel
41178620Smarcel#define BITS_PER_BYTE           8
42178620Smarcel
43178620Smarcelstatic inline int
44178620Smarcel__ffs(int mask)
45178620Smarcel{
46178620Smarcel	return (ffs(mask) - 1);
47178620Smarcel}
48178620Smarcel
49178620Smarcelstatic inline int
50178620Smarcel__fls(int mask)
51178620Smarcel{
52178620Smarcel	return (fls(mask) - 1);
53178620Smarcel}
54178620Smarcel
55178620Smarcelstatic inline int
56178620Smarcel__ffsl(long mask)
57178620Smarcel{
58178620Smarcel	return (ffsl(mask) - 1);
59178620Smarcel}
60178620Smarcel
61178620Smarcelstatic inline int
62178620Smarcel__flsl(long mask)
63178620Smarcel{
64178620Smarcel	return (flsl(mask) - 1);
65178620Smarcel}
66178620Smarcel
67178620Smarcel
68178620Smarcel#define	ffz(mask)	__ffs(~(mask))
69178620Smarcel
70178620Smarcelstatic inline int get_count_order(unsigned int count)
71178620Smarcel{
72178620Smarcel        int order;
73178620Smarcel
74178620Smarcel        order = fls(count) - 1;
75178620Smarcel        if (count & (count - 1))
76178620Smarcel                order++;
77178620Smarcel        return order;
78178620Smarcel}
79178620Smarcel
80178620Smarcelstatic inline unsigned long
81178620Smarcelfind_first_bit(unsigned long *addr, unsigned long size)
82178620Smarcel{
83178620Smarcel	long mask;
84178620Smarcel	int bit;
85178620Smarcel
86178620Smarcel	for (bit = 0; size >= BITS_PER_LONG;
87178620Smarcel	    size -= BITS_PER_LONG, bit += BITS_PER_LONG, addr++) {
88178620Smarcel		if (*addr == 0)
89178620Smarcel			continue;
90178620Smarcel		return (bit + __ffsl(*addr));
91178620Smarcel	}
92178620Smarcel	if (size) {
93178620Smarcel		mask = (*addr) & BIT_MASK(size);
94178620Smarcel		if (mask)
95178620Smarcel			bit += __ffsl(mask);
96178620Smarcel		else
97178620Smarcel			bit += size;
98178620Smarcel	}
99178620Smarcel	return (bit);
100178620Smarcel}
101178620Smarcel
102178620Smarcelstatic inline unsigned long
103178620Smarcelfind_first_zero_bit(unsigned long *addr, unsigned long size)
104178620Smarcel{
105178620Smarcel	long mask;
106178620Smarcel	int bit;
107178620Smarcel
108178620Smarcel	for (bit = 0; size >= BITS_PER_LONG;
109178620Smarcel	    size -= BITS_PER_LONG, bit += BITS_PER_LONG, addr++) {
110178620Smarcel		if (~(*addr) == 0)
111178620Smarcel			continue;
112178620Smarcel		return (bit + __ffsl(~(*addr)));
113178620Smarcel	}
114178620Smarcel	if (size) {
115178620Smarcel		mask = ~(*addr) & BIT_MASK(size);
116178620Smarcel		if (mask)
117178620Smarcel			bit += __ffsl(mask);
118178620Smarcel		else
119178620Smarcel			bit += size;
120178620Smarcel	}
121178620Smarcel	return (bit);
122178620Smarcel}
123178620Smarcel
124178620Smarcelstatic inline unsigned long
125178620Smarcelfind_last_bit(unsigned long *addr, unsigned long size)
126178620Smarcel{
127178620Smarcel	long mask;
128178620Smarcel	int offs;
129178620Smarcel	int bit;
130178620Smarcel	int pos;
131178620Smarcel
132178620Smarcel	pos = size / BITS_PER_LONG;
133178620Smarcel	offs = size % BITS_PER_LONG;
134178620Smarcel	bit = BITS_PER_LONG * pos;
135178620Smarcel	addr += pos;
136178620Smarcel	if (offs) {
137178620Smarcel		mask = (*addr) & BIT_MASK(offs);
138178620Smarcel		if (mask)
139178620Smarcel			return (bit + __flsl(mask));
140178620Smarcel	}
141178620Smarcel	while (--pos) {
142178620Smarcel		addr--;
143178620Smarcel		bit -= BITS_PER_LONG;
144178620Smarcel		if (*addr)
145178620Smarcel			return (bit + __flsl(mask));
146178620Smarcel	}
147178620Smarcel	return (size);
148178620Smarcel}
149178620Smarcel
150178620Smarcelstatic inline unsigned long
151178620Smarcelfind_next_bit(unsigned long *addr, unsigned long size, unsigned long offset)
152178620Smarcel{
153178620Smarcel	long mask;
154178620Smarcel	int offs;
155178620Smarcel	int bit;
156178620Smarcel	int pos;
157178620Smarcel
158178620Smarcel	if (offset >= size)
159178620Smarcel		return (size);
160178620Smarcel	pos = offset / BITS_PER_LONG;
161178620Smarcel	offs = offset % BITS_PER_LONG;
162178620Smarcel	bit = BITS_PER_LONG * pos;
163178620Smarcel	addr += pos;
164178620Smarcel	if (offs) {
165178620Smarcel		mask = (*addr) & ~BIT_MASK(offs);
166178620Smarcel		if (mask)
167178620Smarcel			return (bit + __ffsl(mask));
168178620Smarcel		bit += BITS_PER_LONG;
169178620Smarcel		addr++;
170178620Smarcel	}
171178620Smarcel	for (size -= bit; size >= BITS_PER_LONG;
172178620Smarcel	    size -= BITS_PER_LONG, bit += BITS_PER_LONG, addr++) {
173178620Smarcel		if (*addr == 0)
174178620Smarcel			continue;
175178620Smarcel		return (bit + __ffsl(*addr));
176178620Smarcel	}
177178620Smarcel	if (size) {
178178620Smarcel		mask = (*addr) & BIT_MASK(size);
179178620Smarcel		if (mask)
180178620Smarcel			bit += __ffsl(mask);
181178620Smarcel		else
182178620Smarcel			bit += size;
183178620Smarcel	}
184178620Smarcel	return (bit);
185178620Smarcel}
186178620Smarcel
187178620Smarcelstatic inline unsigned long
188178620Smarcelfind_next_zero_bit(unsigned long *addr, unsigned long size,
189178620Smarcel    unsigned long offset)
190178620Smarcel{
191178620Smarcel	long mask;
192178620Smarcel	int offs;
193178620Smarcel	int bit;
194178620Smarcel	int pos;
195178620Smarcel
196178620Smarcel	if (offset >= size)
197178620Smarcel		return (size);
198178620Smarcel	pos = offset / BITS_PER_LONG;
199178620Smarcel	offs = offset % BITS_PER_LONG;
200178620Smarcel	bit = BITS_PER_LONG * pos;
201178620Smarcel	addr += pos;
202178620Smarcel	if (offs) {
203178620Smarcel		mask = ~(*addr) & ~BIT_MASK(offs);
204178620Smarcel		if (mask)
205178620Smarcel			return (bit + __ffsl(mask));
206178620Smarcel		bit += BITS_PER_LONG;
207178620Smarcel		addr++;
208178620Smarcel	}
209178620Smarcel	for (size -= bit; size >= BITS_PER_LONG;
210178620Smarcel	    size -= BITS_PER_LONG, bit += BITS_PER_LONG, addr++) {
211178620Smarcel		if (~(*addr) == 0)
212178620Smarcel			continue;
213178620Smarcel		return (bit + __ffsl(~(*addr)));
214178620Smarcel	}
215178620Smarcel	if (size) {
216178620Smarcel		mask = ~(*addr) & BIT_MASK(size);
217178620Smarcel		if (mask)
218178620Smarcel			bit += __ffsl(mask);
219178620Smarcel		else
220178620Smarcel			bit += size;
221178620Smarcel	}
222178620Smarcel	return (bit);
223178620Smarcel}
224178620Smarcel
225178620Smarcelstatic inline void
226178620Smarcelbitmap_zero(unsigned long *addr, int size)
227178620Smarcel{
228178620Smarcel	int len;
229178620Smarcel
230178620Smarcel	len = BITS_TO_LONGS(size) * sizeof(long);
231178620Smarcel	memset(addr, 0, len);
232178620Smarcel}
233178620Smarcel
234178620Smarcelstatic inline void
235178620Smarcelbitmap_fill(unsigned long *addr, int size)
236178620Smarcel{
237178620Smarcel	int tail;
238178620Smarcel	int len;
239178620Smarcel
240178620Smarcel	len = (size / BITS_PER_LONG) * sizeof(long);
241178620Smarcel	memset(addr, 0xff, len);
242178620Smarcel	tail = size & (BITS_PER_LONG - 1);
243178620Smarcel	if (tail)
244178620Smarcel		addr[size / BITS_PER_LONG] = BIT_MASK(tail);
245178620Smarcel}
246178620Smarcel
247178620Smarcelstatic inline int
248178620Smarcelbitmap_full(unsigned long *addr, int size)
249178620Smarcel{
250178620Smarcel	long mask;
251178620Smarcel	int tail;
252178620Smarcel	int len;
253178620Smarcel	int i;
254178620Smarcel
255178620Smarcel	len = size / BITS_PER_LONG;
256178620Smarcel	for (i = 0; i < len; i++)
257178620Smarcel		if (addr[i] != ~0UL)
258178620Smarcel			return (0);
259178620Smarcel	tail = size & (BITS_PER_LONG - 1);
260178620Smarcel	if (tail) {
261178620Smarcel		mask = BIT_MASK(tail);
262178620Smarcel		if ((addr[i] & mask) != mask)
263178620Smarcel			return (0);
264178620Smarcel	}
265178620Smarcel	return (1);
266178620Smarcel}
267178620Smarcel
268178620Smarcelstatic inline int
269178620Smarcelbitmap_empty(unsigned long *addr, int size)
270178620Smarcel{
271178620Smarcel	long mask;
272178620Smarcel	int tail;
273178620Smarcel	int len;
274178620Smarcel	int i;
275178620Smarcel
276178620Smarcel	len = size / BITS_PER_LONG;
277178620Smarcel	for (i = 0; i < len; i++)
278178620Smarcel		if (addr[i] != 0)
279178620Smarcel			return (0);
280178620Smarcel	tail = size & (BITS_PER_LONG - 1);
281178620Smarcel	if (tail) {
282178620Smarcel		mask = BIT_MASK(tail);
283178620Smarcel		if ((addr[i] & mask) != 0)
284178620Smarcel			return (0);
285178620Smarcel	}
286178620Smarcel	return (1);
287178620Smarcel}
288178620Smarcel
289178620Smarcel#define	NBLONG	(NBBY * sizeof(long))
290178620Smarcel
291178620Smarcel#define	__set_bit(i, a)							\
292178620Smarcel    atomic_set_long(&((volatile long *)(a))[(i)/NBLONG], 1UL << ((i) % NBLONG))
293178620Smarcel
294178620Smarcel#define	set_bit(i, a)							\
295178620Smarcel    atomic_set_long(&((volatile long *)(a))[(i)/NBLONG], 1UL << ((i) % NBLONG))
296178620Smarcel
297178620Smarcel#define	__clear_bit(i, a)						\
298178620Smarcel    atomic_clear_long(&((volatile long *)(a))[(i)/NBLONG], 1UL << ((i) % NBLONG))
299178620Smarcel
300178620Smarcel#define	clear_bit(i, a)							\
301178620Smarcel    atomic_clear_long(&((volatile long *)(a))[(i)/NBLONG], 1UL << ((i) % NBLONG))
302178620Smarcel
303178620Smarcel#define	test_bit(i, a)							\
304178620Smarcel    !!(atomic_load_acq_long(&((volatile long *)(a))[(i)/NBLONG]) &	\
305178620Smarcel    (1UL << ((i) % NBLONG)))
306178620Smarcel
307178620Smarcelstatic inline long
308test_and_clear_bit(long bit, long *var)
309{
310	long val;
311
312	var += bit / (sizeof(long) * NBBY);
313	bit %= sizeof(long) * NBBY;
314	bit = (1UL << bit);
315	do {
316		val = *(volatile long *)var;
317	} while (atomic_cmpset_long(var, val, val & ~bit) == 0);
318
319	return !!(val & bit);
320}
321
322static inline long
323test_and_set_bit(long bit, long *var)
324{
325	long val;
326
327	var += bit / (sizeof(long) * NBBY);
328	bit %= sizeof(long) * NBBY;
329	bit = (1UL << bit);
330	do {
331		val = *(volatile long *)var;
332	} while (atomic_cmpset_long(var, val, val | bit) == 0);
333
334	return !!(val & bit);
335}
336
337
338#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
339#define BITMAP_LAST_WORD_MASK(nbits)                                    \
340(                                                                       \
341        ((nbits) % BITS_PER_LONG) ?                                     \
342                (1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL               \
343)
344
345
346static inline void
347bitmap_set(unsigned long *map, int start, int nr)
348{
349	unsigned long *p = map + BIT_WORD(start);
350	const int size = start + nr;
351	int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
352	unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
353
354	while (nr - bits_to_set >= 0) {
355		*p |= mask_to_set;
356		nr -= bits_to_set;
357		bits_to_set = BITS_PER_LONG;
358		mask_to_set = ~0UL;
359		p++;
360	}
361	if (nr) {
362		mask_to_set &= BITMAP_LAST_WORD_MASK(size);
363		*p |= mask_to_set;
364	}
365}
366
367static inline void
368bitmap_clear(unsigned long *map, int start, int nr)
369{
370	unsigned long *p = map + BIT_WORD(start);
371	const int size = start + nr;
372	int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
373	unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
374
375	while (nr - bits_to_clear >= 0) {
376		*p &= ~mask_to_clear;
377		nr -= bits_to_clear;
378		bits_to_clear = BITS_PER_LONG;
379		mask_to_clear = ~0UL;
380		p++;
381	}
382	if (nr) {
383		mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
384		*p &= ~mask_to_clear;
385	}
386}
387
388enum {
389        REG_OP_ISFREE,          /* true if region is all zero bits */
390        REG_OP_ALLOC,           /* set all bits in region */
391        REG_OP_RELEASE,         /* clear all bits in region */
392};
393
394static int __reg_op(unsigned long *bitmap, int pos, int order, int reg_op)
395{
396        int nbits_reg;          /* number of bits in region */
397        int index;              /* index first long of region in bitmap */
398        int offset;             /* bit offset region in bitmap[index] */
399        int nlongs_reg;         /* num longs spanned by region in bitmap */
400        int nbitsinlong;        /* num bits of region in each spanned long */
401        unsigned long mask;     /* bitmask for one long of region */
402        int i;                  /* scans bitmap by longs */
403        int ret = 0;            /* return value */
404
405        /*
406         * Either nlongs_reg == 1 (for small orders that fit in one long)
407         * or (offset == 0 && mask == ~0UL) (for larger multiword orders.)
408         */
409        nbits_reg = 1 << order;
410        index = pos / BITS_PER_LONG;
411        offset = pos - (index * BITS_PER_LONG);
412        nlongs_reg = BITS_TO_LONGS(nbits_reg);
413        nbitsinlong = min(nbits_reg,  BITS_PER_LONG);
414
415        /*
416         * Can't do "mask = (1UL << nbitsinlong) - 1", as that
417         * overflows if nbitsinlong == BITS_PER_LONG.
418         */
419        mask = (1UL << (nbitsinlong - 1));
420        mask += mask - 1;
421        mask <<= offset;
422
423        switch (reg_op) {
424        case REG_OP_ISFREE:
425                for (i = 0; i < nlongs_reg; i++) {
426                        if (bitmap[index + i] & mask)
427                                goto done;
428                }
429                ret = 1;        /* all bits in region free (zero) */
430                break;
431
432        case REG_OP_ALLOC:
433                for (i = 0; i < nlongs_reg; i++)
434                        bitmap[index + i] |= mask;
435                break;
436
437        case REG_OP_RELEASE:
438                for (i = 0; i < nlongs_reg; i++)
439                        bitmap[index + i] &= ~mask;
440                break;
441        }
442done:
443        return ret;
444}
445
446/**
447 * bitmap_find_free_region - find a contiguous aligned mem region
448 *      @bitmap: array of unsigned longs corresponding to the bitmap
449 *      @bits: number of bits in the bitmap
450 *      @order: region size (log base 2 of number of bits) to find
451 *
452 * Find a region of free (zero) bits in a @bitmap of @bits bits and
453 * allocate them (set them to one).  Only consider regions of length
454 * a power (@order) of two, aligned to that power of two, which
455 * makes the search algorithm much faster.
456 *
457 * Return the bit offset in bitmap of the allocated region,
458 * or -errno on failure.
459 */
460static inline int
461bitmap_find_free_region(unsigned long *bitmap, int bits, int order)
462{
463        int pos, end;           /* scans bitmap by regions of size order */
464
465        for (pos = 0 ; (end = pos + (1 << order)) <= bits; pos = end) {
466                if (!__reg_op(bitmap, pos, order, REG_OP_ISFREE))
467                        continue;
468                __reg_op(bitmap, pos, order, REG_OP_ALLOC);
469                return pos;
470        }
471        return -ENOMEM;
472}
473
474/**
475 * bitmap_allocate_region - allocate bitmap region
476 *      @bitmap: array of unsigned longs corresponding to the bitmap
477 *      @pos: beginning of bit region to allocate
478 *      @order: region size (log base 2 of number of bits) to allocate
479 *
480 * Allocate (set bits in) a specified region of a bitmap.
481 *
482 * Return 0 on success, or %-EBUSY if specified region wasn't
483 * free (not all bits were zero).
484 */
485
486static inline int
487bitmap_allocate_region(unsigned long *bitmap, int pos, int order)
488{
489        if (!__reg_op(bitmap, pos, order, REG_OP_ISFREE))
490                return -EBUSY;
491        __reg_op(bitmap, pos, order, REG_OP_ALLOC);
492        return 0;
493}
494
495/**
496 * bitmap_release_region - release allocated bitmap region
497 *      @bitmap: array of unsigned longs corresponding to the bitmap
498 *      @pos: beginning of bit region to release
499 *      @order: region size (log base 2 of number of bits) to release
500 *
501 * This is the complement to __bitmap_find_free_region() and releases
502 * the found region (by clearing it in the bitmap).
503 *
504 * No return value.
505 */
506static inline void
507bitmap_release_region(unsigned long *bitmap, int pos, int order)
508{
509        __reg_op(bitmap, pos, order, REG_OP_RELEASE);
510}
511
512
513#define for_each_set_bit(bit, addr, size) \
514	for ((bit) = find_first_bit((addr), (size));		\
515	     (bit) < (size);					\
516	     (bit) = find_next_bit((addr), (size), (bit) + 1))
517
518#endif	/* _LINUX_BITOPS_H_ */
519