用户空间原子操作的实现|用户空间,原子操作,lock,atomic-中国源码网
来源:百度文库 编辑:神马文学网 时间:2024/04/26 14:00:11
用户空间原子操作的实现
作者: 来源:cudev 发表时间:2008-09-27 浏览次数:2896 字号:大 中 小
中国源码网内相关主题链接使用lock指令前缀:
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1)
/* Technically wrong, but this avoids compilation errors on some gcc
versions. */
#define ADDR "=m" (*(volatile long *) addr)
#else
#define ADDR "+m" (*(volatile long *) addr)
#endif
#ifdef CONFIG_SMP
#define LOCK_PREFIX "lock; "
#else /* ! CONFIG_SMP */
#define LOCK_PREFIX ""
#endif
typedef struct {
int counter;
} atomic_t;
#define atomic_read(v) ((v)->counter)
#define atomic_set(v, i) (((v)->counter) = (i))
static inline void atomic_inc(atomic_t *v)
{
asm volatile(LOCK_PREFIX "incl %0"
: "=m" (v->counter)
: "m" (v->counter));
}
static inline void atomic_dec(atomic_t *v)
{
asm volatile(LOCK_PREFIX "decl %0"
: "=m" (v->counter)
: "m" (v->counter));
}
static inline void set_bit(int nr, volatile void *addr)
{
asm volatile(LOCK_PREFIX "bts %1,%0" : ADDR : "Ir" (nr) : "memory");
}
static inline int test_and_set_bit(int nr, volatile void *addr)
{
int oldbit;
asm volatile(LOCK_PREFIX "bts %2,%1nt"
"sbb %0,%0" : "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
return oldbit;
}
static inline void clear_bit(int nr, volatile void *addr)
{
asm volatile(LOCK_PREFIX "btr %1,%0" : ADDR : "Ir" (nr));
}
static inline int test_and_clear_bit(int nr, volatile void *addr)
{
int oldbit;
asm volatile(LOCK_PREFIX "btr %2,%1nt"
"sbb %0,%0"
: "=r" (oldbit), ADDR : "Ir" (nr) : "memory");
return oldbit;
}
使用gcc的内建函数来进行原子访问:
#ifndef _ATOMIC_H
#define _ATOMIC_H
/**
* Atomic type.
*/
typedef struct {
volatile int counter;
} atomic_t;
#define ATOMIC_INIT(i) { (i) }
/**
* Read atomic variable
* @param v pointer of type atomic_t
*
* Atomically reads the value of @v.
*/
#define atomic_read(v) ((v)->counter)
/**
* Set atomic variable
* @param v pointer of type atomic_t
* @param i required value
*/
#define atomic_set(v,i) (((v)->counter) = (i))
/**
* Add to the atomic variable
* @param i integer value to add
* @param v pointer of type atomic_t
*/
static inline void atomic_add( int i, atomic_t *v )
{
(void)__sync_add_and_fetch(&v->counter, i);
}
/**
* Subtract the atomic variable
* @param i integer value to subtract
* @param v pointer of type atomic_t
*
* Atomically subtracts @i from @v.
*/
static inline void atomic_sub( int i, atomic_t *v )
{
(void)__sync_sub_and_fetch(&v->counter, i);
}
/**
* Subtract value from variable and test result
* @param i integer value to subtract
* @param v pointer of type atomic_t
*
* Atomically subtracts @i from @v and returns
* true if the result is zero, or false for all
* other cases.
*/
static inline int atomic_sub_and_test( int i, atomic_t *v )
{
return !(__sync_sub_and_fetch(&v->counter, i));
}
/**
* Increment atomic variable
* @param v pointer of type atomic_t
*
* Atomically increments @v by 1.
*/
static inline void atomic_inc( atomic_t *v )
{
(void)__sync_fetch_and_add(&v->counter, 1);
}
/**
* @brief decrement atomic variable
* @param v: pointer of type atomic_t
*
* Atomically decrements @v by 1. Note that the guaranteed
* useful range of an atomic_t is only 24 bits.
*/
static inline void atomic_dec( atomic_t *v )
{
(void)__sync_fetch_and_sub(&v->counter, 1);
}
/**
* @brief Decrement and test
* @param v pointer of type atomic_t
*
* Atomically decrements @v by 1 and
* returns true if the result is 0, or false for all other
* cases.
*/
static inline int atomic_dec_and_test( atomic_t *v )
{
return !(__sync_sub_and_fetch(&v->counter, 1));
}
/**
* @brief Increment and test
* @param v pointer of type atomic_t
*
* Atomically increments @v by 1
* and returns true if the result is zero, or false for all
* other cases.
*/
static inline int atomic_inc_and_test( atomic_t *v )
{
return !(__sync_add_and_fetch(&v->counter, 1));
}
/**
* @brief add and test if negative
* @param v pointer of type atomic_t
* @param i integer value to add
*
* Atomically adds @i to @v and returns true
* if the result is negative, or false when
* result is greater than or equal to zero.
*/
static inline int atomic_add_negative( int i, atomic_t *v )
{
return (__sync_add_and_fetch(&v->counter, i) < 0);
}
#endif
参考:
http://golubenco.org/blog/atomic-operations/
http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html
http://hi.baidu.com/wrap/blog/item/d8e40f2e7fb022554fc226a0.html
http://bugs.mysql.com/bug.php?id=34175