Whamcloud - gitweb
b=16098
[fs/lustre-release.git] / libcfs / libcfs / user-bitops.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see [sun.com URL with a
20  * copy of GPLv2].
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36 #ifndef __KERNEL__
37
38 #include <libcfs/libcfs.h>
39 #include <libcfs/user-bitops.h>
40
41 #define OFF_BY_START(start)     ((start)/BITS_PER_LONG)
42
43 unsigned long find_next_bit(unsigned long *addr,
44                             unsigned long size, unsigned long offset)
45 {
46         unsigned long *word, *last;
47         unsigned long first_bit, bit, base;
48
49         word = addr + OFF_BY_START(offset);
50         last = addr + OFF_BY_START(size-1);
51         first_bit = offset % BITS_PER_LONG;
52         base = offset - first_bit;
53
54         if (offset >= size)
55                 return size;
56         if (first_bit != 0) {
57                 int tmp = (*word++) & (~0UL << first_bit);
58                 bit = __ffs(tmp);
59                 if (bit < BITS_PER_LONG)
60                         goto found;
61                 word++;
62                 base += BITS_PER_LONG;
63         }
64         while (word <= last) {
65                 if (*word != 0UL) {
66                         bit = __ffs(*word);
67                         goto found;
68                 }
69                 word++;
70                 base += BITS_PER_LONG;
71         }
72         return size;
73 found:
74         return base + bit;
75 }
76
77 unsigned long find_next_zero_bit(unsigned long *addr,
78                                  unsigned long size, unsigned long offset)
79 {
80         unsigned long *word, *last;
81         unsigned long first_bit, bit, base;
82
83         word = addr + OFF_BY_START(offset);
84         last = addr + OFF_BY_START(size-1);
85         first_bit = offset % BITS_PER_LONG;
86         base = offset - first_bit;
87
88         if (offset >= size)
89                 return size;
90         if (first_bit != 0) {
91                 int tmp = (*word++) & (~0UL << first_bit);
92                 bit = __ffz(tmp);
93                 if (bit < BITS_PER_LONG)
94                         goto found;
95                 word++;
96                 base += BITS_PER_LONG;
97         }
98         while (word <= last) {
99                 if (*word != ~0UL) {
100                         bit = __ffz(*word);
101                         goto found;
102                 }
103                 word++;
104                 base += BITS_PER_LONG;
105         }
106         return size;
107 found:
108         return base + bit;
109 }
110
111 #endif