bitops.h revision 76f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07
1/* 2 * bitops.h --- Bitmap frobbing code. The byte swapping routines are 3 * also included here. 4 * 5 * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. 6 * 7 * %Begin-Header% 8 * This file may be redistributed under the terms of the GNU Public 9 * License. 10 * %End-Header% 11 * 12 * i386 bitops operations taken from <asm/bitops.h>, Copyright 1992, 13 * Linus Torvalds. 14 */ 15 16 17extern int ext2fs_set_bit(int nr,void * addr); 18extern int ext2fs_clear_bit(int nr, void * addr); 19extern int ext2fs_test_bit(int nr, const void * addr); 20extern __u16 ext2fs_swab16(__u16 val); 21extern __u32 ext2fs_swab32(__u32 val); 22 23/* 24 * EXT2FS bitmap manipulation routines. 25 */ 26 27/* Support for sending warning messages from the inline subroutines */ 28extern const char *ext2fs_block_string; 29extern const char *ext2fs_inode_string; 30extern const char *ext2fs_mark_string; 31extern const char *ext2fs_unmark_string; 32extern const char *ext2fs_test_string; 33extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg, 34 const char *description); 35extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap, 36 int code, unsigned long arg); 37 38extern void ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block); 39extern void ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap, 40 blk_t block); 41extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block); 42 43extern void ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ino_t inode); 44extern void ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, 45 ino_t inode); 46extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ino_t inode); 47 48extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap, 49 blk_t block); 50extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap, 51 blk_t block); 52extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap, 53 blk_t block); 54 55extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, 56 ino_t inode); 57extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, 58 ino_t inode); 59extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap, 60 ino_t inode); 61extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap); 62extern ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap); 63extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap); 64extern ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap); 65 66extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, 67 blk_t block, int num); 68extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, 69 blk_t block, int num); 70extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap, 71 blk_t block, int num); 72extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, 73 blk_t block, int num); 74extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, 75 blk_t block, int num); 76extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap, 77 blk_t block, int num); 78extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map); 79 80/* 81 * The inline routines themselves... 82 * 83 * If NO_INLINE_FUNCS is defined, then we won't try to do inline 84 * functions at all; they will be included as normal functions in 85 * inline.c 86 */ 87#ifdef NO_INLINE_FUNCS 88#if (defined(__GNUC__) && (defined(__i386__) || defined(__i486__) || \ 89 defined(__i586__) || defined(__mc68000__) || \ 90 defined(__sparc__))) 91 /* This prevents bitops.c from trying to include the C */ 92 /* function version of these functions */ 93#define _EXT2_HAVE_ASM_BITOPS_ 94#endif 95#endif /* NO_INLINE_FUNCS */ 96 97#if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) 98#ifdef INCLUDE_INLINE_FUNCS 99#define _INLINE_ extern 100#else 101#ifdef __GNUC__ 102#define _INLINE_ extern __inline__ 103#else /* For Watcom C */ 104#define _INLINE_ extern inline 105#endif 106#endif 107 108#if ((defined __GNUC__) && (defined(__i386__) || defined(__i486__) || \ 109 defined(__i586__))) 110 111#define _EXT2_HAVE_ASM_BITOPS_ 112 113/* 114 * These are done by inline assembly for speed reasons..... 115 * 116 * All bitoperations return 0 if the bit was cleared before the 117 * operation and != 0 if it was not. Bit 0 is the LSB of addr; bit 32 118 * is the LSB of (addr+1). 119 */ 120 121/* 122 * Some hacks to defeat gcc over-optimizations.. 123 */ 124struct __dummy_h { unsigned long a[100]; }; 125#define EXT2FS_ADDR (*(struct __dummy_h *) addr) 126#define EXT2FS_CONST_ADDR (*(const struct __dummy_h *) addr) 127 128_INLINE_ int ext2fs_set_bit(int nr, void * addr) 129{ 130 int oldbit; 131 132 __asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0" 133 :"=r" (oldbit),"=m" (EXT2FS_ADDR) 134 :"r" (nr)); 135 return oldbit; 136} 137 138_INLINE_ int ext2fs_clear_bit(int nr, void * addr) 139{ 140 int oldbit; 141 142 __asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0" 143 :"=r" (oldbit),"=m" (EXT2FS_ADDR) 144 :"r" (nr)); 145 return oldbit; 146} 147 148_INLINE_ int ext2fs_test_bit(int nr, const void * addr) 149{ 150 int oldbit; 151 152 __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0" 153 :"=r" (oldbit) 154 :"m" (EXT2FS_CONST_ADDR),"r" (nr)); 155 return oldbit; 156} 157 158#undef EXT2FS_ADDR 159 160#endif /* i386 */ 161 162#ifdef __mc68000__ 163 164#define _EXT2_HAVE_ASM_BITOPS_ 165 166_INLINE_ int ext2fs_set_bit(int nr,void * addr) 167{ 168 char retval; 169 170 __asm__ __volatile__ ("bfset %2@{%1:#1}; sne %0" 171 : "=d" (retval) : "d" (nr^7), "a" (addr)); 172 173 return retval; 174} 175 176_INLINE_ int ext2fs_clear_bit(int nr, void * addr) 177{ 178 char retval; 179 180 __asm__ __volatile__ ("bfclr %2@{%1:#1}; sne %0" 181 : "=d" (retval) : "d" (nr^7), "a" (addr)); 182 183 return retval; 184} 185 186_INLINE_ int ext2fs_test_bit(int nr, const void * addr) 187{ 188 char retval; 189 190 __asm__ __volatile__ ("bftst %2@{%1:#1}; sne %0" 191 : "=d" (retval) : "d" (nr^7), "a" (addr)); 192 193 return retval; 194} 195 196#endif /* __mc68000__ */ 197 198#ifdef __sparc__ 199 200#define _EXT2_HAVE_ASM_BITOPS_ 201 202#ifndef EXT2_OLD_BITOPS 203 204/* 205 * Do the bitops so that we are compatible with the standard i386 206 * convention. 207 */ 208 209_INLINE_ int ext2fs_set_bit(int nr,void * addr) 210{ 211#if 1 212 int mask; 213 unsigned char *ADDR = (unsigned char *) addr; 214 215 ADDR += nr >> 3; 216 mask = 1 << (nr & 0x07); 217 __asm__ __volatile__("ldub [%0], %%g6\n\t" 218 "or %%g6, %2, %%g5\n\t" 219 "stb %%g5, [%0]\n\t" 220 "and %%g6, %2, %0\n" 221 : "=&r" (ADDR) 222 : "0" (ADDR), "r" (mask) 223 : "g5", "g6"); 224 return (int) ADDR; 225#else 226 int mask, retval; 227 unsigned char *ADDR = (unsigned char *) addr; 228 229 ADDR += nr >> 3; 230 mask = 1 << (nr & 0x07); 231 retval = (mask & *ADDR) != 0; 232 *ADDR |= mask; 233 return retval; 234#endif 235} 236 237_INLINE_ int ext2fs_clear_bit(int nr, void * addr) 238{ 239#if 1 240 int mask; 241 unsigned char *ADDR = (unsigned char *) addr; 242 243 ADDR += nr >> 3; 244 mask = 1 << (nr & 0x07); 245 __asm__ __volatile__("ldub [%0], %%g6\n\t" 246 "andn %%g6, %2, %%g5\n\t" 247 "stb %%g5, [%0]\n\t" 248 "and %%g6, %2, %0\n" 249 : "=&r" (ADDR) 250 : "0" (ADDR), "r" (mask) 251 : "g5", "g6"); 252 return (int) ADDR; 253 254#else 255 int mask, retval; 256 unsigned char *ADDR = (unsigned char *) addr; 257 258 ADDR += nr >> 3; 259 mask = 1 << (nr & 0x07); 260 retval = (mask & *ADDR) != 0; 261 *ADDR &= ~mask; 262 return retval; 263#endif 264} 265 266_INLINE_ int ext2fs_test_bit(int nr, const void * addr) 267{ 268 int mask; 269 const unsigned char *ADDR = (const unsigned char *) addr; 270 271 ADDR += nr >> 3; 272 mask = 1 << (nr & 0x07); 273 return ((mask & *ADDR) != 0); 274} 275 276#else 277 278/* Do things the old, unplesant way. */ 279 280_INLINE_ int ext2fs_set_bit(int nr, void *addr) 281{ 282 int mask, retval; 283 unsigned long *ADDR = (unsigned long *) addr; 284 285 ADDR += nr >> 5; 286 mask = 1 << (nr & 31); 287 retval = ((mask & *ADDR) != 0); 288 *ADDR |= mask; 289 return retval; 290} 291 292_INLINE_ int ext2fs_clear_bit(int nr, void *addr) 293{ 294 int mask, retval; 295 unsigned long *ADDR = (unsigned long *) addr; 296 297 ADDR += nr >> 5; 298 mask = 1 << (nr & 31); 299 retval = ((mask & *ADDR) != 0); 300 *ADDR &= ~mask; 301 return retval; 302} 303 304_INLINE_ int ext2fs_test_bit(int nr, const void *addr) 305{ 306 int mask; 307 const unsigned long *ADDR = (const unsigned long *) addr; 308 309 ADDR += nr >> 5; 310 mask = 1 << (nr & 31); 311 return ((mask & *ADDR) != 0); 312} 313#endif 314 315#endif /* __sparc__ */ 316 317#ifndef _EXT2_HAVE_ASM_SWAB 318 319_INLINE_ __u16 ext2fs_swab16(__u16 val) 320{ 321 return (val >> 8) | (val << 8); 322} 323 324_INLINE_ __u32 ext2fs_swab32(__u32 val) 325{ 326 return ((val>>24) | ((val>>8)&0xFF00) | 327 ((val<<8)&0xFF0000) | (val<<24)); 328} 329 330#endif /* !_EXT2_HAVE_ASM_SWAB */ 331 332_INLINE_ void ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap, 333 __u32 bitno); 334_INLINE_ void ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap, 335 blk_t bitno); 336_INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap, 337 blk_t bitno); 338 339_INLINE_ void ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap, 340 __u32 bitno) 341{ 342 if ((bitno < bitmap->start) || (bitno > bitmap->end)) { 343 ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno); 344 return; 345 } 346 ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap); 347} 348 349_INLINE_ void ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap, 350 blk_t bitno) 351{ 352 if ((bitno < bitmap->start) || (bitno > bitmap->end)) { 353 ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno); 354 return; 355 } 356 ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap); 357} 358 359_INLINE_ int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap, 360 blk_t bitno) 361{ 362 if ((bitno < bitmap->start) || (bitno > bitmap->end)) { 363 ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno); 364 return 0; 365 } 366 return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap); 367} 368 369_INLINE_ void ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, 370 blk_t block) 371{ 372 ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block); 373} 374 375_INLINE_ void ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap, 376 blk_t block) 377{ 378 ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block); 379} 380 381_INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, 382 blk_t block) 383{ 384 return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap, 385 block); 386} 387 388_INLINE_ void ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, 389 ino_t inode) 390{ 391 ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode); 392} 393 394_INLINE_ void ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, 395 ino_t inode) 396{ 397 ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode); 398} 399 400_INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, 401 ino_t inode) 402{ 403 return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap, 404 inode); 405} 406 407_INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap, 408 blk_t block) 409{ 410#ifdef EXT2FS_DEBUG_FAST_OPS 411 if ((block < bitmap->start) || (block > bitmap->end)) { 412 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block, 413 bitmap->description); 414 return; 415 } 416#endif 417 ext2fs_set_bit(block - bitmap->start, bitmap->bitmap); 418} 419 420_INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap, 421 blk_t block) 422{ 423#ifdef EXT2FS_DEBUG_FAST_OPS 424 if ((block < bitmap->start) || (block > bitmap->end)) { 425 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, 426 block, bitmap->description); 427 return; 428 } 429#endif 430 ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap); 431} 432 433_INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap, 434 blk_t block) 435{ 436#ifdef EXT2FS_DEBUG_FAST_OPS 437 if ((block < bitmap->start) || (block > bitmap->end)) { 438 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, 439 block, bitmap->description); 440 return 0; 441 } 442#endif 443 return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap); 444} 445 446_INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, 447 ino_t inode) 448{ 449#ifdef EXT2FS_DEBUG_FAST_OPS 450 if ((inode < bitmap->start) || (inode > bitmap->end)) { 451 ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_MARK, 452 inode, bitmap->description); 453 return; 454 } 455#endif 456 ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap); 457} 458 459_INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, 460 ino_t inode) 461{ 462#ifdef EXT2FS_DEBUG_FAST_OPS 463 if ((inode < bitmap->start) || (inode > bitmap->end)) { 464 ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_UNMARK, 465 inode, bitmap->description); 466 return; 467 } 468#endif 469 ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap); 470} 471 472_INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap, 473 ino_t inode) 474{ 475#ifdef EXT2FS_DEBUG_FAST_OPS 476 if ((inode < bitmap->start) || (inode > bitmap->end)) { 477 ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_TEST, 478 inode, bitmap->description); 479 return 0; 480 } 481#endif 482 return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap); 483} 484 485_INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap) 486{ 487 return bitmap->start; 488} 489 490_INLINE_ ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap) 491{ 492 return bitmap->start; 493} 494 495_INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap) 496{ 497 return bitmap->end; 498} 499 500_INLINE_ ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap) 501{ 502 return bitmap->end; 503} 504 505_INLINE_ int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap, 506 blk_t block, int num) 507{ 508 int i; 509 510 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { 511 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, 512 block, bitmap->description); 513 return 0; 514 } 515 for (i=0; i < num; i++) { 516 if (ext2fs_fast_test_block_bitmap(bitmap, block+i)) 517 return 0; 518 } 519 return 1; 520} 521 522_INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap, 523 blk_t block, int num) 524{ 525 int i; 526 527#ifdef EXT2FS_DEBUG_FAST_OPS 528 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { 529 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, 530 block, bitmap->description); 531 return 0; 532 } 533#endif 534 for (i=0; i < num; i++) { 535 if (ext2fs_fast_test_block_bitmap(bitmap, block+i)) 536 return 0; 537 } 538 return 1; 539} 540 541_INLINE_ void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, 542 blk_t block, int num) 543{ 544 int i; 545 546 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { 547 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block, 548 bitmap->description); 549 return; 550 } 551 for (i=0; i < num; i++) 552 ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap); 553} 554 555_INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, 556 blk_t block, int num) 557{ 558 int i; 559 560#ifdef EXT2FS_DEBUG_FAST_OPS 561 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { 562 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block, 563 bitmap->description); 564 return; 565 } 566#endif 567 for (i=0; i < num; i++) 568 ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap); 569} 570 571_INLINE_ void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, 572 blk_t block, int num) 573{ 574 int i; 575 576 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { 577 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block, 578 bitmap->description); 579 return; 580 } 581 for (i=0; i < num; i++) 582 ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap); 583} 584 585_INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, 586 blk_t block, int num) 587{ 588 int i; 589 590#ifdef EXT2FS_DEBUG_FAST_OPS 591 if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { 592 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block, 593 bitmap->description); 594 return; 595 } 596#endif 597 for (i=0; i < num; i++) 598 ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap); 599} 600 601#undef _INLINE_ 602#endif 603 604