您的位置:首页 > 其它

原子位操作

2016-02-10 22:49 316 查看
include/asm-generic/bitops

针对SMP与非SMP:

#include <asm/types.h>
#include <linux/irqflags.h>

#ifdef CONFIG_SMP
#include <asm/spinlock.h>
#include <asm/cache.h>          /* we use L1_CACHE_BYTES */

/* Use an array of spinlocks for our atomic_ts.
* Hash function to index into a different SPINLOCK.
* Since "a" is usually an address, use one spinlock per cacheline.
*/
#  define ATOMIC_HASH_SIZE 4
#  define ATOMIC_HASH(a) (&(__atomic_hash[ (((unsigned long) a)/L1_CACHE_BYTES) & (ATOMIC_HASH_SIZE-1) ]))

extern arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned;

/* Can't use raw_spin_lock_irq because of #include problems, so
* this is the substitute */
#define _atomic_spin_lock_irqsave(l,f) do {     \
arch_spinlock_t *s = ATOMIC_HASH(l);    \
local_irq_save(f);                      \
arch_spin_lock(s);                      \
} while(0)

#define _atomic_spin_unlock_irqrestore(l,f) do {        \
arch_spinlock_t *s = ATOMIC_HASH(l);            \
arch_spin_unlock(s);                            \
local_irq_restore(f);                           \
} while(0)

#else
#  define _atomic_spin_lock_irqsave(l,f) do { local_irq_save(f); } while (0)
#  define _atomic_spin_unlock_irqrestore(l,f) do { local_irq_restore(f); } while (0)
#endif


置位:

static inline void set_bit(int nr, volatile unsigned long *addr)
{
unsigned long mask = BIT_MASK(nr);
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
unsigned long flags;

_atomic_spin_lock_irqsave(p, flags);
*p  |= mask;
_atomic_spin_unlock_irqrestore(p, flags);
}

等。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: