当前位置: 首页 >> 程序设计 >> 用户空间原子操作的实现
 

用户空间原子操作的实现

作者:      来源:cudev     发表时间:2008-09-27     浏览次数:      字号:    

使用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

编辑 webmaster

 
 
 
评论更多>>
 
标明出处~~
 
发表
 
姓名: QQ:
性别: MSN:
E-mail: 主页:
评分: 1 2 3 4 5
评论内容:
验证码:
  
  • 请遵守《互联网电子公告服务管理规定》及中华人民共和国其他各项有关法律法规。
  • 严禁发表危害国家安全、损害国家利益、破坏民族团结、破坏国家宗教政策、破坏社会稳定、侮辱、诽谤、教唆、淫秽等内容的评论 。
  • 用户需对自己在使用本站服务过程中的行为承担法律责任(直接或间接导致的)。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表网友个人观点,与本网站立场无关。
  •