原子操作
来源:互联网 发布:java数组二分查找 编辑:程序博客网 时间:2024/05/17 01:25
所谓原子操作,是指不能被cpu和其他cpu所中断的执行指令或指令流
原子操作需要硬件的支持,因此是架构相关的,其API和原子类型的定义都定义在内核源码树的include/asm/atomic.h文件中,它们都使用汇编语言实现,因为C语言并不能实现这样的操作。
原子操作的实现
CPU基本的原子操作
LOCK前缀
自动带LOCK的指令
CPU平台本身可以保证的原子操作
-读或者写一个字节
-读或者写一个对齐的16-bit数据
-读或者写一个对齐的32-bit数据
-读或者写一个对齐的64-bit数据(64位CPU)
另外:
在32-bit的数据总线上访问一块cache禁止的16位数据(>=Petiunm)
在一个cache line中访问不对其的 16,32,64位数据(>=P6 pamily)
LOCK前缀
-指令前带LOCK前缀迫使CPU做独占的内存访问
-XCHG自动带有LOCK前缀
LOCK在不同CPU版本的实现
-在较老的CPU上,产生LOCK信号以用来锁总线
-在>=P6 family,锁cache line
代码示例:
cmpxchg(ptr.old, new):比较*ptr和old的值,如果相等则*ptr = new.在任何时候该函数返回ptr的初始值.因此,如果想要知道ptr的值是否被New替换,只需要检查其返回值是否与old相等。
自动带LOCK前缀的指令
-xchg
-事物内存(TSX on intel)
可以自定义一块transaction region,然后可以在区域结束的时候原子提交,如果成功提交,则其他CPU可以看到该区域的所有更改,如果提交失败则撤销该区域的所有更改操作,进而转入到程序提供的abort代码。
两种主要的类型
-atomic_t的数据
-bit操作
-其他指令
定义:
atomic_t的操作
-所有的操作都定义在include/linux/atomic.h中以及include/asm/atomic.h中
-常用的atomic操作:
ATOMIC_INIT(i)
atomic_set(v,i)
automic_read(v)
automic_add(i,v)
atomic_sub(i,v)
atomic_inc(v)
atomic_dec(v)
atomic_inc_add_test(v) /*测试新值是否为0*/
atomic_dec_add_test(v)
atomic_xchg(v,new)
atomic_cmpxchg(v,old,new)
atomic_add_negative(i,v) /*测试新值是否为负*/
atomic_add_unless(v,a,u) /*如果v不为u,则v加上a,返回非0,否则直接返回0*/
bit操作
-原子性的位操作
-常用的原子位操作
set_bit(nr, *addr)
clear_bit(nr, *addr)
test_bit(nr, *addr)
change_bit(nr, *addr)
test_and_set_bit(nr, addr) /*测试旧位是否已经设置*/
test_and_clear_bit(nr, *addr)
test_and_change_bit(nr, *addr)
-另外,非原子的位操作
__set_bit(nr, *addr)
__clear_bit(nr, *addr)
test_bit(nr, *addr)
__change_bit(nr, *addr)
__test_and_set_bit(nr, addr) /*测试旧位是否已经设置*/
其他指令(包含原子)
- xchg()
- cmpxchg()
- cmpxchg_double()
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/atomic.h>
- #include <linux/delay.h>
- #include <linux/kthread.h>
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Chen");
- MODULE_DESCRIPTION("The module for atomic");
- #define MAX_KTHREAD 10
- static unsigned long my_bits;
- static void show_my_data(void)
- {
- int i, bits = sizeof(my_bits) * 8;
- for (i = 0; i < bits; i++) {
- int set = test_bit(i, &my_bits);
- if (set)
- printk("bit %d is set\n", i);
- }
- }
- static struct task_struct *threads[MAX_KTHREAD];
- static int thread_do(void *data)
- {
- long i = (long)data;
- printk("thread %ld is running...\n", i);
- set_bit(i, &my_bits);
- set_bit(i + MAX_KTHREAD, &my_bits);
- while(!kthread_should_stop()) {
- msleep(10);
- }
- return 0;
- }
- static int create_threads(void)
- {
- int i;
- for (i = 0; i < MAX_KTHREAD; i++) {
- struct task_struct *thread;
- thread = kthread_run(thread_do, (void *)(long)i, "thread-%d", i);
- if (IS_ERR(thread))
- return -1;
- threads[i] = thread;
- }
- return 0;
- }
- static void cleanup_threads(void)
- {
- int i;
- for(i = 0; i < MAX_KTHREAD; i++)
- if (threads[i])
- kthread_stop(threads[i]);
- }
- static __init int minit(void)
- {
- printk("call %s.\n", __FUNCTION__);
- if (create_threads())
- goto err;
- return 0;
- err:
- cleanup_threads();
- return -1;
- }
- static __exit void mexit(void)
- {
- printk("call %s.\n", __FUNCTION__);
- cleanup_threads();
- show_my_data();
- }
- module_init(minit);
- module_exit(mexit);
上一篇:c++中使用Ctags
下一篇:(一)洞悉linux下的Netfilter&iptables:什么是Netfilter?
- atomic_inc 原子操作
- 实战Java高并发程序设计5】让...
- 原子操作
- Linux字符设备驱动之按键驱动...
- Linux 内核的同步机制--原子操...
- linux 常见服务端口
- xmanager 2.0 for linux配置
- 【ROOTFS搭建】busybox的httpd...
- openwrt中luci学习笔记
- 什么是shell
- linux dhcp peizhi roc
- 关于Unix文件的软链接
- 求教这个命令什么意思,我是新...
- sed -e "/grep/d" 是什么意思...
- 谁能够帮我解决LINUX 2.6 10...
- 原子操作
- 原子操作
- 原子操作
- 原子操作
- 原子操作
- 原子操作
- 原子操作
- 原子操作
- 原子操作
- 原子操作
- 原子操作
- 原子操作
- 原子操作
- 原子操作
- 原子操作
- 原子操作
- 原子操作
- 原子操作
- 8.可变对象(无序表和有序表——含java库中应用)
- LoRa笔记02 LoRa sx1276 sx1278的发射功率研究
- 不可睡眠锁:RCU read-copy-updat
- 可睡眠锁 互斥量、信号量、读写信号量、完成变量
- c++中使用Ctags
- 原子操作
- (一)洞悉linux下的Netfilter&iptables:什么是Netfilter?
- opencv2—(6)基于类的图像处理程序设计
- 简单字符驱动程序mycdev_globalmem.c
- C#多线程学习(一)
- intrins.h头文件
- I2C接口
- 进程管理—进程描述符(task_struct)
- 安卓沉浸式状态栏初体验