GCC 提供的原子操作

GCC的built-in方法之 —— 原子操作 如果要在多线程中对同一个整型变量进行加减操作,我们知道可以通过加锁的方式保证线程同步,但仅对这一个变量加锁,是不是大材小用了?有没有类似于Linux内核中的atomic_inc()/atomic_dec()方法从指令的层面上实现操作变量的原子性?答案是,有的。GCC提供了一系列内置函数,来完成对一些简单的数据操作的同步。type __sync_fetch_and_add (type *ptr, ty 阅读详情

 

[日期:2011-06-17]来源:Linux社区  作者:FrankTan
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;
}
FREERTOS+LWIP+IAP实现TCP、HTTP、网页访问并固件升级、更新配置 (三)lwip实现httpd服务并在web访问 在前两篇文章中配置freeRTOS和,并实现了TCP、UDP的通信协议,现在终于轮到重头戏lwip的httpd服务,LWIP官方例程中是有很多自带的网页的,但是远远不够满足实际项目的使用需求,因此我也是踩了很多坑,从前端网页制作,到网络通信的实现,到后端数据处理,从头开始学起,也是学习到了很多没接触过的东西,本章将搭建LWIP的HTTP服务使得浏览器可以访问WEB。 阅读详情

相关推荐

手把手教你用西门子博图V18配置阿特拉斯PF6000拧紧枪PN通讯(附完整GSD文件与ToolsTalk配置文件)

本文详细介绍了如何使用西门子博图V18配置阿特拉斯PF6000拧紧枪的PN通讯,包括硬件连接、网络参数规划、ToolsTalk软件配置及博图工程设置。通过完整的GSD文件和配置文件,帮助工程师快速实现高精度拧紧设备与PLC的高效通讯,适用于汽车装配和电子制造等工业自动化场景。

weixin_42662293的博客 602

使用 原子操作 __sync_val_compare_and_swap进行无锁化编程

无锁化编程

zgw465283089的博客 3920

vue3接入大华摄像头

┃ ┃ ┣ 📜PlaybackModal.vue 回放列表模态框。┃ ┃ ┗ 📜VideoGrid.vue 视频播放区域。┃ ┃ ┣ 📜ControlPanel.vue 控制面板。┃ ┃ ┣ 📜DeviceList.vue 设备列表。┃ ┣ 📂module //大华摄像头文件。

💻 专注 Vue 前端与 Java 后端技术 🌱 目前正在深入 Spring Boot、微服务与性能优化 📝 定期分享实战踩坑经验与学习笔记 🤝 欢迎交流,共同进步 914

原子操作 . 原理与底层实现

一.概述 原子操作(atomic operation)指的是由多步操作组成的一个操作。如果该操作不能原子地执行,则要么执行完所有步骤,要么一步也不执行,不可能只执行所有步骤的一个子集。 现代操作系统中,一般都提供了原子操作来实现一些同步操作,所谓原子操作,也就是一个独立而不可分割的操作。在单核环境中,一般的意义下原子操作中线程不会被切换,线程切换要么在原子操作之前,要么在原子操作完成之后。更广...

paradox_1_0的博客 8880

海康H304NAS 刷机飞牛

本文旨在分享如何将闲置的海康威视H304 NAS刷入飞牛NAS系统,并利用iStoreOS作为安装媒介。之前因为使用极空间NAS,这台H304闲置已久。最近尝试了飞牛NAS,在虚拟机上安装后挂载极空间的电影资源,体验不错,于是决定重新折腾这台H304。我个人喜欢尝试新系统,之前经常更新H304的固件,但设备总在使用一两年后出现故障,需要联系技术清理日志才能恢复。最后一次设备“变砖”后,连技术人员也联系不上了,自己尝试修复未果,设备就此闲置两三年。

u012985257的博客 2747

CST微波工作室端口设置保姆级教程:从波导端口到离散端口,手把手教你搞定S参数仿真

本文提供CST微波工作室端口设置的详细教程,涵盖波导端口和离散端口的选择与配置,助力工程师精准完成S参数仿真。通过微带线滤波器案例,详解端口尺寸、阻抗设置及常见问题排查,提升仿真效率与准确性。

