转载:GCC 提供的原子操作
转载自:GCC 提供的原子操作

GCC 提供的原子操作

gcc从4.1.2提供了__sync_*系列的built-in函数,用于提供加减和逻辑运算的原子操作。

其声明如下:

type __sync_fetch_and_add (type *ptr, type value, ...)
type __sync_fetch_and_sub (type *ptr, type value, ...)
type __sync_fetch_and_or (type *ptr, type value, ...)
type __sync_fetch_and_and (type *ptr, type value, ...)
type __sync_fetch_and_xor (type *ptr, type value, ...)
type __sync_fetch_and_nand (type *ptr, type value, ...)

type __sync_add_and_fetch (type *ptr, type value, ...)
type __sync_sub_and_fetch (type *ptr, type value, ...)
type __sync_or_and_fetch (type *ptr, type value, ...)
type __sync_and_and_fetch (type *ptr, type value, ...)
type __sync_xor_and_fetch (type *ptr, type value, ...)
type __sync_nand_and_fetch (type *ptr, type value, ...)

这两组函数的区别在于第一组返回更新前的值,第二组返回更新后的值。

type可以是1,2,4或8字节长度的int类型,即:


int8_t / uint8_t
int16_t / uint16_t
int32_t / uint32_t
int64_t / uint64_t

后面的可扩展参数(...)用来指出哪些变量需要memory barrier,因为目前gcc实现的是full barrier(类似于linux kernel 中的mb(),表示这个操作之前的所有内存操作不会被重排序到这个操作之后),所以可以略掉这个参数。


bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)
type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)

这两个函数提供原子的比较和交换,如果*ptr == oldval,就将newval写入*ptr,
第一个函数在相等并写入的情况下返回true.
第二个函数在返回操作之前的值。

__sync_synchronize (...)

发出一个full barrier.

关于memory barrier,cpu会对我们的指令进行排序,一般说来会提高程序的效率,但有时候可能造成我们不希望得到的结果,举一个例子,比如我们有一个硬件设备,它有4个寄存器,当你发出一个操作指令的时候,一个寄存器存的是你的操作指令(比如READ),两个寄存器存的是参数(比如是地址和size),最后一个寄存器是控制寄存器,在所有的参数都设置好之后向其发出指令,设备开始读取参数,执行命令,程序可能如下:

write1(dev.register_size,size);
    write1(dev.register_addr,addr);
    write1(dev.register_cmd,READ);
    write1(dev.register_control,GO);

如果最后一条write1被换到了前几条语句之前,那么肯定不是我们所期望的,这时候我们可以在最后一条语句之前加入一个memory barrier,强制cpu执行完前面的写入以后再执行最后一条:


    write1(dev.register_size,size);
    write1(dev.register_addr,addr);
    write1(dev.register_cmd,READ);
    __sync_synchronize();
    write1(dev.register_control,GO);

memory barrier有几种类型:
    acquire barrier : 不允许将barrier之后的内存读取指令移到barrier之前(linux kernel中的wmb())。
    release barrier : 不允许将barrier之前的内存读取指令移到barrier之后 (linux kernel中的rmb())。
    full barrier    : 以上两种barrier的合集(linux kernel中的mb())。

还有两个函数:

type __sync_lock_test_and_set (type *ptr, type value, ...)
   将*ptr设为value并返回*ptr操作之前的值。

void __sync_lock_release (type *ptr, ...)
     将*ptr置0

示例程序:


#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>

static int count = 0;

void *test_func(void *arg)
{
        int i=0;
        for(i=0;i<20000;++i){
                __sync_fetch_and_add(&count,1);
        }
        return NULL;
}

int main(int argc, const char *argv[])
{
        pthread_t id[20];
        int i = 0;

for(i=0;i<20;++i){
                pthread_create(&id[i],NULL,test_func,NULL);
        }

for(i=0;i<20;++i){
                pthread_join(id[i],NULL);
        }

printf("%d\n",count);
        return 0;
}

参考:

1. http://refspecs.freestandards.org/elf/IA64-SysV-psABI.pdf   section 7.4

2. http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html#Atomic-Builtins

posted on 2017-04-18 16:13 桑海 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/sanghai/p/6728366.html

