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

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看到。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/135936.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

劲松HPV防治诊疗中心发布:HPV感染全面防治解决方案

在当今社会&#xff0c;HPV(人乳头瘤病毒)感染问题已成为广大公众关注的焦点。作为一种高度传染性的病毒&#xff0c;HPV感染不仅可能导致生殖器疣&#xff0c;还可能引发各种癌症。面对这一严重威胁&#xff0c;劲松HPV防治诊疗中心以其专业的医疗团队、正规的治疗流程和全方位…

Python基础入门例程51-NP51 列表的最大与最小(循环语句)

最近的博文&#xff1a; Python基础入门例程50-NP50 程序员节&#xff08;循环语句&#xff09;-CSDN博客 Python基础入门例程49-NP49 字符列表的长度-CSDN博客 Python基础入门例程48-NP48 验证登录名与密码&#xff08;条件语句&#xff09;-CSDN博客 目录 最近的博文&…

函数极限求解方法归纳

1、连续函数直接代入值&#xff08;加减不可以部分代入值&#xff09; 例题1 配凑构造等价无穷小 等价无穷小 注意&#xff1a;不要在加减中部分使用等价无穷小&#xff0c;可以利用拆极限的方式求&#xff0c;拆出来的每一部分都要有极限&#xff0c;如果有一部分没有极限就是…

STM32F4X定时器之通用定时器

一、STM32通用定时器概述 通用定时器包括一个16位或32位自动重载计数器&#xff0c;可通过可编程预分频器进行驱动。定时器可以实现多种功能&#xff0c;包括测量输入信号的脉冲宽度和生成输出波形&#xff0c;通过使用定时器预分频器和RCC时钟控制器预分频器&#xff0c;可以…

目标检测——Yolo系列(YOLOv1/2/v3/4/5/x/6/7/8)

目标检测概述 什么是目标检测&#xff1f; 滑动窗口&#xff08;Sliding Window&#xff09; 滑动窗口的效率问题和改进 滑动窗口的效率问题&#xff1a;计算成本很大 改进思路 1&#xff1a;使用启发式算法替换暴力遍历 例如 R-CNN&#xff0c;Fast R-CNN 中使用 Selectiv…

C++算法:完美矩形

题目 给你一个数组 rectangles &#xff0c;其中 rectangles[i] [xi, yi, ai, bi] 表示一个坐标轴平行的矩形。这个矩形的左下顶点是 (xi, yi) &#xff0c;右上顶点是 (ai, bi) 。 如果所有矩形一起精确覆盖了某个矩形区域&#xff0c;则返回 true &#xff1b;否则&#xf…

AI 绘画 | Stable Diffusion WebUI的基本设置和插件扩展

前言 Stable Diffusion WebUI是一个基于Gradio库的浏览器界面&#xff0c;用于配置和生成AI绘画作品&#xff0c;并且进行各种精细地配置。它支持目前主流的开源AI绘画模型&#xff0c;例如NovelAI/Stable Diffusion。 在基本设置方面&#xff0c;Stable Diffusion WebUI的默…

asp.net外卖网站系统VS开发mysql数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net外卖网站系统 是一套完善的web设计管理系统&#xff0c;系统采用mvc模式&#xff08;BLLDALENTITY&#xff09;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为mysql&#xff0c;使用c#语…

Git的原理与使用(一)

目录 Git初始 Git安装 Git基本操作 创建git本地仓库 配置git 工作区,暂存区,版本库 添加文件,提交文件 查看.git文件 修改文件 版本回退 小结 Git初始 git是一个非常强大的版本控制工具.可以快速的将我们的文档和代码等进行版本管理. 下面这个实例看理解下为什么需…

CountDownLatch和CyclicBarrier详解

1. CountDownLatch 1.1 简介 CountDownLatch 是 Java 中并发包&#xff08;java.util.concurrent&#xff09;提供的一种同步工具&#xff0c;用于在多线程环境中协调多个线程之间的执行顺序。它的作用是允许一个或多个线程等待其他线程完成操作。 CountDownLatch 通过一个计…

