linux内核同步(2)--原子操作

内核同步方法主要有:原子操作、自旋锁、读写自旋锁、信号量、读写信号、完成变量等。内核提供了两组原子操作接口:一是对整数进行操作;而是对位进行操作。在linux支持的所有体系接口上都实现了这两组接口:要么支持简单的原子操作;要么为单步执行提供锁内存总线的指令。

include\linux\types.h中对原子变量atomic_t进行了定义:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. typedef struct {  
  2.     int counter;  
  3. } atomic_t;  
使用方法:
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. atomic_t V;  
  2. atomic_t V1=ATOMIC_INIT(0);  
  3. atomic_set(&V,4);  
  4. atomic_add(2,&V);  
  5. atomic_inc(&V);  

        原子操作通常是内联函数,通过内嵌汇编来实现。原子性确保执行在执行期间不被打断,要么执行完,要么不执行。顺序性确保即使两条或多条指令出现在独立的线程或者处理器中,但他们本该的执行顺序依然要保持。顺序可以通过屏障(barrier)来实施。

原子操作接口的实现:

arch/arm/include/asm/atomic.h中实现了对原子操作接口的实现(3.10):

atomic_read/atomic_set:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* * On ARM, ordinary assignment (str instruction) doesn't clear the local 
  2.  * strex/ldrex monitor on some implementations. The reason we can use it for 
  3.  * atomic_set() is the clrex or dummy strex done on every exception return. 
  4.  */  
  5. #define atomic_read(v)  (*(volatile int *)&(v)->counter)  
  6. #define atomic_set(v,i) (((v)->counter) = (i))  

atomic_add:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** ARMv6 UP and SMP safe atomic ops.  We use load exclusive and store exclusive to ensure that these are atomic.  We may loop to ensure that the update happens. */  
  2. static inline void atomic_add(int i, atomic_t *v)  
  3. {  
  4.     unsigned long tmp;  
  5.     int result;  
  6.     __asm__ __volatile__("@ atomic_add\n"  
  7. "1: ldrex   %0, [%3]\n"  
  8. "   add %0, %0, %4\n"  
  9. "   strex   %1, %0, [%3]\n"  
  10. "   teq %1, #0\n"  
  11. "   bne 1b"  
  12.     : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)  
  13.     : "r" (&v->counter), "Ir" (i)  
  14.     : "cc");  
  15. }  

atomic_add_return:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static inline int atomic_add_return(int i, atomic_t *v)  
  2. {  
  3.     unsigned long tmp;  
  4.     int result;  
  5.   
  6.     smp_mb();  
  7.   
  8.     __asm__ __volatile__("@ atomic_add_return\n"  
  9. "1: ldrex   %0, [%3]\n"  
  10. "   add %0, %0, %4\n"  
  11. "   strex   %1, %0, [%3]\n"  
  12. "   teq %1, #0\n"  
  13. "   bne 1b"  
  14.     : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)  
  15.     : "r" (&v->counter), "Ir" (i)  
  16.     : "cc");  
  17.   
  18.     smp_mb();  
  19.   
  20.     return result;  
  21. }  

atomic_sub:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static inline void atomic_sub(int i, atomic_t *v)  
  2. {  
  3.     unsigned long tmp;  
  4.     int result;  
  5.   
  6.     __asm__ __volatile__("@ atomic_sub\n"  
  7. "1: ldrex   %0, [%3]\n"  
  8. "   sub %0, %0, %4\n"  
  9. "   strex   %1, %0, [%3]\n"  
  10. "   teq %1, #0\n"  
  11. "   bne 1b"  
  12.     : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)  
  13.     : "r" (&v->counter), "Ir" (i)  
  14.     : "cc");  
  15. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值