Linux内核中的cmpxchg函数
http://www.longene.org/forum/viewtopic.php?t=2216
在Linux内核中,提供了比较并交换的函数cmpxchg,代码在include/asm-i386/cmpxchg.h中,函数的原型是:
- 代码: 全选
cmpxchg(void *ptr, unsigned long old, unsigned long new);
函数完成的功能是:将old和ptr指向的内容比较,如果相等,则将new写入到ptr中,返回old,如果不相等,则返回ptr指向的内容。
在linux中的实现是这样的。
- 代码: 全选
#define cmpxchg(ptr,o,n)\
((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
(unsigned long)(n),sizeof(*(ptr))))
很明显,这个函数就是调用了__cmpxchg。
- 代码: 全选
static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
unsigned long new, int size)
{
unsigned long prev;
switch (size) {
case 1:
__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
: "=a"(prev)
: "q"(new), "m"(*__xg(ptr)), "0"(old)
: "memory");
return prev;
case 2:
__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
: "=a"(prev)
: "r"(new), "m"(*__xg(ptr)), "0"(old)
: "memory");
return prev;
case 4:
__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
: "=a"(prev)
: "r"(new), "m"(*__xg(ptr)), "0"(old)
: "memory");
return prev;
}
return old;
}
以最为常用的4字节交换为例,主要的操作就是汇编指令cmpxchgl %1,%2,注意一下其中的%2,也就是后面的"m"(*__xg(ptr))。
__xg是在这个文件中定义的宏:
struct __xchg_dummy { unsigned long a[100]; };
#define __xg(x) ((struct __xchg_dummy *)(x))
那么%2经过预处理,展开就是"m"(*((struct __xchg_dummy *)(ptr))),这种做法,就可以达到在cmpxchg中的%2是一个地址,就是ptr指向的地址。如果%2是"m"(ptr),那么指针本身的值就出现在cmpxchg指令中。
我手头有一份《奔腾指令速查》,其中对cmpxchg的说明是这样的:
- 代码: 全选
CMPXCHG r/m32,r32 0F B1 /r CMPXCHG EBX,ECX ;如果EAX与EBX相等,则ECX送EBX且ZF置1;否则EBX送ECX,且ZF清0
文章里用的是MS的汇编格式,换成AT&T的格式就是:
- 代码: 全选
cmpxchg %ecx, %ebx;如果EAX与EBX相等,则ECX送EBX且ZF置1;否则EBX送ECX,且ZF清0
在上述例子中,eax就是old,ebx就是ptr指向的内容,ecx就是new。所以cmpxchg指令的操作就是:如果old等于ptr指向的内容,那么就把new写入到ptr中,返回old(%eax没有改变过,一直是old),这部分和cmpxchg函数的原意是符合的;如果old不等于ptr指向的内容,那么ptr的内容写入new(%ecx)中,返回old(%eax没有改变过,一直是old),这明显不符合cmpxchg函数的意思。对此是大惑不解,后来经过Google才知道,那份资料有错。正解是:
- 代码: 全选
cmpxchg %ecx, %ebx;如果EAX与EBX相等,则ECX送EBX且ZF置1;否则EBX送EAX,且ZF清0
也就是说,在old和ptr指向的内容不相等的时候,将ptr的内容写入eax中,这样,ptr的内容就会返回给cmpxchg函数的调用者。这样就和原意相符合了。
Linux内核中的cmpxchg函数的更多相关文章
- linux内核中的排序接口--sort函数
linux内核中的sort函数,其实跟我们所说的qsort函数很像,我们来看看qsort: qsort 的函数原型是 void qsort(void*base,size_t num,size_t wi ...
- Linux 编程中的API函数和系统调用的关系【转】
转自:http://blog.chinaunix.net/uid-25968088-id-3426027.html 原文地址:Linux 编程中的API函数和系统调用的关系 作者:up哥小号 API: ...
- Linux内核中常见内存分配函数【转】
转自:http://blog.csdn.net/wzhwho/article/details/4996510 1. 原理说明 Linux内核中采用了一种同时适用于32位和64位系统的内存分页 ...
- (笔记)Linux内核中内存相关的操作函数
linux内核中内存相关的操作函数 1.kmalloc()/kfree() static __always_inline void *kmalloc(size_t size, gfp_t flags) ...
- Linux内核中常见内存分配函数
1. 原理说明 Linux内核中采用了一种同时适用于32位和64位系统的内存分页模型,对于32位系统来说,两级页表足够用了,而在x86_64系统中,用到了四级页表,如图2-1所示.四级页表分 ...
- Linux内核中常见内存分配函数(一)
linux内核中采 用了一种同时适用于32位和64位系统的内存分页模型,对于32位系统来说,两级页表足够用了,而在x86_64系 统中,用到了四级页表. * 页全局目录(Page Global Dir ...
- linux内核中打印栈回溯信息 - dump_stack()函数分析【转】
转自:http://blog.csdn.net/jasonchen_gbd/article/details/45585133 版权声明:本文为博主原创文章,转载请附上原博链接. 目录(?)[-] ...
- Linux内核中的算法和数据结构
算法和数据结构纷繁复杂,但是对于Linux Kernel开发人员来说重点了解Linux内核中使用到的算法和数据结构很有必要. 在一个国外问答平台stackexchange.com的Theoretica ...
- [翻译] Linux 内核中的位数组和位操作
目录 Linux 内核里的数据结构 原文链接与说明 Linux 内核中的位数组和位操作 位数组声明 体系结构特定的位操作 通用位操作 链接 Linux 内核里的数据结构 原文链接与说明 https:/ ...
随机推荐
- mysql小数和类型转换函数
保留两位小数 SELECT ROUND( 123456789.3563898,2),TRUNCATE(123456789.3563898,2),FORMAT(123456789.3563898,2); ...
- RS chap2:利用用户行为数据
一.用户行为数据简介 1.用户行为在个性化推荐系统中分为两种: (1)显式反馈行为:包括用户明确表示对物品喜好的行为. (2)隐式反馈行为:不能明确反应用户喜好的行为. (3)显式反馈行为和隐式反馈行 ...
- 如何使用前端分页框架bootstrap paginator
前端分页框架bootstrap paginator用于web前端页面快速实现美观大方的翻页功能.在实现交互良好的页面翻页功能时,往往还需要配合使用后端分页框架pagehelper.pagehelper ...
- Linux RAID磁盘阵列
RAID磁盘阵列 什么是RAID RAID是磁盘阵列的英文缩写,多块磁盘组成了一个组合,一起完成存储任务,就是磁盘阵列. RAID几种常用的类别(组合) RAID0:条带卷:最低磁盘个数2+,空间利用 ...
- 文件I/O编程 (fcntl)
Fcntl函数语法要点所需头文件:#include #include #include函数原型:int fcntl(int fd,cmd,struct flock ...
- 008-zabbix监控nginx
(1)agent端配置 1)nginx编译安装需要加上该选项--with-http_stub_status_module 2)修改nginx配置文件 #vim /usr/local/nginx/con ...
- 条件随机场CRF介绍
链接:https://mp.weixin.qq.com/s/BEjj5zJG3QmxvQiqs8P4-w softmax CRF主要用于序列标注问题,可以简单理解为是给序列中的每一帧,既然是分类,很自 ...
- Luogu P2619 [国家集训队2]Tree I 凸优化,wqs二分
新学的科技.设\(f(x)\)为选\(x\)条白色边的时候的最小生成树权值和,那么可以猜到它应该是一个下凸函数的形式. 如图,图中\(x\)坐标表示选的白色边条数,\(y\)坐标表示获得的权值,那么我 ...
- 一个web应用的诞生(7)
现在所有的Py代码均写在default.py文件中,很明显这种方法下,一旦程序变的负责,那么无论对于开发和维护来说,都会带来很多问题. Flask框架并不强制要求项目使用特定的组织结构,所以这里使用的 ...
- IPython的简单介绍
量化投资与Python 目录: 一.量化投资第三方相关模块 NumPy:数组批量计算 Pandas:表计算与数据分析 Matplotlib:图表绘制 二.IPython的介绍 IPython:和Pyt ...