bitops_64.h 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /*
  2. * Copyright 2011 Tilera Corporation. All Rights Reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation, version 2.
  7. *
  8. * This program is distributed in the hope that it will be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  11. * NON INFRINGEMENT. See the GNU General Public License for
  12. * more details.
  13. */
  14. #ifndef _ASM_TILE_BITOPS_64_H
  15. #define _ASM_TILE_BITOPS_64_H
  16. #include <linux/compiler.h>
  17. #include <asm/cmpxchg.h>
  18. /* See <asm/bitops.h> for API comments. */
  19. static inline void set_bit(unsigned nr, volatile unsigned long *addr)
  20. {
  21. unsigned long mask = (1UL << (nr % BITS_PER_LONG));
  22. __insn_fetchor((void *)(addr + nr / BITS_PER_LONG), mask);
  23. }
  24. static inline void clear_bit(unsigned nr, volatile unsigned long *addr)
  25. {
  26. unsigned long mask = (1UL << (nr % BITS_PER_LONG));
  27. __insn_fetchand((void *)(addr + nr / BITS_PER_LONG), ~mask);
  28. }
  29. static inline void change_bit(unsigned nr, volatile unsigned long *addr)
  30. {
  31. unsigned long mask = (1UL << (nr % BITS_PER_LONG));
  32. unsigned long guess, oldval;
  33. addr += nr / BITS_PER_LONG;
  34. oldval = *addr;
  35. do {
  36. guess = oldval;
  37. oldval = cmpxchg(addr, guess, guess ^ mask);
  38. } while (guess != oldval);
  39. }
  40. /*
  41. * The test_and_xxx_bit() routines require a memory fence before we
  42. * start the operation, and after the operation completes. We use
  43. * smp_mb() before, and rely on the "!= 0" comparison, plus a compiler
  44. * barrier(), to block until the atomic op is complete.
  45. */
  46. static inline int test_and_set_bit(unsigned nr, volatile unsigned long *addr)
  47. {
  48. int val;
  49. unsigned long mask = (1UL << (nr % BITS_PER_LONG));
  50. smp_mb(); /* barrier for proper semantics */
  51. val = (__insn_fetchor((void *)(addr + nr / BITS_PER_LONG), mask)
  52. & mask) != 0;
  53. barrier();
  54. return val;
  55. }
  56. static inline int test_and_clear_bit(unsigned nr, volatile unsigned long *addr)
  57. {
  58. int val;
  59. unsigned long mask = (1UL << (nr % BITS_PER_LONG));
  60. smp_mb(); /* barrier for proper semantics */
  61. val = (__insn_fetchand((void *)(addr + nr / BITS_PER_LONG), ~mask)
  62. & mask) != 0;
  63. barrier();
  64. return val;
  65. }
  66. static inline int test_and_change_bit(unsigned nr,
  67. volatile unsigned long *addr)
  68. {
  69. unsigned long mask = (1UL << (nr % BITS_PER_LONG));
  70. unsigned long guess, oldval;
  71. addr += nr / BITS_PER_LONG;
  72. oldval = *addr;
  73. do {
  74. guess = oldval;
  75. oldval = cmpxchg(addr, guess, guess ^ mask);
  76. } while (guess != oldval);
  77. return (oldval & mask) != 0;
  78. }
  79. #include <asm-generic/bitops/ext2-atomic-setbit.h>
  80. #endif /* _ASM_TILE_BITOPS_64_H */