weixin_42570296的博客 362

Linux基础 -- 原子同步之__sync_val_compare_and_swap 用法详解

是 GCC 提供的一个内置函数,用于实现原子操作。它在多线程编程中非常有用,可以用来实现无锁数据结构和同步机制。该函数提供了一个原子性的比较并交换操作,即在一个多线程环境下,这个操作能够确保多个线程不会同时修改同一个变量。 参数说明 :指向需要进行原子操作的变量的指针。 :期待的当前值,也就是我们希望 指向的变量当前应该包含的值。 :如果 指向的变量的值等于 ,那么将 指向的变量的值设置为 。 返回值 如果 指向的变量的值等于 ,函数会将 赋值给该变量,并返回 。 如果 指向的变量的值不等

sz66cm 学习随笔 1747

processing与arduino互动编程

Arduino开发板对AVR单片机二次编译封装,无需考虑单片机编程寄存器、地址指针等复杂细节processing借助arduino读取各种传感器的数值,控制各种机电装置。

weixin_45679408的博客 824

通过muduo的Atomic.h学习原子操作

最新在读muduo源码,想写一个源码阅读的系列,就以这个为开篇吧 源码如下: template<typename T> class AtomicIntegerT : noncopyable { public: AtomicIntegerT() : value_(0) { } // uncomment if you need copying and assignment // // AtomicIntegerT(const AtomicIntegerT&a

qu1993的博客 785

解锁RK3588:内核模块签名与安全启动配置全攻略

RK3588作为一款高性能嵌入式SoC芯片,其内核模块签名与安全启动配置是保障系统安全的核心机制。本文详细介绍了RK3588的芯片特性,重点阐述了安全启动的硬件信任链原理和内核模块签名的实现方法。通过具体步骤演示了从密钥生成、模块签名到验证加载的完整流程,并深入解析了安全启动配置的硬件连接、软件工具准备、密钥烧录等关键环节。此外,还提出了防御旁路攻击和动态信任链扩展等高级安全策略,为RK3588在工业控制、智能安防等高安全要求场景中的应用提供了全面的安全解决方案。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 347

华为OD机考真题 新系统 - 数列求值(Java/Py/C/C++/Js/Go)

华为OD机试真题 新系统【数列求值】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题 【数列求值】多语言题解。

qq_45776114的博客 664

GCC 提供的原子操作总结

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

qq_41643443的博客 174

【全志V821_FoxPi】6-3 GC2083 MIPI摄像头适配

本文介绍了在全志V821芯片上适配GC2083 MIPI摄像头的方案。GC2083是一款支持1080P@30fps的高性能CMOS图像传感器,采用MIPI CSI-2接口,具有低功耗特性。文章详细列出了传感器的技术参数和工作电压要求,并提供了设备树配置示例,包括CSI接口、ISP处理单元和传感器节点的具体设置。通过快速配置命令one_gc2083_sensor或手动修改设备树即可启用该摄像头模组,适用于IPC等对图像质量有要求的嵌入式应用场景。

第四维度的博客 1927

GCC提供的加减和逻辑原子操作

在实际的编程中,我们不免需要对变量进行加减和逻辑操作。由于对变量的加减和逻辑操作并不是原子操作,在单线程编程中这并不会有什么的影响;在多线程编程中这就会造成问题。 在多线程编程中,如果需要对同一变量进行访问。那么我们最先想到的可能是利用线程的同步机制(比如互斥量)制造出一片线程安全的区域,并在这片区域对变量进行访问。这似乎“合情合理”,确实这种做法是正确的,它的确能确保对变量访问的线程安全,但某些情况下,这种处理方式效率是低下的。 gcc从4.1.2提供了__sync_*系列的built-in函数,用于提供

huangjh2017的博客 2101

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

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 *

bob的博客 233

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

GCC提供的内置原子操作

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

flyingfalcon的专栏 1199
上一篇: 善用backtrace解决大问题
下一篇: MySQL 使用静态链接库遇到的问题
Falcon2000
博客等级 码龄26年 2粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值