`
aigo
  • 浏览: 2644805 次
  • 性别: Icon_minigender_1
  • 来自: 宜昌
社区版块
存档分类
最新评论

GCC 提供的原子操作

 
阅读更多

原文:http://www.cnblogs.com/FrankTan/archive/2010/12/11/1903377.html


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

分享到:
评论

相关推荐

    用GCC开发STM32,正点原子开发板的一个库函数版本例程示例

    总的来说,这个压缩包文件提供的示例涵盖了STM32 GCC开发的基本流程,包括库函数的使用、GPIO外设的操作以及代码编译和烧录。通过学习和实践这个例程,开发者能够更好地理解和掌握STM32的GCC开发方法,为进一步深入...

    gcc-4.6.0.tar.gz

    描述中提到的"undefined reference to '__sync_sub_and_fetch_4'"是一个链接时错误,通常在使用原子操作(如GCC的内置同步函数)时出现。__sync_sub_and_fetch_4是一个GCC提供的原子减法并返回结果的函数,用于多...

    gcc-window-4.8.3

    对于C程序员,GCC 4.8.3也可能提供了对C11标准的一些支持,比如_thread_local关键字、原子操作和线程函数等。 在Windows环境下使用GCC,通常需要借助MinGW(Minimalist GNU for Windows)或MinGW-w64。MinGW是一个...

    gcc C语言API

    为了支持多线程编程,GCC C语言API提供了一套完整的并发工具,包括原子操作、互斥锁、条件变量等。这些工具可以帮助开发者编写出高效且安全的多线程程序。 ##### 5.2 线程安全性 GCC C语言API中的大部分功能都设计...

    atomicops_internals_x86_gcc.rar_This Is It

    GCC(GNU Compiler Collection)是一个广泛使用的开源编译器套件,它提供了对C、C++、Objective-C、Fortran等多种语言的支持,并且在处理并发和多线程编程时,提供了丰富的内建函数和扩展来实现原子操作。...

    gcc内联汇编手册

    1. **原子自增**:使用内联汇编实现原子自增操作。 2. **内存屏障**:在多核系统上,使用内存屏障确保数据的一致性和可见性。 3. **CPU特征检测**:通过运行特定的CPU指令来检测CPU支持的特性。 #### 八、结论 GCC...

    gcc中的内嵌汇编语言.rar

    - **原子操作**:在多线程编程中,内联汇编可以用于创建不可中断的原子操作,确保数据一致性。 - **利用处理器特性**:对于某些特定处理器的特殊功能,如SIMD(单指令多数据)指令,内嵌汇编能直接利用这些特性。 ...

    gcc-4.8.2.tar.gz包含依赖

    在C语言方面,它支持C11标准,这是C语言的最新标准,提供了许多新的特性和改进,如线程支持、原子操作、类型安全的指针和新的内存管理功能等。描述中提到的“unrecognized command line option "-std=c11"”错误通常...

    tdm-gcc-5.1.0-3.zip

    2. **原子操作**:通过 `&lt;stdatomic.h&gt;` 头文件,提供了原子类型和操作,增强了并发编程的安全性。 3. **静态断言**:`_Static_assert()` 函数可以在编译时进行类型检查,确保代码的正确性。 4. **可选的尾置返回...

    cpp-ARMGCC内联汇编参考手册中文版

    3. **原子操作**:在多线程环境中,内联汇编可以实现无锁数据结构或原子操作。 4. **初始化和启动代码**:在系统启动阶段,可能需要执行特定的汇编代码。 **注意事项:** 1. **兼容性问题**:不同的ARM架构可能有...

    C语言与实现测试-原子.zip

    例如,可以使用gcc的__sync系列函数或C11标准中的std::atomic模板类来进行原子操作。这些操作包括原子读写、原子比较并交换(CAS)等。 1.dsp 和 1.dsw 文件是Microsoft Visual Studio的项目文件,用于管理和构建C/...

    ARM_GCC内嵌汇编

    3. **同步原语**:如原子操作,在多线程编程中确保数据一致性。 了解并熟练掌握ARM_GCC内嵌汇编,可以帮助开发者编写出更高效、更接近硬件的代码,特别是在需要精细控制硬件资源或优化性能的关键部分。然而,这需要...

    GCC内嵌汇编收集

    GCC内嵌汇编的一个常见应用场景是利用特定的CPU特性,比如向量运算或原子操作,这些在高级语言中可能难以表达。此外,它还可以用于直接访问硬件寄存器,如中断控制器或设备状态寄存器。 通过深入理解AT&T汇编语法和...

    正点原子Buildroot用户手册中文版(正点原子翻译)-V1.0

    正点原子提供了在线教学平台()和论坛(),供用户学习 Buildroot 的使用、深入理解其工作原理,以及参与 Buildroot 的开发。 **总结** Buildroot 是构建嵌入式 Linux 系统的强大工具,它的易用性和灵活性使其...

    gcc 内联汇编howto

    教程会给出具体的示例,展示如何在实际项目中应用内联汇编,比如原子操作、位操作或者与特定硬件外设通信。 除此之外,教程可能还会讨论一些高级主题,如延迟分支、向量运算、浮点运算的汇编表示,以及如何在多线程...

    mymalloc:2 malloc实现的简单功能,专为Linux和gcc提供,具有原子自旋锁

    原子自旋锁的实现通常依赖于底层的原子操作指令,如`__sync_lock_test_and_set`或`__sync_synchronize`等。这些指令保证了在多核处理器上的并发访问不会导致数据不一致。在`mymalloc`中,自旋锁用于保护内存池的数据...

    GCC.rar_内嵌汇编

    7. **应用场景**:常见的内嵌汇编应用包括硬件中断处理、访问硬件寄存器、优化关键循环、原子操作等。在嵌入式系统或实时操作系统中,内嵌汇编特别常见,因为这些系统往往需要对硬件有更精细的控制。 通过深入理解...

    gcc-inline-assembly

    **GCC内嵌汇编**是GCC(GNU Compiler Collection)提供的一种功能,允许程序员在C、C++等高级语言中直接插入汇编代码。这在处理特定硬件特性、优化性能或解决与硬件紧密交互的问题时非常有用。本篇将详细解析GCC内嵌...

    stm32+esp8266连接原子云

    3. **STM32编程**:使用如Keil uVision或GCC等开发环境,编写STM32F103的C代码,实现对ESP8266的控制,发送和接收数据。 4. **通信协议**:选择合适的通信协议,如AT指令集,允许STM32通过UART向ESP8266发送命令进行...

Global site tag (gtag.js) - Google Analytics