ARM64 linux并发与同步之内存屏障

news/2024/11/24 22:51:27/

1.2 内存屏障

1.2.1 概念理解

在这里插入图片描述
在这里插入图片描述
原理部分比较苦涩难懂,我们先不过多详细介绍这部分的由来和经过,接下来着重讲解什么用途和实现;

ARM64架构中提供了3条内存屏障指令。

  • 数据存储屏障(Data Memory Barrier, DMB)指令。
  • 数据同步屏障(Data Synchronization Barrier, DSB)指令。
  • 指令同步屏障(Instruction Synchronization Barrier, ISB)指令。

学习过程中对这三条指令的含义还是有所困惑的,接下来介绍下:

数据存储屏障(Data Memory Barrier, DMB)指令: 仅当所有在它前面的存储器访问操作都执行完毕后,才提交在它后面的访问指令,DMB指令保证的是DMB指令之前的所有内存访问指令和DMB指令之后的所有内存访问指令的顺序。也就是说,DMB指令之后的内存访问不会被处理器重排到DMB指令前面。DMB指令不会保证内存访问指令在内存屏障指令之前必须完成它仅仅保证内存屏障指令前后的内存访问指令的执行顺序。DMB指令仅仅影响内存访问指令、数据高速缓存指令,以及高速缓存管理指令等,并不会影响其他指令的顺序。
在这里插入图片描述
**数据同步屏障(Data Synchronization Barrier, DSB)指令:**比DMB指令要严格一些,仅当所有在它前面的访问指令都执行完毕后,才会执行在它后面的指令,即任何指令都要等待DSB指令前面的访问指令完成。位于此指令前的所有缓存,如分支预测和TLB维护操作需全部完成

**指令同步屏障(Instruction Synchronization Barrier, ISB)指令:**比DMB指令和DSB指令严格,刷新流水线和预取缓冲区后,才会从高速缓存或者内存中预取ISB指令之后的指令。ISB指令通常用来保证上下文切换的效果,如ASID(address space ID)更改,TLB维护操作和C15寄存器的修改等。

Note: DMB和DSB指令可以带参数,后续有遇到我们再补充说明,感兴趣的也可自行查阅;

1.2.2 接口说明

在这里插入图片描述

在ARM64 Linux内核中实现内存屏障函数的代码如下:

<kernel/linux/linux-5.15.73/arch/arm64/include/asm/barrier.h>#define isb()		asm volatile("isb" : : : "memory")
#define dmb(opt)	asm volatile("dmb " #opt : : : "memory")
#define dsb(opt)	asm volatile("dsb " #opt : : : "memory")#define mb()		dsb(sy)
#define rmb()		dsb(ld)
#define wmb()		dsb(st)#define dma_mb()	dmb(osh)
#define dma_rmb()	dmb(oshld)
#define dma_wmb()	dmb(oshst)
1.2.3 linux中案例说明

例1:在一个网卡驱动中发送数据包。把网络数据包写入缓冲区后,由DMA引擎负责发送,wmb()函数保证在DMA传输之前,数据被完全写入缓冲区中。

