用户空间原子操作的实现|用户空间,原子操作,lock,atomic-中国源码网

来源:百度文库 编辑:神马文学网 时间:2024/04/26 14:00:11

用户空间原子操作的实现

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

中国源码网内相关主题链接
  • PowerPC原子操作源码
  • OpenMP线程中锁及原子操作性能...
  • Unix系统的原子操作
  • 用户空间原子操作的实现
  • 利用mmap实现用户空间驱动的理解
  • OpenMP创建线程中锁及原子操作...
  • Linux 2.6内核抢占和spinlock
  • Spinlock编程
  • 使用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