分享
 
 
 

原子操作

王朝百科·作者佚名  2010-01-27
窄屏简体版  字體: |||超大  

在多进程(线程)访问资源时,能够确保所有其他的进程(线程)都不在同一时间内访问相同的资源。

原子操作:UP和SMP的异同

-----------------------------------------------------------

原子操作是不可分割的,在执行完毕不会被任何其它任务或事件中断。在单处理器系统(UniProcessor)中,能够在单条指令中完成的操作都可以认为是" 原子操作",因为中断只能发生于指令之间。这也是某些CPU指令系统中引入了test_and_set、test_and_clear等指令用于临界资源互斥的原因。但是,在对称多处理器(Symmetric Multi-Processor)结构中就不同了,由于系统中有多个处理器在独立地运行,即使能在单条指令中完成的操作也有可能受到干扰。我们以decl (递减指令)为例,这是一个典型的"读-改-写"过程,涉及两次内存访问。设想在不同CPU运行的两个进程都在递减某个计数值,可能发生的情况是:

1. CPU A(CPU A上所运行的进程,以下同)从内存单元把当前计数值(2)装载进它的寄存器中;

2. CPU B从内存单元把当前计数值(2)装载进它的寄存器中。

3. CPU A在它的寄存器中将计数值递减为1;

4. CPU B在它的寄存器中将计数值递减为1;

5. CPU A把修改后的计数值(1)写回内存单元。

6. CPU B把修改后的计数值(1)写回内存单元。

我们看到,内存里的计数值应该是0,然而它却是1。如果该计数值是一个共享资源的引用计数,每个进程都在递减后把该值与0进行比较,从而确定是否需要释放该共享资源。这时,两个进程都去掉了对该共享资源的引用,但没有一个进程能够释放它--两个进程都推断出:计数值是1,共享资源仍然在被使用。

原子性不可能由软件单独保证--必须需要硬件的支持,因此是和架构相关的。在x86 平台上,CPU提供了在指令执行期间对总线加锁的手段。CPU芯片上有一条引线#HLOCK pin,如果汇编语言的程序中在一条指令前面加上前缀"LOCK",经过汇编以后的机器代码就使CPU在执行这条指令的时候把#HLOCK pin的电位拉低,持续到这条指令结束时放开,从而把总线锁住,这样同一总线上别的CPU就暂时不能通过总线访问内存了,保证了这条指令在多处理器环境中的原子性。

Linux内核中的原子操作

-----------------------------------------------------------

原子操作大部分使用汇编语言实现,因为c语言并不能实现这样的操作。

* 在x86的原子操作实现代码中,定义了LOCK宏,这个宏可以放在随后的内联汇编指令之前。如果是SMP,LOCK宏被扩展为lock指令;否则被定义为空 -- 单CPU无需防止其它CPU的干扰,锁内存总线完全是在浪费时间。

#ifdef CONFIG_SMP

#define LOCK "lock ; "

#else

#define LOCK ""

#endif

* typedef struct { volatile int counter; } atomic_t;

在所有支持的体系结构上原子类型atomic_t都保存一个int值。在x86的某些处理器上,由于工作方式的原因,原子类型能够保证的可用范围只有24位。volatile是一个类型描述符,要求编译器不要对其描述的对象作优化处理,对它的读写都需要从内存中访问。

* #define ATOMIC_INIT(i) { (i) }

用于在定义原子变量时,初始化为指定的值。如:

static atomic_t count = ATOMIC_INIT(1);

* static __inline__ void atomic_add(int i, atomic_t *v)

----------------------------------------

将v指向的原子变量加上i。该函数不关心原子变量的新值,返回void类型。

在下面的实现中,使用了带有C/C++表达式的内联汇编代码,格式如下(参考《AT&T ASM Syntax》):

__asm__ __volatile__("Instruction List" : Output : Input : Clobber/Modify);

__asm__ __volatile__指示编译器原封不动保留表达式中的汇编指令系列,不要考虑优化处理。涉及的约束还包括:

1. 等号约束(=):只能用于输出操作表达式约束,说明括号内的左值表达式v->counter是write-only的。

2. 内存约束(m):表示使用不需要借助寄存器,直接使用内存方式进行输入或输出。

3. 立即数约束(i):表示输入表达式是一个立即数(整数),不需要借助任何寄存器。

4. 寄存器约束(r):表示使用一个通用寄存器,由GCC在%eax/%ax/%al、%ebx/%bx/%bl、%ecx/%cx/%cl和%edx/%dx/%dl中选取一个合适的。

{

__asm__ __volatile__(

LOCK "addl %1,%0"

:"=m" (v->counter)

:"ir" (i), "m" (v->counter));

}

* static __inline__ int atomic_sub_and_test(int i, atomic_t *v)

----------------------------------------

从v 指向的原子变量减去i,并测试是否为0。若为0,返回真,否则返回假。由于x86的subl指令会在结果为0时设置CPU的zero标志位,而且这个标志位是CPU私有的,不会被其它CPU影响。因此,可以执行一次加锁的减操作,再根据CPU的zero标志位来设置本地变量c,并相应返回。

{

unsigned char c;

__asm__ __volatile__(

LOCK "subl %2,%0; sete %1"

:"=m" (v->counter), "=qm" (c)

:"ir" (i), "m" (v->counter) : "memory");

return c;

}

------------------------------------

#define atomic_read(v) ((v)->counter)

读取v指向的原子变量的值。由于该操作本身就是原子的,只需要一次内存访问就能完成,因此定义为一个宏,并用C代码实现。

#define atomic_set(v,i) (((v)->counter) = (i))

设置v指向的原子变量的值为i。由于该操作本身就是原子的,只需要一次内存访问就能完成,因此定义为一个宏,并用C代码实现。

static __inline__ void atomic_sub(int i, atomic_t *v)

从v指向的原子变量减去i。

static __inline__ void atomic_inc(atomic_t *v)

递增v指向的原子变量。

static __inline__ void atomic_dec(atomic_t *v)

递减v指向的原子变量。

static __inline__ int atomic_dec_and_test(atomic_t *v)

递减v指向的原子变量,并测试是否为0。若为0,返回真,否则返回假。

static __inline__ int atomic_inc_and_test(atomic_t *v)

递增v指向的原子变量,并测试是否为0。若为0,返回真,否则返回假。

static __inline__ int atomic_add_negative(int i, atomic_t *v)

将v指向的原子变量加上i,并测试结果是否为负。若为负,返回真,否则返回假。这个操作用于实现semaphore。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有