ILD

Kernel Synchronization 1: atomic operation
作者:YUAN JIANPENG 邮箱:yuanjp@hust.edu.cn
发布时间:2018-8-20 站点:Inside Linux Development

 Causes of Concurrency

内核中,下面的东西会导致并发

中断

软中断和任务队列

内核抢占

Sleeping and synchronization with user-space

Symmetrical multiprocessing


Atomic Operations

在很多体系架构中,对齐的CPU字长的内存读写通常为原子操作。但是也提供了很多的指令来实现多操作的原子操作,这些指令可以用来实现锁原语。


内核提供两种原子操作。一种是整数原子操作;一种是位原子操作。


Atomic Integer Operations

这些方法操作在一个特殊的数据类型: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 OperationDesc
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。


Atomic Bitwise Operations

位原子操作,定义在<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 OperationDescription
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()接口。


Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.