bitops.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:3k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (C) 1996 Paul Mackerras.
  3.  * Adapted for ppc64 - Todd Inglett, Anton Blanchard
  4.  *
  5.  * This program is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU General Public License
  7.  * as published by the Free Software Foundation; either version
  8.  * 2 of the License, or (at your option) any later version.
  9.  */
  10. #include <linux/kernel.h>
  11. #include <asm/bitops.h>
  12. #include <linux/fs.h>
  13. #include <linux/ext2_fs.h>
  14. #include <linux/locks.h>
  15. #include <linux/quotaops.h>
  16. #include <asm/ppcdebug.h>
  17. #undef DEBUG_BITOPS
  18. /*
  19.  * Bitops are weird when viewed on big-endian systems.  They were designed
  20.  * on little endian so the size of the bitset doesn't matter (low order bytes
  21.  * come first) as long as the bit in question is valid.
  22.  *
  23.  * Bits are "tested" often using the C expression (val & (1<<nr)) so we do
  24.  * our best to stay compatible with that.  The assumption is that val will
  25.  * be unsigned long for such tests.  As such, we assume the bits are stored
  26.  * as an array of unsigned long (the usual case is a single unsigned long,
  27.  * of course).  Here's an example bitset with bit numbering:
  28.  *
  29.  *   |63..........0|127........64|195.......128|255.......196|
  30.  *
  31.  * This leads to two problems.  First, if an int, short or char is passed as
  32.  * a bitset it will be a bad memory reference since we want to store in chunks
  33.  * of unsigned long (64 bits here) size.  Second, since these could be char
  34.  * arrays we might have an alignment problem.  We ease the alignment problem
  35.  * by actually doing the operation with 32 bit values yet preserving the
  36.  * 64 bit long layout as shown above.  Got that?  Good.
  37.  */
  38. unsigned long find_next_zero_bit(void * addr, unsigned long size,
  39.  unsigned long offset)
  40. {
  41. unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
  42. unsigned long result = offset & ~63UL;
  43. unsigned long tmp;
  44. if (offset >= size)
  45. return size;
  46. size -= result;
  47. offset &= 63UL;
  48. if (offset) {
  49. tmp = *p++;
  50. tmp |= ~0UL >> (64-offset);
  51. if (size < 64)
  52. goto found_first;
  53. if (~tmp)
  54. goto found_middle;
  55. size -= 64;
  56. result += 64;
  57. }
  58. while (size & ~63UL) {
  59. if (~(tmp = *(p++)))
  60. goto found_middle;
  61. result += 64;
  62. size -= 64;
  63. }
  64. if (!size)
  65. return result;
  66. tmp = *p;
  67. found_first:
  68. tmp |= ~0UL << size;
  69. if (tmp == ~0UL)
  70. return result+size;
  71. found_middle:
  72. return result + ffz(tmp);
  73. }
  74. void BUG_OUTLINE(char* file, unsigned line) 
  75. {
  76. udbg_printf("BUG - kernel BUG at %s:%d! n", __FILE__, __LINE__);
  77. PPCDBG_ENTER_DEBUGGER();
  78. printk("kernel BUG at %s:%d!n", __FILE__, __LINE__);
  79. __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR);
  80. }