内核中,下面的东西会导致并发
中断
软中断和任务队列
内核抢占
Sleeping and synchronization with user-space
Symmetrical multiprocessing
在很多体系架构中,对齐的CPU字长的内存读写通常为原子操作。但是也提供了很多的指令来实现多操作的原子操作,这些指令可以用来实现锁原语。
内核提供两种原子操作。一种是整数原子操作;一种是位原子操作。
这些方法操作在一个特殊的数据类型:atomic_t。定义在<linux/types.h>
1 2 3 | typedef struct { volatile int counter; } atomic_t; |
使用原子操作需要的声明在<asm/atomic.h>
定义和初始化
1 2 | atomic_t v; atomic_t u = ATOMIC_INIT(0); |
读取其整数,使用atomic_read()
1 | printk(“%d\n”, atomic_read(&v)); |
Atomic Integer Methods
Atomic Integer Operation | Desc |
void atomic_set(atomic_t *v, int i) | |
void atomic_add(int i, atomic_t *v) | |
void atomic_sub(int i, atomic_t *v) | |
void atomic_inc(atomic_t *v) | |
void atomic_dec(atomic_t *v) | |
int atomic_sub_and_test(int i, atomic_t *v) | |
int atomic_add_negative(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(int i, atomic_t *v) | |
int atomic_dec_return(int i, atomic_t *v) | |
int atomic_dec_and_test(atomic_t *v) | |
int atomic_inc_and_test(atomic_t *v) |
64-bit Atomic Operations
扩展为64位原子操作。类型atomic64_t,接口如atomic64_set。
位原子操作,定义在<asm/bitops.h>,这些接口接收的是以一个指向整数的地址,这个整数没有必要是volatile的。Aarch64架构中,位操作使用汇编编写,实现在arch/arm64/lib/bitops.S,所以不存在编译器优化,不需要声明为volatile。
简单的例子:
1 2 | unsigned long word = 0; set_bit(0, &word); |
atomic bitwise method
Atomic Bitwise Operation | Description |
void set_bit(int nr, void *addr) | |
void clear_bit(int nr, void *addr) | |
void change_bit(int nr, void *addr) | |
int test_and_set_bit(int nr, void *addr) | 位设置为1,并返回之前的值。 |
int test_and_clear_bit(int nr, void *addr) | |
int test_and_change_bit(int nr, void *addr) | |
int test_bit(int nr, void *addr) |
内核也提供了非原子操作的接口,前面有个双下划线,如__test_bit()
内核还提供两个接口,来查找第一个设置的或清零的位:
1 2 | int find_first_bit(unsigned long *addr, unsigned int size) int find_first_zero_bit(unsigned long *addr, unsigned int size) |
如果你的代码是搜索一个word长度,使用__ffs()和ffz()接口。