<kernel/linux/linux-5.15.73/drivers/net/ethernet/realtek/8139too.c>static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb,struct net_device *dev)
{struct rtl8139_private *tp = netdev_priv(dev);void __iomem *ioaddr = tp->mmio_addr;unsigned int entry;unsigned int len = skb->len;unsigned long flags;/* Calculate the next Tx descriptor entry. */entry = tp->cur_tx % NUM_TX_DESC;/* Note: the chip doesn't have auto-pad! */if (likely(len < TX_BUF_SIZE)) {if (len < ETH_ZLEN)memset(tp->tx_buf[entry], 0, ETH_ZLEN);skb_copy_and_csum_dev(skb, tp->tx_buf[entry]); // 写入TxStatus以触发DMA传输dev_kfree_skb_any(skb);} else {dev_kfree_skb_any(skb);dev->stats.tx_dropped++;return NETDEV_TX_OK;}spin_lock_irqsave(&tp->lock, flags);/** Writing to TxStatus triggers a DMA transfer of the data* copied to tp->tx_buf[entry] above. Use a memory barrier* to make sure that the device sees the updated data.*/wmb(); //使用一条内存屏障指令以保证设备可以看到这些更新后的数据RTL_W32_F (TxStatus0 + (entry * sizeof (u32)),tp->tx_flag | max(len, (unsigned int)ETH_ZLEN));tp->cur_tx++;if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)netif_stop_queue (dev);spin_unlock_irqrestore(&tp->lock, flags);netif_dbg(tp, tx_queued, dev, "Queued Tx packet size %u to slot %d\n",len, entry);return NETDEV_TX_OK;
}

例2: Linux内核里面的睡眠和唤醒接口函数也运用了内存屏障指令,通常一个进程因为等待某些事件需要睡眠,如调用wait_event()函数。睡眠者的代码片段如下。

for (;;) { set_current_state(TASKJJNINTERRUPTIBLE);if (event_indicated)break;schedule();/****************************************************************************/#define set_current_state(state_value)					\do {								\debug_normal_state_change((state_value));		\smp_store_mb(current->__state, (state_value));		\} while (0)

set_current_state()函数在修改进程的状态时隐含插入了内存屏障函数smp_mb()。smp_store_mb函数最终调用的是mb();

唤醒者通常会调用wake_up()函数,它在修改task状态之前也隐含地插入内存屏障函数 smp_rmb()。

wake_up() —> __wake_up_common() -----> wq_entry->func—> autoremove_wake_function() —> try_to_wake_up() ------> smp_rmb()
在这里插入图片描述

  • 睡眠者:CPUI在更改当前进程current->state后,插入一条内存屏障指令,保证加载唤醒标记load event_indicated不会出现在修改current->state之前。
  • 唤醒者:CPU2在唤醒标记store操作和把进程状态修改成RUNNING的store操作之间插入写屏障,保证唤醒标记event indicated的修改能被其他CPU看到。

感谢学习,有什么问题可以评论区讨论学习。


http://www.ppmy.cn/news/1219582.html

相关文章

P1260 工程规划

工程规划 题目描述 造一幢大楼是一项艰巨的工程&#xff0c;它是由 n n n 个子任务构成的&#xff0c;给它们分别编号 1 , 2 , ⋯ , n ( 5 ≤ n ≤ 1000 ) 1,2,\cdots,n\ (5≤n≤1000) 1,2,⋯,n (5≤n≤1000)。由于对一些任务的起始条件有着严格的限制&#xff0c;所以每个…

指针传2

几天没有写博客了&#xff0c;怎么说呢&#xff1f;这让我总感觉缺点什么&#xff0c;心里空落落的&#xff0c;你懂吧&#xff01; 好了&#xff0c;接下来开始我们今天的正题&#xff01; 1. ⼆级指针 我们先来看看代码&#xff1a; 首先创建了一个整型变量a&#xff0c;将…

什么是基因表达谱分析及其相关概念

目录 相关概念1. 转录本2. 什么是L1000技术 相关概念 1. 转录本 转录本&#xff08;transcript&#xff09;是指在基因表达中产生的RNA分子。基因是DNA上的一段特定序列&#xff0c;通过基因表达&#xff0c;该DNA序列的信息被转录为RNA。转录本是这个转录过程的产物&#xff…

Spring6(一):入门案例

文章目录 1. 概述1.1 Spring简介1.2 Spring 的狭义和广义1.3 Spring Framework特点1.4 Spring模块组成 2 入门2.1 构建模块2.2 程序开发2.2.1 引入依赖2.2.2 创建java类2.2.3 创建配置文件2.2.4 创建测试类测试 2.3 程序分析2.4 启用Log4j2日志框架2.4.1 引入Log4j2依赖2.4.2 加…

es性能强悍的推演过程

前言 es底层复用的Lucene的能力&#xff0c;Lucene在以前的文章中有所讲解&#xff0c;感兴趣可查看 https://blog.csdn.net/u013978512/article/details/125474873?ops_request_misc%257B%2522request%255Fid%2522%253A%2522169771769916777224433628%2522%252C%2522scm%2522…

CNN进展:AlexNet、VGGNet、ResNet 和 Inception

一、说明 对于初学者来说&#xff0c;神经网络进展的历程有无概念&#xff1f;该文综合叙述了深度神经网络的革命性突破&#xff0c;从AlexNet开始&#xff0c;然后深度VGG的改进&#xff0c;然后是残差网络ResNet和 Inception&#xff0c;如果能讲出各种特色改进点的和改进理由…

【Amazon】云上探索实验室—了解 AI 编程助手 Amazon Codewhisperer

文章目录 一、前言&#x1f4e2;二、关于云上探索实验室&#x1f579;️三、领学员需要做什么&#xff1f;✴️四、领学员能获得什么&#xff1f;&#x1f523;五、学课通道入口&#x1f447;1️⃣CSDN平台2️⃣网易云课堂3️⃣Skill Builder 平台 六、活动详情链接 一、前言&a…

vue和react项目中实现 px 转 vm

vue和react项目中实现 px 转 vm vue中配置 1、下载插件 npm i postcss-px-to-viewport2、vue项目配置 const { defineConfig } require(vue/cli-service); const AutoImport require(unplugin-auto-import/webpack); const Components require(unplugin-vue-components/…