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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #ifndef _BITS_BITOPS_H
  2. #define _BITS_BITOPS_H
  3. /** @file
  4. *
  5. * ARM bit operations
  6. *
  7. */
  8. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  9. #include <stdint.h>
  10. /**
  11. * Test and set bit atomically
  12. *
  13. * @v bit Bit to set
  14. * @v bits Bit field
  15. * @ret old Old value of bit (zero or non-zero)
  16. */
  17. static inline __attribute__ (( always_inline )) int
  18. test_and_set_bit ( unsigned int bit, volatile void *bits ) {
  19. unsigned int index = ( bit / 64 );
  20. unsigned int offset = ( bit % 64 );
  21. volatile uint64_t *qword = ( ( ( volatile uint64_t * ) bits ) + index );
  22. uint64_t mask = ( 1UL << offset );
  23. uint64_t old;
  24. uint64_t new;
  25. uint32_t flag;
  26. __asm__ __volatile__ ( "\n1:\n\t"
  27. "ldxr %0, %3\n\t"
  28. "orr %1, %0, %4\n\t"
  29. "stxr %w2, %1, %3\n\t"
  30. "tst %w2, %w2\n\t"
  31. "bne 1b\n\t"
  32. : "=&r" ( old ), "=&r" ( new ), "=&r" ( flag ),
  33. "+Q" ( *qword )
  34. : "r" ( mask )
  35. : "cc" );
  36. return ( !! ( old & mask ) );
  37. }
  38. /**
  39. * Test and clear bit atomically
  40. *
  41. * @v bit Bit to set
  42. * @v bits Bit field
  43. * @ret old Old value of bit (zero or non-zero)
  44. */
  45. static inline __attribute__ (( always_inline )) int
  46. test_and_clear_bit ( unsigned int bit, volatile void *bits ) {
  47. unsigned int index = ( bit / 64 );
  48. unsigned int offset = ( bit % 64 );
  49. volatile uint64_t *qword = ( ( ( volatile uint64_t * ) bits ) + index );
  50. uint64_t mask = ( 1UL << offset );
  51. uint64_t old;
  52. uint64_t new;
  53. uint32_t flag;
  54. __asm__ __volatile__ ( "\n1:\n\t"
  55. "ldxr %0, %3\n\t"
  56. "bic %1, %0, %4\n\t"
  57. "stxr %w2, %1, %3\n\t"
  58. "tst %w2, %w2\n\t"
  59. "bne 1b\n\t"
  60. : "=&r" ( old ), "=&r" ( new ), "=&r" ( flag ),
  61. "+Q" ( *qword )
  62. : "r" ( mask )
  63. : "cc" );
  64. return ( !! ( old & mask ) );
  65. }
  66. /**
  67. * Set bit atomically
  68. *
  69. * @v bit Bit to set
  70. * @v bits Bit field
  71. */
  72. static inline __attribute__ (( always_inline )) void
  73. set_bit ( unsigned int bit, volatile void *bits ) {
  74. test_and_set_bit ( bit, bits );
  75. }
  76. /**
  77. * Clear bit atomically
  78. *
  79. * @v bit Bit to set
  80. * @v bits Bit field
  81. */
  82. static inline __attribute__ (( always_inline )) void
  83. clear_bit ( unsigned int bit, volatile void *bits ) {
  84. test_and_clear_bit ( bit, bits );
  85. }
  86. #endif /* _BITS_BITOPS_H */