You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bitops.h 2.2KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #ifndef _BITS_BITOPS_H
  2. #define _BITS_BITOPS_H
  3. /** @file
  4. *
  5. * x86 bit operations
  6. *
  7. * We perform atomic bit set and bit clear operations using "lock bts"
  8. * and "lock btr". We use the output constraint to inform the
  9. * compiler that any memory from the start of the bit field up to and
  10. * including the byte containing the bit may be modified. (This is
  11. * overkill but shouldn't matter in practice since we're unlikely to
  12. * subsequently read other bits from the same bit field.)
  13. */
  14. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  15. #include <stdint.h>
  16. /**
  17. * Set bit atomically
  18. *
  19. * @v bit Bit to set
  20. * @v bits Bit field
  21. */
  22. static inline __attribute__ (( always_inline )) void
  23. set_bit ( unsigned int bit, volatile void *bits ) {
  24. volatile struct {
  25. uint8_t byte[ ( bit / 8 ) + 1 ];
  26. } *bytes = bits;
  27. __asm__ __volatile__ ( "lock bts %1, %0"
  28. : "+m" ( *bytes ) : "Ir" ( bit ) );
  29. }
  30. /**
  31. * Clear bit atomically
  32. *
  33. * @v bit Bit to set
  34. * @v bits Bit field
  35. */
  36. static inline __attribute__ (( always_inline )) void
  37. clear_bit ( unsigned int bit, volatile void *bits ) {
  38. volatile struct {
  39. uint8_t byte[ ( bit / 8 ) + 1 ];
  40. } *bytes = bits;
  41. __asm__ __volatile__ ( "lock btr %1, %0"
  42. : "+m" ( *bytes ) : "Ir" ( bit ) );
  43. }
  44. /**
  45. * Test and set bit atomically
  46. *
  47. * @v bit Bit to set
  48. * @v bits Bit field
  49. * @ret old Old value of bit (zero or non-zero)
  50. */
  51. static inline __attribute__ (( always_inline )) int
  52. test_and_set_bit ( unsigned int bit, volatile void *bits ) {
  53. volatile struct {
  54. uint8_t byte[ ( bit / 8 ) + 1 ];
  55. } *bytes = bits;
  56. int old;
  57. __asm__ __volatile__ ( "lock bts %2, %0\n\t"
  58. "sbb %1, %1\n\t"
  59. : "+m" ( *bytes ), "=r" ( old )
  60. : "Ir" ( bit ) );
  61. return old;
  62. }
  63. /**
  64. * Test and clear bit atomically
  65. *
  66. * @v bit Bit to set
  67. * @v bits Bit field
  68. * @ret old Old value of bit (zero or non-zero)
  69. */
  70. static inline __attribute__ (( always_inline )) int
  71. test_and_clear_bit ( unsigned int bit, volatile void *bits ) {
  72. volatile struct {
  73. uint8_t byte[ ( bit / 8 ) + 1 ];
  74. } *bytes = bits;
  75. int old;
  76. __asm__ __volatile__ ( "lock btr %2, %0\n\t"
  77. "sbb %1, %1\n\t"
  78. : "+m" ( *bytes ), "=r" ( old )
  79. : "Ir" ( bit ) );
  80. return old;
  81. }
  82. #endif /* _BITS_BITOPS_H */