DPDK CAS(compare and set)操作
前言
rte_ring是一个无锁队列,无锁队列的出队入队操作是rte_ring实现的关键。因此,本文主要讲解dpdk是怎样使用无锁机制实现rte_ring的多生产者入队操作。
rte_atomic32_cmpset()称为CAS(compare and set)操作,是无锁队列实现的关键
函数原型
static inline int
rte_atomic32_cmpset(volatile uint32_t *dst, uint32_t exp, uint32_t src)
{
uint8_t res;
asm volatile(
"lock;"
"cmpxchgl %[src], %[dst];"
"sete %[res];"
:[res] "=a"(res), /*output*/
[dst] "=m"(*dst)
:[src] "r"(src), /*input*/
"a" (exp),
"m" (*dst)
:"memory"); /* no-clobber list */
return res;
} //函数的作用是:rte_atomic32_cmpset内部比较dst和exp,如果dst和exp相等,那么把src赋值给dst
便于理解,参数可以重命名一下
static inline int rte_atomic32_cmpset(volatile uint32_t *current, uint32_t old, uint32_t next);
内联汇编的基本格式为:
asm [ volatile ] (
assembler template
[ : output operands ] /* optional */
[ : input operands ] /* optional */
[ : list of clobbered registers ] /* optional */
);
asm: asm为gcc关键字,表示接下来要嵌入汇编代码。为避免keyword asm与程序中其它部分产生命名冲突,gcc还支持__asm__关键字,与asm的作用等价。
volatile: 为可选关键字,表示不需要gcc对下面的汇编代码做任何优化。同样出于避免命名冲突的原因,__volatile__也是gcc支持的与volatile等效的关键字。
assembler template:这部分即我们要嵌入的汇编命令,由于我们是在C语言中内联汇编代码,故需用双引号""将命令括起来,以便gcc以字符串形式将这些命令传给汇编器AS。例如可以写成这样:"movl %eax, %ebx"。有时候,汇编命令可能有多个,则通常分多行写,每行的命令都用双引号括起来,命令后紧跟"\n\t"之类的分隔符(当然,也可以只用1对双引号将多行命令括起来,从语法来说,两种写法均有效,我们可自行决定用哪种格式来写)。
output operands: 该字段为可选项,用以指明输出操作数,典型的格式为:
: "=a" (out_var)
其中,"=a"指定output operand的应遵守的约束(constraint),out_var为存放指令结果的变量,通常是个C语言变量。
input operands: 该字段为可选项,用以指明输入操作数,其典型格式为:
: "constraints" (in_var)
其中,constraints可以是gcc支持的各种约束方式,in_var通常为C语言提供的输入变量。
list of clobbered registers : 该字段为可选项,用于列出指令中涉及到的且没出现在output operands字段及input operands字段的那些寄存器。若寄存器被列入clobber-list,则等于是告诉gcc,这些寄存器可能会被内联汇编命令改写。因此,执行内联汇编的过程中,这些寄存器就不会被gcc分配给其它进程或命令使用。
- 我们再来看rte_atomic32_cmpset函数就会清晰很多了
- "lock;"
- > 枷锁,避免多个线程同时执行下面的汇编指令。
- "cmpxchgl %[src], %[dst];"
Cmpxchgl指令有三个操作数,dst、src和eax寄存器,执行结果会影响dst和ZF标志位。
指令将dst和eax里的值比较,如果相同,将src里的值赋给dst,同时ZF置位。
Eax寄存器的在c语言掉用汇编的时候,函数入参exp赋给寄存器eax。
那么cmpxchgl实际执行的就是,比较exp(也就是eax)与 dst的值,如果相等,那么将src的值赋值给dst
"sete %[res];"
sete这个命令,是set+equeal,就是上面Cmpxchgl比较结果如果相等,则set ZF,并把值赋给res
入参属性:
1、[src] "r" (src),
Src是个寄存器变量(普通register,也就是eax,ebx,ecx,edx,esi,edi中的一个)
2、"a" (exp),
exp是个寄存器变量,它的值在c语言调用汇编时候,“a”表示的是(eax寄存器),通过这个标识,将exp放在eax寄存器里。
如果eax已经被使用,eax的原来的值会先push到堆栈里,执行完汇编后,再push到eax里。
3、"m" (*dst)
入参dst是个memory变量
出参属性
1、[res] "=a" (res),
汇编函数返回的值
[dst] "=m" (*dst)
dst是个内存变量,这个变量被volatile修饰,是从内存读取的,不是寄存器或者cache缓存的。不想借助于任何寄存器。
常用的寄存器约束的缩写:
- r:I/O,表示使用一个通用寄存器,由GCC在%eax/%ax/%al、%ebx/%bx/%bl、%ecx/%cx/%cl、%edx/%dx/%dl中选取一个GCC认为是合适的;
- q:I/O,表示使用一个通用寄存器,与r的意义相同;
- g:I/O,表示使用寄存器或内存地址;
- m:I/O,表示使用内存地址;
- a:I/O,表示使用%eax/%ax/%al;
- b:I/O,表示使用%ebx/%bx/%bl;
- c:I/O,表示使用%ecx/%cx/%cl;
- d:I/O,表示使用%edx/%dx/%dl;
- D:I/O,表示使用%edi/%di;
- S:I/O,表示使用%esi/%si;
- f:I/O,表示使用浮点寄存器;
- t:I/O,表示使用第一个浮点寄存器;
- u:I/O,表示使用第二个浮点寄存器;
- A:I/O,表示把%eax与%edx组合成一个64位的整数值;
- o:I/O,表示使用一个内存位置的偏移量;
- V:I/O,表示仅仅使用一个直接内存位置;
- i:I/O,表示使用一个整数类型的立即数;
- n:I/O,表示使用一个带有已知整数值的立即数;
- F:I/O,表示使用一个浮点类型的立即数;
测试rte_atomic32_cmpset 函数
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <pthread.h>
static inline int
rte_atomic32_cmpset(volatile uint32_t *dst, uint32_t exp, uint32_t src)
{
uint8_t res;
asm volatile(
"lock;"
"cmpxchgl %[src], %[dst];"
"sete %[res];"
:[res] "=a"(res), /*output*/
[dst] "=m"(*dst)
:[src] "r"(src), /*input*/
"a" (exp),
"m" (*dst)
:"memory"); /* no-clobber list */
return res;
}
volatile uint32_t sum = 0;
void *func()
{
uint32_t last_sum = 0;
for(int i = 0; i < 100000; i++)
{
while(!rte_atomic32_cmpset(&sum, last_sum, last_sum + 1))
{
last_sum = sum;
}
}
}
int main()
{
pthread_t pid1, pid2;
pthread_create(&pid1, NULL, func, NULL);
pthread_create(&pid2, NULL, func, NULL);
pthread_join(pid1, NULL);
pthread_join(pid2, NULL);
printf("sum = %d\n", sum);
return 0;
}
编译时加上 -lpthread
DPDK CAS(compare and set)操作的更多相关文章
- 无锁机制----比较交换CAS Compare And Swap
一.锁与共享变量 加锁是一种悲观的策略,它总是认为每次访问共享资源的时候,总会发生冲突,所以宁愿牺牲性能(时间)来保证数据安全. 无锁是一种乐观的策略,它假设线程访问共享资源不会发生冲突,所以不需要加 ...
- CAS(Compare and Swap)无锁算法-学习笔记
非阻塞同步算法与CAS(Compare and Swap)无锁算法 这篇问题对java的CAS讲的非常透彻! 锁的代价 1. 内核态的锁的时候需要操作系统进行一次上下文切换,加锁.释放锁会导致比较多的 ...
- 浅谈CAS(Compare and Swap) 原理
浅谈CAS原理java并发编程也研究了一段时间了,对CAS的原理总是不太理解,今天再研究了一下,记录一些自己的理解. 说到CAS,再java中的某些情况下,甚至jdk1.5以后的大多数情况,并发 ...
- 非阻塞同步算法与CAS(Compare and Swap)无锁算法
锁(lock)的代价 锁是用来做并发最简单的方式,当然其代价也是最高的.内核态的锁的时候需要操作系统进行一次上下文切换,加锁.释放锁会导致比较多的上下文切换和调度延时,等待锁的线程会被挂起直至锁释放. ...
- CAS(Compare and Swap)理解
什么叫CAS(Compare and Swap)? 硬件同步原语!! 什么蛋疼的名字,一般人很难理解.根据英文全称翻译==比较与交换,这个名字大致还能理解一点,目前先暂且这么理解吧. 有啥用处? 对 ...
- 【Java并发编程】9、非阻塞同步算法与CAS(Compare and Swap)无锁算法
转自:http://www.cnblogs.com/Mainz/p/3546347.html?utm_source=tuicool&utm_medium=referral 锁(lock)的代价 ...
- CAS (Compare and Swap)
synchronized是悲观锁 注意:实现了CAS的有原子类(AtomicInteger,AtomicLong,等等原子类) CAS 是乐观锁,一种高效实现线程安全性的方法 1.支持原子更新操作,适 ...
- 使用CAS实现无锁的SkipList
无锁 并发环境下最常用的同步手段是互斥锁和读写锁,例如pthread_mutex和pthread_readwrite_lock,常用的范式为: void ConcurrencyOperation() ...
- 线程安全(中)--彻底搞懂synchronized(从偏向锁到重量级锁)
接触过线程安全的同学想必都使用过synchronized这个关键字,在java同步代码快中,synchronized的使用方式无非有两个: 通过对一个对象进行加锁来实现同步,如下面代码. synchr ...
随机推荐
- Java学习_Java快速入门
Java简介 安装完JDK后,需要设置一个JAVA_HOME的环境变量,它指向JDK的安装目录.在Windows下,它是安装目录,类似: C:\Program Files\Java\jdk-15 把J ...
- MM-采购模块相关业务
采购模块主要业务流程: 1.收集采购需求(采购申请单),系统采购申请单单据可以由需求部门手工产生,也可以由系统的MRP(物料需求计划)来产生. 2,货源确定,用来确定所申请的物料,通过何种方式向供应商 ...
- hadoop伪分布式平台组件搭建
第一部分:系统基础配置 系统基础配置中主完成了安装大数据环境之前的基础配置,如防火墙配置和安装MySQL.JDK安装等 第一步:关闭防火墙 Hadoop与其他组件的服务需要通过端口进行通信,防火墙的存 ...
- sql文件转换为excel文件
最近经常需要把sql整理成excel,本人比较懒,所以写一个小工具,用到了jxl包.以前没有接触过,正好了解一下. 一.基础知识 jxl操作excel包括对象 Workbook,Sheet ...
- Kubernetes官方java客户端之五:proto基本操作
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- docker学习之路(安装、使用)
一.docker安装 1.更新现有的yum包 yum update 2.配置docker yum源 [root@docker ~]# cat /etc/yum.repos.d/docker.repo ...
- 双重校验锁 --使用volatile和两次判空校验
介绍 双重校验锁是单例模式中,饿汉式的一种实现方式.因为有两次判空校验,所以叫双重校验锁,一次是在同步代码块外,一次是在同步代码块内. 为什么在同步代码块内还要再检验一次? 第一个if减少性能开销,第 ...
- chatsRoom Design Report
基于TCP实现聊天室 主要使用四个类 ChatClient类 使用BufferedReader 得到输入流,使用OutputStream得到输出流 实现读取服务器广播的消息和发送消息到 ...
- Python在项目外更改项目内引用
前言 目前有一个奇葩的需求, 将某个开源项目整合进自己的项目里去调度, 还需要在每次启动这个开源项目时, 加载不同的配置文件进去, 问题是配置文件并不是一个 conf 或者是其他的什么, 而是以 .p ...
- 【剑指 Offer】08.二叉树的下一个节点
题目描述 给定一颗二叉树和其中的一个节点,找出中序遍历序列的下一个节点.树中的节点除了有两个分别指向左右节点的指针,还有一个指向父节点的指针. Java public class Solution08 ...