1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
#ifndef _LINUX_BITOPS_H
#define _LINUX_BITOPS_H
#include <asm/types.h>
#include "common/compiler.h"
#include "common/asm-generic/bitops.h"
/**
* test_and_set_bit - Set a bit and return its old value
* @nr: Bit to set
* @addr: Address to count from
*
* This operation is atomic and cannot be reordered.
* It also implies a memory barrier.
*/
static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *addr)
{
unsigned long *m = ((unsigned long *)addr) + (nr >> 6);
unsigned long temp = 0;
unsigned long res;
int bit = nr & 63UL;
do {
__asm__ __volatile__(" .set mips3 \n"
" lld %0, %1 # test_and_set_bit \n"
" or %2, %0, %3 \n"
" scd %2, %1 \n"
" .set mips0 \n"
: "=&r"(temp), "+m"(*m), "=&r"(res)
: "r"(1UL << bit)
: "memory");
} while (unlikely(!res));
res = temp & (1UL << bit);
return res != 0;
}
#endif
|