当前位置: 首页 > news >正文

volatile 和 memory barrier 的组合用法

为什么 volatile 不够?

先讲一个核心观点:

volatile 只防止 编译器优化但不阻止 CPU 的乱序执行(reorder)

这在 多核系统、SoC、DSP 交互、或者访问 共享 memory-mapped IO(如 DP 寄存器) 时,会引发隐蔽 bug。


举个例子:想设置两个寄存器

*(volatile uint32_t*)REG_A = 0x01;  // 开启
*(volatile uint32_t*)REG_B = 0x02;  // 配置

你以为执行顺序是 A → B,但 CPU 可能 重排序 成 B → A!

为什么?

因为:

  • volatile 保证每条语句都执行,但不保证顺序

  • 现代 CPU(尤其 ARM)为性能会对内存访问做乱序执行

  • 你以为“先开再设”的动作,硬件上可能变成“先设再开”


所以引入:memory barrier(内存屏障)

内存屏障(Memory Barrier / Memory Fence)用于强制 CPU 在指令之间的顺序,防止重排序。


关键类型的内存屏障

屏障指令作用
__sync_synchronize()(GCC builtin)全屏障,阻止所有内存访问乱序
dmb, dsb, isb(ARM 汇编)数据/系统/指令级内存屏障
mb(), rmb(), wmb()(Linux 内核)全屏障、只读屏障、只写屏障
std::atomic_thread_fence(C++11)C++ 标准的 memory fence,用于控制跨线程顺序

volatile + memory barrier 的组合用法示例

场景:通知 DSP 某个命令写完了

// 寄存器地址映射
volatile uint32_t* REG_CMD  = (uint32_t*)0xF9008000;
volatile uint32_t* REG_FLAG = (uint32_t*)0xF9008004;// 步骤1:写命令
*REG_CMD = 0xABCD;// 步骤2:内存屏障,确保写入命令完成后再标记完成
__sync_synchronize();  // 或 Linux 下的 smp_wmb();// 步骤3:设置 flag
*REG_FLAG = 0x1;

这就能确保 REG_CMD 的写操作在 REG_FLAG 设置前完成

DSP 或硬件看到 REG_FLAG=1,就知道前面的指令已经 ready。


volatile 是防编译器,memory barrier 是防 CPU

类型编译器优化CPU重排序使用对象
volatile✅ 禁止❌ 不管变量/寄存器
memory barrier❌ 不管✅ 阻止线程间、寄存器顺序

volatile ≠ 内存屏障! 但它们经常需要配合使用,尤其是在多核场景或驱动中。


Linux 驱动中的实际例子

writel(val, reg_addr);       // 写入寄存器(可能会被缓冲)
wmb();                       // 保证这个写操作被 flush 到总线
  • writel() 本身可能是 relaxed 的

  • wmb() 保证 写操作在它之前的写入一定完成


在 QCOM Display / DP 驱动中的典型用法:

你可能看到这样的片段:

writel(DP_CTL_ENABLE, dp_base + DP_CTL);
mb();  // 或 wmb()writel(START, dp_base + DP_START);

确保“先 enable 控制器、再发送 start 命令”,不会被 CPU 重排序。


总结口诀

volatile 是给 编译器 的提示,
memory barrier 是给 CPU 的命令。
两者配合,用于确保:

“写完再标记”
“先设寄存器 A,再设寄存器 B”
“先检查条件,再做动作”

http://www.xdnf.cn/news/12043.html

相关文章:

  • xml+html 概述
  • React 事件处理基础
  • 简单好用的在线工具
  • Webpack基础
  • PHP8.2.9NTS版本使用composer报错,扩展找不到的问题处理
  • 清华大学李升波教授的强化学习Tutorial Lecture
  • 2D物体检测学习
  • Linux 系统编程 day4 进程管道
  • 多线程使用——多线程的创建和常用方法
  • 2025年MathorCup数学应用挑战赛【选题分析】
  • Android tinyalsa库函数剖析
  • nginx 在 windows 中 部署 jar包 和 dist包
  • 深度学习基础--CNN经典网络之InceptionV3详解与复现(pytorch)
  • goland做验证码识别时报“undefined: gosseract.NewClient”
  • 哪种电脑更稳定?Mac?Windows?还是云电脑? 实测解密
  • 对WAV文件进行降噪
  • 探索 Higress:下一代云原生 API 网关
  • ulauncher软件启动器
  • Nacos 中使用了哪些缓存?缓存的目的是什么?是如何实现的?
  • 基于领域知识的A型主动脉夹层综合分割及面向临床的评估|文献速递-深度学习医疗AI最新文献
  • 获取不到AndroidManifest中的meta-data
  • AI Agents系列之构建多智能体系统
  • 《奇迹世界起源》:神之月晓活动介绍!
  • 不确定与非单调推理的概率方法
  • 安全光幕的CE认证
  • 项目计划管理系统怎么选?15款项目管理工具详评
  • Flutter与FastAPI的OSS系统实现
  • 【系统架构设计师】统一过程模型(RUP)
  • 什么是爬虫?——从技术原理到现实应用的全面解析
  • Scrapeless Scraping Browser: A high-concurrency automation solution for AI