gcc 的原子操作和代码生成

2023-11-21

我正在查看 gcc 为原子操作生成的一些程序集。我尝试了以下简短的序列:

int x1;
int x2;

int foo;

void test()
{
  __atomic_store_n( &x1, 1, __ATOMIC_SEQ_CST );
  if( __atomic_load_n( &x2  ,__ATOMIC_SEQ_CST ))
    return;

  foo = 4;
}

看看 Herb Sutter 关于代码生成的原子武器演讲,他提到 X86 手册要求使用xchg对于原子商店和一个简单的mov用于原子读取。所以我期待一些类似的事情:

test():
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $1, %eax
    xchg    %eax, x1(%rip)
    movl    x2(%rip), %eax
    testl   %eax, %eax
    setne   %al
    testb   %al, %al
    je      .L2
    jmp     .L1
.L2:
    movl    $4, foo(%rip)
.L1:
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc

由于锁定,内存栅栏是隐式的xchg操作说明。

但是如果我使用编译它gcc -march=core2 -S test.cc我得到以下信息:

test():
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $1, %eax
    movl    %eax, x1(%rip)
    mfence
    movl    x2(%rip), %eax
    testl   %eax, %eax
    setne   %al
    testb   %al, %al
    je      .L2
    jmp     .L1
.L2:
    movl    $4, foo(%rip)
.L1:
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc

所以不要使用xchg操作 gcc 这里使用mov + mfence组合。这种代码生成与 Herb Sutter 所说的 x86 架构所要求的不同的原因是什么?


The xchg当目标是内存位置时,指令具有隐含的锁定语义。这意味着您可以自动交换寄存器的内容与内存位置的内容。

问题中的示例是进行原子存储,而不是交换。 x86 架构内存模型保证在多处理器/多核系统中,一个线程完成的存储将按该顺序被其他线程看到......因此内存移动就足够了。话虽如此,有些较旧的 Intel CPU 和一些克隆产品在这方面存在错误,并且xchg需要作为这些 CPU 上的解决方法。请参阅这篇关于自旋锁的维基百科文章的重要优化部分:

http://en.wikipedia.org/wiki/Spinlock#Example_implementation

哪个州

上面的简单实现适用于所有使用 x86 架构的 CPU。但是,可以进行许多性能优化:

在 x86 架构的后续实现中,spin_unlock 可以安全地使用未锁定的 MOV,而不是较慢的锁定 XCHG。这是由于支持这一点的微妙内存排序规则,即使 MOV 不是完整的内存屏障。但是,某些处理器(某些 Cyrix 处理器、Intel Pentium Pro 的某些修订版(由于错误)以及早期的 Pentium 和 i486 SMP 系统)会执行错误操作,并且受锁保护的数据可能会损坏。在大多数非 x86 体系结构上,必须使用显式内存屏障或原子指令(如示例中所示)。在某些系统上,例如 IA-64,有特殊的“解锁”指令来提供所需的内存排序。

记忆障碍,mfence,确保所有存储已完成(CPU 内核中的存储缓冲区为空,值存储在高速缓存或内存中),它还确保未来的加载不会乱序执行。

MOV 足以解锁互斥体(不需要序列化或内存屏障)这一事实已在 1999 年 Intel 架构师回复 Linus Torvalds 时“正式”澄清

http://lkml.org/lkml/1999/11/24/90.

我想后来发现它不适用于某些较旧的 x86 处理器。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