java使用geotools导出shp文件

SHP格式是一种矢量数据格式&#xff0c;用于存储地理信息系统&#xff08;GIS&#xff09;数据。 SHP文件由一系列有序的文件组成&#xff0c;我们导出的shp文件包括.shp、.shx、.dbf、.prj以及.fix文件。 .shp&#xff08;shape&#xff09;文件&#xff1a;存储矢量地图数据&…

自定义类型:联合和枚举

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 1. 联合体 1.1 联合体类型的声明 1.2 联合体的特点 1.3 相同成员的结构体和联合体对比 1.4 联合体大小的计算 1.5 联合的一个练习 2. 枚举类型 2.1 枚举类型的声明…

思维模型 目标效应

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。明确目标&#xff0c;激发内在动机。 1 目标效应的应用 1.1 目标效应在教育领域的应用-棉花糖实验 美国斯坦福大学心理学系的教授米歇尔&#xff08;Walter Mischel&#xff09;曾经进行了…

1204. 错误票据

题目&#xff1a; 1204. 错误票据 - AcWing题库 思路&#xff1a; 将输入的数据存入数组&#xff0c;从小到大排序后遍历&#xff0c;若 (a[i] a[i - 1])res1 a[i]--->重号;若(a[i] - a[i - 1] > 2)res2 a[i] - 1--->断号。 难点&#xff1a;题目只告诉我们输入…

1977 智慧校园平台开发与实现JSP【程序源码+文档+调试运行】

摘要 本文旨在设计和实现一个智慧校园平台系统&#xff0c;以满足管理员、教师和学生三类用户的需求。管理员拥有最高管理权限&#xff0c;可对教师和学生用户进行管理&#xff1b;教师用户可查看和管理本班学生信息、成绩等&#xff1b;学生用户可查看个人信息、考试成绩等。…

Leetcode139单词拆分及其多种变体问题

1 声明 1.1 首先&#xff0c;大家常常把这道题当作了背包问题来做&#xff0c;因为其循环结构和背包问题刚好相反&#xff0c;但事实如此嘛&#xff1f; 背包问题通常都是组合问题&#xff0c;这其实是一道“”面向目标值的排列问题“&#xff0c;具体和背包问题有什么不同可…

[01]汇川IMC30G-E系列运动控制卡应用笔记

简介 IMC30G-E系列产品是汇川技术自主研制的高性能EtherCAT网络型运动控制器&#xff08;卡&#xff09;&#xff0c;同时兼容脉冲轴的控制&#xff1b;IMC30G-E支持点位/JOG、插补、多轴同步、高速位置比较输出、PWM等全面的运动控制功能&#xff0c;具备高同步控制精度。 开发…

【Nginx】深入浅出搞懂Nginx

Nginx是一款轻量级的Web服务器、反向代理服务器&#xff0c;由于它的内存占用少&#xff0c;启动极快&#xff0c;高并发能力强&#xff0c;在互联网项目中广泛应用。 反向代理服务器&#xff1f; 经常听人说到一些术语&#xff0c;如反向代理&#xff0c;那么什么是反向代理&a…

Pinia 状态管理器 菠萝:Option Store风格

Pinia介绍&#xff1a; Pinia 是 Vue 的专属状态管理库&#xff0c;它允许你跨组件或页面共享状态。 Pinia 大小只有 1kb 左右&#xff0c;超轻量级&#xff0c;你甚至可能忘记它的存在&#xff01; 相比 Vuex,Pinia 的优点&#xff1a; 更贴合 Vue 3 的 Composition API 风…

【Python】KDtree的调用

前言 查询点集中与目标点最近的k个点 from scipy.spatial import cKDTree import numpy as npdata np.array([[1,2],[1,3],[4,5]]) # 生成 100 个三维数据 tree cKDTree(data) # 创建 K-D Tree result tree.query(np.array([5, 5]), k2) # 查询与 [0.5, 0.5, 0.5] 最近的三…