Linux駆動(同時):04---原子操作(atomic_t、atomic_set、set_bit)
3214 ワード
一、原子操作の紹介
static inline void atomic_add(int i, atomic_t *v)
{
unsigned long tmp;
int result;
prefetchw(&v->counter);
__asm__ __volatile__("@ atomic_add
"
"1: ldrex %0, [%3]
"
" add %0, %0, %4
"
" strex %1, %0, [%3]
"
" teq %1, #0
"
" bne 1b"
: "=&r" (result),"=&r" (tmp),"+Qo" (v->counter)
: "r" (&v->counter),"Ir" (i)
: "cc");
}
二、整型原子操作
原子変数の値の設定
void atomic_set(atomic_t *v, int i); /* i */
atomic_t v = ATOMIC_INIT(0); /* v 0 */
原子変数の値の取得
atomic_read(atomic_t *v); /* */
原子変数の増減
void atomic_add(int i, atomic_t *v); /* i */
void atomic_sub(int i, atomic_t *v); /* i */
原子変数の自己増加/自己減少
void atomic_inc(atomic_t *v); /* 1 */
void atomic_dec(atomic_t *v); /* 1 */
操作とテスト
void atomic_set(atomic_t *v, int i); /* i */
atomic_t v = ATOMIC_INIT(0); /* v 0 */
atomic_read(atomic_t *v); /* */
void atomic_add(int i, atomic_t *v); /* i */
void atomic_sub(int i, atomic_t *v); /* i */
void atomic_inc(atomic_t *v); /* 1 */
void atomic_dec(atomic_t *v); /* 1 */
int atomic_inc_and_test(atomic_t *v);
int atomic_dec_and_test(atomic_t *v);
int atomic_sub_and_test(int i, atomic_t *v);
操作して戻る
int atomic_add_return(int i, atomic_t *v);
int atomic_sub_return(int i, atomic_t *v);
int atomic_inc_return(atomic_t *v);
int atomic_dec_return(atomic_t *v);
三位原子操作
セットビット
void set_bit(nr, void *addr);
クリアビット
void clear_bit(nr, void *addr);
へんいビット
void change_bit(nr, void *addr);
テストビット
test_bit(nr, void *addr);
ビットのテストと操作
int test_and_set_bit(nr, void *addr);
int test_and_clear_bit(nr, void *addr);
int test_and_change_bit(nr, void *addr);
四、実例
static atomic_t xxx_available = ATOMIC_INIT(1); /* */
static int xxx_open(struct inode *inode, struct file *filp)
{
...
if (!atomic_dec_and_test(&xxx_available)) {
atomic_inc(&xxx_available);
return - EBUSY; /* */
}
...
return 0; /* */
}
static int xxx_release(struct inode *inode, struct file *filp)
{
atomic_inc(&xxx_available); /* */
return 0;
}