#ifndef _BITS_BITOPS_H #define _BITS_BITOPS_H /** @file * * x86 bit operations * * We perform atomic bit set and bit clear operations using "lock bts" * and "lock btr". We use the output constraint to inform the * compiler that any memory from the start of the bit field up to and * including the byte containing the bit may be modified. (This is * overkill but shouldn't matter in practice since we're unlikely to * subsequently read other bits from the same bit field.) */ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include /** * Set bit atomically * * @v bit Bit to set * @v bits Bit field */ static inline __attribute__ (( always_inline )) void set_bit ( unsigned int bit, volatile void *bits ) { volatile struct { uint8_t byte[ ( bit / 8 ) + 1 ]; } *bytes = bits; __asm__ __volatile__ ( "lock btsl %k1, %0" : "+m" ( *bytes ) : "Ir" ( bit ) ); } /** * Clear bit atomically * * @v bit Bit to set * @v bits Bit field */ static inline __attribute__ (( always_inline )) void clear_bit ( unsigned int bit, volatile void *bits ) { volatile struct { uint8_t byte[ ( bit / 8 ) + 1 ]; } *bytes = bits; __asm__ __volatile__ ( "lock btrl %k1, %0" : "+m" ( *bytes ) : "Ir" ( bit ) ); } /** * Test and set bit atomically * * @v bit Bit to set * @v bits Bit field * @ret old Old value of bit (zero or non-zero) */ static inline __attribute__ (( always_inline )) int test_and_set_bit ( unsigned int bit, volatile void *bits ) { volatile struct { uint8_t byte[ ( bit / 8 ) + 1 ]; } *bytes = bits; int old; __asm__ __volatile__ ( "lock btsl %k2, %0\n\t" "sbb %1, %1\n\t" : "+m" ( *bytes ), "=r" ( old ) : "Ir" ( bit ) ); return old; } /** * Test and clear bit atomically * * @v bit Bit to set * @v bits Bit field * @ret old Old value of bit (zero or non-zero) */ static inline __attribute__ (( always_inline )) int test_and_clear_bit ( unsigned int bit, volatile void *bits ) { volatile struct { uint8_t byte[ ( bit / 8 ) + 1 ]; } *bytes = bits; int old; __asm__ __volatile__ ( "lock btrl %k2, %0\n\t" "sbb %1, %1\n\t" : "+m" ( *bytes ), "=r" ( old ) : "Ir" ( bit ) ); return old; } #endif /* _BITS_BITOPS_H */