转载:GCC 提供的原子操作相关推荐

  1. gcc 提供的原子操作

    gcc从4.1.2提供了__sync_*系列的built-in函数,用于提供加减和逻辑运算的原子操作. 其声明如下: type __sync_fetch_and_add (type *ptr, typ ...

  2. GCC提供的builtin函数

    GCC提供了一系列的builtin函数,可以实现一些简单快捷的功能来方便程序编写,另外,很多builtin函数可用来优化编译结果.这些函数以"_builtin"作为函数名前缀. 很 ...

  3. 转载 锁机制与原子操作 第四篇

    一.线程同步中的一些概念 1.1临界区(共享区)的概念 在多线程的环境中,可能需要共同使用一些公共资源,这些资源可能是变量,方法逻辑段等等,这些被多个线程共用的区域统称为临界区(共享区),临界区的资源 ...

  4. Android系统中提供的原子操作

    代码的实现位于文件system/core/include/cutils中 http://androidxref.com/4.4.3_r1.1/xref/system/core/include/cuti ...

  5. linux C/C++服务器后台开发面试题总结

    一.编程语言 1.根据熟悉的语言,谈谈两种语言的区别? 主要浅谈下C/C++和PHP语言的区别: 1)PHP弱类型语言,一种脚本语言,对数据的类型不要求过多,较多的应用于Web应用开发,现在好多互联网 ...

  6. C++面试基础知识点

    C++开发面试基础知识点 1. 语言基础 1.1 const的用法 1)在定义的时候必须进行初始化 2)指针可以是const  指针,也可以是指向const对象的指针 3)定义为const的形参,即在 ...

  7. linux C/C 服务器后台开发面试题总结

    一.编程语言 1.根据熟悉的语言,谈谈两种语言的区别? 主要浅谈下C/C++和PHP语言的区别: 1)PHP弱类型语言,一种脚本语言,对数据的类型不要求过多,较多的应用于Web应用开发,现在好多互联网 ...

  8. 【转贴】GCC内联汇编基础

    原文作者 Sandeep.S 英文原文 [https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html] 本文将介绍GCC编译环境下 ...

  9. 关于 线程模型中经常使用的 __sync_fetch_and_add 原子操作的性能

    最近从 kvell 这篇论文中看到一些单机存储引擎的优秀设计,底层存储硬件性能在不远的未来可能不再是主要的性能瓶颈,反而高并发下的CPU可能是软件性能的主要限制.像BPS/AEP/Optane-SSD ...

最新文章

  1. 【Ant Design Pro 五】箱套路由在菜单栏显示返回上一页
  2. MSTAR SETBOX 常用API
  3. java.net.uri,java.net.uri
  4. Ext分区文件恢复工具extundelete
  5. java 计算移动平均线_基于Java语言开发的个性化股票分析技术:移动平均线(MA)...
  6. nginx负载均衡集群
  7. DCMTK:缩放DICOM图像
  8. jupyter notebook怎么写python代码_如何在Jupyter Notebook中使用Python虚拟环境?
  9. 国科大高级人工智能6-GAN
  10. Oracle 导出部分表结构,以及导入
  11. 编译hadoop,spark遇到的问题总结
  12. 单片机sprintf函数的用法_C++小知识之sprintf用法
  13. 零基础:21天搞定Python分布爬虫完整视频教程百度网盘免费获取
  14. 用c语言编写6位计算器,用c语言编写易简计算器.doc
  15. 不可战胜的苹果:全球最酷企业十大经验
  16. phpexcel中文手册(转)
  17. 沉溺于成为资深Java程序员的危机
  18. 从原型图到成品:步步深入CSS布局
  19. 当婚纱摄影邂逅超级表格|流程监控
  20. 成功解决Qt中ui_xxx.h: no such file or directory”

热门文章

  1. 客户端用mstsc不能用一台设备连接终端服务器的解决办法
  2. SQL Server 2005 Analysis Services实践(一)
  3. 浅谈C++ STL中的优先队列(priority_queue)
  4. workerman相关
  5. keepalive配置mysql自动故障转移
  6. php二维数组指定其键名对其排序的方法
  7. VLAN学习笔记大全(1)
  8. 1、配置PHP构建环境
  9. leetcode141. 环形链表
  10. Elasticsearch(三) 使用kibana 操作ES