gcc 的原子操作和代码生成 的相关文章

  • C 编程 - 文件 - fwrite

    我有一个关于编程和文件的问题 while current NULL if current gt Id Doctor 0 current current gt next id doc current gt Id Doctor if curre
  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • 通过 CMIS (dotCMIS) 连接到 SP2010:异常未经授权

    我正在使用 dotCMIS 并且想要简单连接到我的 SP2010 服务器 我尝试用 C 来做到这一点 如下所示http chemistry apache org dotnet getting started with dotcmis htm
  • “构建”构建我的项目,“构建解决方案”则不构建

    我刚刚开始使用VS2010 我有一个较大的解决方案 已从 VS2008 成功迁移 我已将一个名为 Test 的控制台应用程序项目添加到解决方案中 选择构建 gt 构建解决方案不编译新项目 选择构建 gt 构建测试确实构建了项目 在失败的情况
  • WCF RIA 服务 - 加载多个实体

    我正在寻找一种模式来解决以下问题 我认为这很常见 我正在使用 WCF RIA 服务在初始加载时将多个实体返回给客户端 我希望两个实体异步加载 以免锁定 UI 并且我想利用 RIA 服务来执行此操作 我的解决方案如下 似乎有效 这种方法会遇到
  • GLKit的GLKMatrix“列专业”如何?

    前提A 当谈论线性存储器中的 列主 矩阵时 列被一个接一个地指定 使得存储器中的前 4 个条目对应于矩阵中的第一列 另一方面 行主 矩阵被理解为依次指定行 以便内存中的前 4 个条目指定矩阵的第一行 A GLKMatrix4看起来像这样 u
  • 为什么两个不同的 Base64 字符串的转换会返回相等的字节数组?

    我想知道为什么从 base64 字符串转换会为不同的字符串返回相同的字节数组 const string s1 dg const string s2 dq byte a1 Convert FromBase64String s1 byte a2
  • 类模板参数推导 - clang 和 gcc 不同

    下面的代码使用 gcc 编译 但不使用 clang 编译 https godbolt org z ttqGuL template
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • Clang 3.1 + libc++ 编译错误

    我已经构建并安装了 在前缀下 alt LLVM Clang trunk 2012 年 4 月 23 日 在 Ubuntu 12 04 上成功使用 GCC 4 6 然后使用此 Clang 构建的 libc 当我想使用它时我必须同时提供 lc
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable

随机推荐

  • 如何在C++中获取动态数组的大小[重复]

    这个问题在这里已经有答案了 通过输入大小并将其存储到 n 变量中来编写动态数组的代码 但我想从模板方法获取数组长度而不是使用 n int a NULL Pointer to int initialize to nothing int n S
  • ASP.Net:在 Page_Load 中调用异步方法

    我有一个 API 客户端 它有一个发送方法 用于将我的对象发布到 Web API 服务并返回 ReturnedResults 类型的对象 现在我需要在 ASP net page load 事件中运行此 post 方法 我在这里看到了类似的示
  • 保护图片下载

    我知道保护图像下载的最佳方法首先就是不要将其放在互联网上 我认为没有 100 的防止图像下载的保护 如果用户可以在互联网上看到图像 他可以通过一些经验找到下载它的权限 我知道透明 gif or png覆盖图像或使用background im
  • 为什么macos(x86)可以运行docker arm容器arm64v8/alpine?

    我碰巧发现我的macos x86 可以为arm镜像arm64v8 alpine运行docker容器 但有以下警告 docker run it arm64v8 alpine uname a WARNING The requested imag
  • JavaFX完全定制windows?

    我想要一个完全自定义窗口外观的应用程序 到目前为止 我已经了解到可以使用以下方法删除典型的窗口内容 class Application extends javafx application Application Starts the ap
  • 通过 Eclipse Kepler 启动 tomcat v7 时遇到问题

    我看到像我这样的问题以前已经发布过 其中一些帖子已得到解答 我已经尝试过修复 看起来确实应该有效 但我仍然遇到同样的问题 我正在尝试通过本地主机上的 apache tomcat 7 0 53 在 Eclipse Kepler Java EE
  • 两个子图的单个颜色条会更改其中一个子图的大小

    我正在尝试添加一个colorbar两个人matshow主要使用以下代码here and here 我的代码现在如下 但问题是颜色条调节了右侧绘图的大小 我怎样才能防止这种情况发生 import numpy as np import matp
  • 如何比较大文本文件?

    我有一个关于你对我的 技术 的看法的一般性问题 有 2 个文本文件 file 1 and file 2 需要相互比较 两者都非常巨大 3 4 GB 每个从 30 000 000 到 45 000 000 行 我的想法是阅读几行 尽可能多 f
  • 查询计算连续事件之间的平均时间

    我的问题是如何编写 SQL 查询来计算连续事件之间的平均时间 我有一张小桌子 event Name Time stage 1 10 01 stage 2 10 03 stage 3 10 06 stage 1 10 10 stage 2 1
  • 运行时在 Highcharts 图表中添加按钮

    我需要添加一些自定义按钮 带有 onclick 事件 而不覆盖导出按钮值 因为我想包含新按钮 而不会丢失图表中先前定义的自定义按钮 我的图表已经定义了自定义按钮 所有这些都在运行时进行 在使用此对象的 Highcharts 图表中 容器 h
  • 我不想在 DatePicker 中显示消息“选择日期”

    我不想在 DatePicker 的文本框中显示 选择日期 但我想看到这样的内容 或其他文本 这是我的资源
  • 什么是“file_like_object”,什么是“文件”; pickle.load() 和 pickle.loads()

    我正在弄清楚两者之间的差异pickle load and pickle loads 有人说那是什么样的物体pickle load 进程是 file like object 但是 pickle loads 对应于 文件对象 您选择使用哪个函数
  • Internet Explorer 在哪里存储其加载项?

    我检查了整个注册表 但找不到所有已安装扩展的任何列表 此时 IE 扩展 附加组件的任何常规位置都会有所帮助 取自here 浏览器辅助对象 旨在增强浏览器功能的浏览器插件 条目可以在注册表中找到 HKEY LOCAL MACHINE Soft
  • Vim 文本着色

    I use echo e为了给我的脚本输出着色 它在使用标准输出时工作得很好 但是当我将输出重定向到文件时 vim不显示颜色 而是显示这样的标志 例子 echo e e 32m Green message e 0m echo e e 31m
  • 检查 Facebook 是否被阻止然后重定向 [重复]

    这个问题在这里已经有答案了 可能的重复 通过 JavaScript 检查网站是否正常运行的最佳方法是什么 我们即将通过 Facebook 页面开展一项活动 理想情况下 我们希望将用于此活动的网址 例如 www oursite com cam
  • 错误:即使使用 Dispatcher,也必须在与 DependencyObject 相同的线程上创建 DependencySource

    以下是我的部分内容View其中我已将图像绑定到我的属性ViewModel
  • View.GONE 和 View.INVISIBLE 之间有什么区别[重复]

    这个问题在这里已经有答案了 我正在使用自定义视图 在自定义视图上 我正在绘制一些图表 我还在我的布局上使用 TextView 当我在按钮上单击此 TextView 可见和不可见时 是清除图 为什么是清除图 同时有GONE和INVISIBLE
  • 数据库复制。 2台服务器,主数据库,第二台是只读的

    假设您有 2 个数据库服务器 其中一个数据库是执行所有写入操作的 主 数据库 它被视为 真实 原始 数据库 另一台服务器的数据库将是主数据库 从 的镜像副本 它将用于应用程序某一部分的只读操作 如何设置一个从数据库来镜像主数据库上的数据 据
  • elasticsearch:自动节点发现没有发生,遗漏了什么?

    在我的同一台机器上 我首先运行 elasticsearch f 2014 02 06 10 27 59 066 INFO node Gabe Jones version 0 90 11 pid 1767 build 11da1ba 2014
  • gcc 的原子操作和代码生成

    我正在查看 gcc 为原子操作生成的一些程序集 我尝试了以下简短的序列 int x1 int x2 int foo void test atomic store n x1 1 ATOMIC SEQ CST if atomic load n