Whamcloud - gitweb
e98e2d263c964f3e6f524c665bd4e0fd29f08b79
[tools/e2fsprogs.git] / lib / ext2fs / bitops.h
1 /*
2  * bitops.h --- Bitmap frobbing code.  The byte swapping routines are
3  *      also included here.
4  * 
5  * Copyright (C) 1993, 1994, 1995 Theodore Ts'o.  This file may be
6  * redistributed under the terms of the GNU Public License.
7  * 
8  * Taken from <asm/bitops.h>, Copyright 1992, Linus Torvalds.
9  */
10
11
12 extern int ext2fs_set_bit(int nr,void * addr);
13 extern int ext2fs_clear_bit(int nr, void * addr);
14 extern int ext2fs_test_bit(int nr, const void * addr);
15 extern __u16 ext2fs_swab16(__u16 val);
16 extern __u32 ext2fs_swab32(__u32 val);
17
18 /*
19  * EXT2FS bitmap manipulation routines.
20  */
21
22 /* Support for sending warning messages from the inline subroutines */
23 extern const char *ext2fs_block_string;
24 extern const char *ext2fs_inode_string;
25 extern const char *ext2fs_mark_string;
26 extern const char *ext2fs_unmark_string;
27 extern const char *ext2fs_test_string;
28 extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
29                                const char *description);
30
31 extern void ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
32 extern void ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
33                                        blk_t block);
34 extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
35
36 extern void ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ino_t inode);
37 extern void ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
38                                        ino_t inode);
39 extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ino_t inode);
40
41 extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
42                                           blk_t block);
43 extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
44                                             blk_t block);
45 extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
46                                          blk_t block);
47
48 extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
49                                           ino_t inode);
50 extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
51                                             ino_t inode);
52 extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
53                                          ino_t inode);
54 extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
55 extern blk_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
56 extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
57 extern blk_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
58
59 /*
60  * The inline routines themselves...
61  * 
62  * If NO_INLINE_FUNCS is defined, then we won't try to do inline
63  * functions at all; they will be included as normal functions in
64  * inline.c
65  */
66 #ifdef NO_INLINE_FUNCS
67 #if (defined(__i386__) || defined(__i486__) || defined(__i586__) || \
68      defined(__mc68000__) || defined(__sparc__))
69         /* This prevents bitops.c from trying to include the C */
70         /* function version of these functions */
71 #define _EXT2_HAVE_ASM_BITOPS_
72 #endif
73 #endif /* NO_INLINE_FUNCS */
74
75 #if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS))
76 #ifdef INCLUDE_INLINE_FUNCS
77 #define _INLINE_ extern
78 #else
79 #define _INLINE_ extern __inline__
80 #endif
81
82 #if (defined(__i386__) || defined(__i486__) || defined(__i586__))
83
84 #define _EXT2_HAVE_ASM_BITOPS_
85         
86 /*
87  * These are done by inline assembly for speed reasons.....
88  *
89  * All bitoperations return 0 if the bit was cleared before the
90  * operation and != 0 if it was not.  Bit 0 is the LSB of addr; bit 32
91  * is the LSB of (addr+1).
92  */
93
94 /*
95  * Some hacks to defeat gcc over-optimizations..
96  */
97 struct __dummy_h { unsigned long a[100]; };
98 #define EXT2FS_ADDR (*(struct __dummy_h *) addr)
99 #define EXT2FS_CONST_ADDR (*(const struct __dummy_h *) addr)    
100
101 _INLINE_ int ext2fs_set_bit(int nr, void * addr)
102 {
103         int oldbit;
104
105         __asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0"
106                 :"=r" (oldbit),"=m" (EXT2FS_ADDR)
107                 :"r" (nr));
108         return oldbit;
109 }
110
111 _INLINE_ int ext2fs_clear_bit(int nr, void * addr)
112 {
113         int oldbit;
114
115         __asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0"
116                 :"=r" (oldbit),"=m" (EXT2FS_ADDR)
117                 :"r" (nr));
118         return oldbit;
119 }
120
121 _INLINE_ int ext2fs_test_bit(int nr, const void * addr)
122 {
123         int oldbit;
124
125         __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
126                 :"=r" (oldbit)
127                 :"m" (EXT2FS_CONST_ADDR),"r" (nr));
128         return oldbit;
129 }
130
131 #undef EXT2FS_ADDR
132
133 #endif  /* i386 */
134
135 #ifdef __mc68000__
136
137 #define _EXT2_HAVE_ASM_BITOPS_
138
139 _INLINE_ int ext2fs_set_bit(int nr,void * addr)
140 {
141         char retval;
142
143         __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0"
144              : "=d" (retval) : "d" (nr^7), "a" (addr));
145
146         return retval;
147 }
148
149 _INLINE_ int ext2fs_clear_bit(int nr, void * addr)
150 {
151         char retval;
152
153         __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0"
154              : "=d" (retval) : "d" (nr^7), "a" (addr));
155
156         return retval;
157 }
158
159 _INLINE_ int ext2fs_test_bit(int nr, const void * addr)
160 {
161         char retval;
162
163         __asm__ __volatile__ ("bftst %2@{%1:#1}; sne %0"
164              : "=d" (retval) : "d" (nr^7), "a" (addr));
165
166         return retval;
167 }
168
169 #endif /* __mc68000__ */
170
171 #ifdef __sparc__
172
173 #define _EXT2_HAVE_ASM_BITOPS_
174
175 _INLINE_ int ext2fs_set_bit(int nr, void *addr)
176 {
177         int             mask, retval;
178         unsigned long   *ADDR = (unsigned long *) addr;
179
180         ADDR += nr >> 5;
181         mask = 1 << (nr & 31);
182         retval = ((mask & *ADDR) != 0);
183         *ADDR |= mask;
184         return retval;
185 }
186
187 _INLINE_ int ext2fs_clear_bit(int nr, void *addr)
188 {
189         int             mask, retval;
190         unsigned long   *ADDR = (unsigned long *) addr;
191
192         ADDR += nr >> 5;
193         mask = 1 << (nr & 31);
194         retval = ((mask & *ADDR) != 0);
195         *ADDR &= ~mask;
196         return retval;
197 }
198
199 _INLINE_ int ext2fs_test_bit(int nr, const void *addr)
200 {
201         int                     mask;
202         const unsigned long     *ADDR = (const unsigned long *) addr;
203
204         ADDR += nr >> 5;
205         mask = 1 << (nr & 31);
206         return ((mask & *ADDR) != 0);
207 }
208
209 #endif /* __sparc__ */
210
211 #ifndef _EXT2_HAVE_ASM_SWAB
212
213 _INLINE_ __u16 ext2fs_swab16(__u16 val)
214 {
215         return (val >> 8) | (val << 8);
216 }
217
218 _INLINE_ __u32 ext2fs_swab32(__u32 val)
219 {
220         return ((val>>24) | ((val>>8)&0xFF00) |
221                 ((val<<8)&0xFF0000) | (val<<24));
222 }
223
224 #endif /* !_EXT2_HAVE_ASM_SWAB */
225
226 _INLINE_ void ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
227                                        blk_t block)
228 {
229         if ((block < bitmap->start) || (block > bitmap->end)) {
230                 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
231                                    bitmap->description);
232                 return;
233         }
234         ext2fs_set_bit(block - bitmap->start, bitmap->bitmap);
235 }
236
237 _INLINE_ void ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
238                                          blk_t block)
239 {
240         if ((block < bitmap->start) || (block > bitmap->end)) {
241                 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK,
242                                    block, bitmap->description);
243                 return;
244         }
245         ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap);
246 }
247
248 _INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
249                                        blk_t block)
250 {
251         if ((block < bitmap->start) || (block > bitmap->end)) {
252                 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
253                                    block, bitmap->description);
254                 return 0;
255         }
256         return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap);
257 }
258
259 _INLINE_ void ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
260                                        ino_t inode)
261 {
262         if ((inode < bitmap->start) || (inode > bitmap->end)) {
263                 ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_MARK,
264                                    inode, bitmap->description);
265                 return;
266         }
267         ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap);
268 }
269
270 _INLINE_ void ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
271                                          ino_t inode)
272 {
273         if ((inode < bitmap->start) || (inode > bitmap->end)) {
274                 ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_UNMARK,
275                                    inode, bitmap->description);
276                 return;
277         }
278         ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap);
279 }
280
281 _INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
282                                        ino_t inode)
283 {
284         if ((inode < bitmap->start) || (inode > bitmap->end)) {
285                 ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_TEST,
286                                    inode, bitmap->description);
287                 return 0;
288         }
289         return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap);
290 }
291
292 _INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
293                                             blk_t block)
294 {
295 #ifdef EXT2FS_DEBUG_FAST_OPS
296         if ((block < bitmap->start) || (block > bitmap->end)) {
297                 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
298                                    bitmap->description);
299                 return;
300         }
301 #endif  
302         ext2fs_set_bit(block - bitmap->start, bitmap->bitmap);
303 }
304
305 _INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
306                                               blk_t block)
307 {
308 #ifdef EXT2FS_DEBUG_FAST_OPS
309         if ((block < bitmap->start) || (block > bitmap->end)) {
310                 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK,
311                                    block, bitmap->description);
312                 return;
313         }
314 #endif
315         ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap);
316 }
317
318 _INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
319                                             blk_t block)
320 {
321 #ifdef EXT2FS_DEBUG_FAST_OPS
322         if ((block < bitmap->start) || (block > bitmap->end)) {
323                 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST,
324                                    block, bitmap->description);
325                 return 0;
326         }
327 #endif
328         return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap);
329 }
330
331 _INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
332                                             ino_t inode)
333 {
334 #ifdef EXT2FS_DEBUG_FAST_OPS
335         if ((inode < bitmap->start) || (inode > bitmap->end)) {
336                 ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_MARK,
337                                    inode, bitmap->description);
338                 return;
339         }
340 #endif
341         ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap);
342 }
343
344 _INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
345                                               ino_t inode)
346 {
347 #ifdef EXT2FS_DEBUG_FAST_OPS
348         if ((inode < bitmap->start) || (inode > bitmap->end)) {
349                 ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_UNMARK,
350                                    inode, bitmap->description);
351                 return;
352         }
353 #endif
354         ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap);
355 }
356
357 _INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
358                                            ino_t inode)
359 {
360 #ifdef EXT2FS_DEBUG_FAST_OPS
361         if ((inode < bitmap->start) || (inode > bitmap->end)) {
362                 ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_TEST,
363                                    inode, bitmap->description);
364                 return 0;
365         }
366 #endif
367         return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap);
368 }
369
370 _INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
371 {
372         return bitmap->start;
373 }
374
375 _INLINE_ blk_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
376 {
377         return bitmap->start;
378 }
379
380 _INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
381 {
382         return bitmap->end;
383 }
384
385 _INLINE_ blk_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
386 {
387         return bitmap->end;
388 }
389
390 #undef _INLINE_
391 #endif
392