博客
关于我
Linux内核同步机制之(一):原子操作
阅读量:142 次
发布时间:2019-02-26

本文共 1019 字,大约阅读时间需要 3 分钟。

多核系统中,读取-修改-写入操作序列的原子性问题

在多核系统中,读取-修改-写入操作序列面临着严峻的挑战。在多个CPU同时执行同一操作时,可能出现数据覆盖问题。这种情况不仅限于多核系统,还可能在单核系统中由于多线程控制路径交错引发。

1. 读取-修改-写入操作的常见问题

在多核系统中,两个或多个CPU同时读取同一内存变量的值。此时,读取操作可能返回旧值。随后,修改操作由其中一个CPU执行。写入操作时,由于总线arbiter的限制,可能存在先写入再覆盖的情况,导致最终结果错误。

在单核系统中,同样存在内核控制路径交错的问题。例如,在系统调用的中断处理中,中断handler的写入操作可能被系统调用控制路径的写入操作覆盖。

2. 解决方案:原子操作

针对这种情况,内核提供了atomic_t类型。该类型定义了若干原子接口API函数,确保操作的原子性。

3. ARM架构中的实现

在ARM架构中,原子操作分为两类:支持SMP的ARMv6及以后的版本,以及仅支持单核的ARMv6之前的版本。对于支持SMP的版本,原子操作通过特殊的指令完成。对于UP,原子操作则通过关闭中断实现。

4. 汇编实现细节

以atomic_add为例,展示具体实现:

asm volatile (    : "%0 += %1"     : "r"    : "ir"    : "cc");

上述代码中,__volatile__用于防止优化。asm语句定义了一个嵌入式汇编接口,: "%0 += %1"表示将结果保存到输出操作数,"r"表示输出操作数为一个可写寄存器,"ir"表示输入操作数为一个早期覆盖寄存器。"cc"通知GCC汇编器条件码寄存器的变化。

5. 指令细节:LDREX和STREX

LDREX和STREX指令用于实现原子操作。LDREX从内存读取数据至寄存器,并放出两个监控dog。STREX用于写入内存,并根据结果返回状态。LDREX和STREX适用于非共享内存;对于共享内存,需要额外的机制确保互斥。

6. 实现中的关键注意事项

  • 寄存器分配output operand listinput operand list需明确区分,确保编译器正确分配寄存器。
  • 缓存预加载:在使用STREX前,需预加载相关内存至缓存以提高性能。
  • 异常处理:需检查写入结果,若失败则重复操作。
  • 通过以上方法,可以确保读取-修改-写入操作的原子性,从而避免数据错误。

    转载地址:http://rypk.baihongyu.com/

    你可能感兴趣的文章
    pytorch介绍
    查看>>
    pprint 排序字典但不是集合?
    查看>>
    pptp拨号上网
    查看>>
    ppt上的倒计时小工具_PPT中有哪些「看似很 LOW,实则惊艳」的小工具
    查看>>
    PPT添加视频的路径问题
    查看>>
    PPT美化插件 islide 安装过程问题“加载com加载项时运行出现错误”
    查看>>
    Prefix Tuning:详细解读Optimizing Continuous Prompts for Generation
    查看>>
    PreparedStatement 与Statement 的区别,以及为什么推荐使用 PreparedStatement ?
    查看>>
    PreparedStatement 查询 In 语句 setArray 等介绍。
    查看>>
    presentModalViewController显示半透明的一个view
    查看>>
    PresentViewController切换界面
    查看>>
    PyTorch之torch.utils.data.DataLoader解读
    查看>>
    PyTorch之DataLoader杂谈
    查看>>
    presto、druid、sparkSQL、kylin的对比分析
    查看>>
    Presto分布式大数据查询引擎
    查看>>
    Presto架构及原理
    查看>>
    Presto(一)集群部署
    查看>>
    Presto(二)开启安全认证
    查看>>
    Pricing procedure Steps and Details in SAP MM (from SCN)
    查看>>
    Prim 算法在不同权重范围内的性能分析及其实现
    查看>>