制作一个RISC-V的操作系统十四-任务同步和锁

文章目录

  • 并发与同步
  • 临界区和锁
  • 死锁
  • 解决死锁
  • 自旋锁(spin lock)
  • 原子性问题
  • 原子操作实现
    • amoswap.w.aq
    • 例子
  • 另一种方法
  • 自旋锁的注意事项
  • 代码
  • 其他同步技术

并发与同步

控制流:可理解为任务或进程

中断也可以理解为一个切换到另一个任务(中断处理程序),于是宏观上认为同时执行了

同步:可以理解要求某个任务的某个操作与某个任务的某个操作的先后顺序有要求
在这里插入图片描述

临界区和锁

在这里插入图片描述
并发执行中,当一个进程访问临界区时,除非访问结束,否则其他进程(即使切换到了该进程)不能进入临界区即阻塞。不然影响该进程对临界区资源的使用。

临界区是指在多线程环境中,同一时刻只允许一个线程访问的一段代码或资源区域。为了确保临界区的安全访问,避免因多个线程同时访问导致的数据不一致或其他竞态条件,我们需要采取同步措施来保护临界区

  • 当线程尝试获取一个已被其他线程持有的可睡眠锁时,如果锁不可用,该线程会被操作系统挂起,并放入等待队列中,从而停止执行(进入睡眠状态)。一旦持有锁的线程释放了锁,操作系统会选择合适的线程将其唤醒并赋予其锁的所有权。这样,线程就可以继续执行被保护的代码段。
  • 不可睡眠锁在尝试获取锁时,如果锁被占用,当前线程并不会被挂起,而是会在原地循环等待(自旋),不断检查锁是否已经释放。这种方式避免了线程上下文切换的开销,但可能会导致线程消耗大量的CPU资源,尤其是当锁被持有时间较长时。
    在这里插入图片描述

上锁导致另一个进程也要上锁时阻塞然后一直循坏,。直到最后解锁

死锁

访问多个临界区可能就需要涉及多个锁

当按照A执行获取A锁,然后B执行获取B锁,A再获取B锁,B再获取A锁
这样将导致阻塞。即再切换到A准备获取B锁,然后再切换到B获取A锁会阻塞。二者都卡住
在这里插入图片描述

解决死锁

除了三点之外还可以实现申请多个锁一次性申请,不中断。可以解决

调整获取锁的顺序,因为上个例子中申请锁的顺序不一致也是导致死锁的原因
防止在持有一把锁再申请其他锁就是尽量保存申请一把锁之前申请的锁都释放掉
在这里插入图片描述

自旋锁(spin lock)

  • 初始话锁
  • 在不同控制流访问临界区的前后执行上锁和解锁
    在这里插入图片描述

原子性问题

中断的级别是针对到汇编指令级别的

也就是说上锁操作可能还没完成就中断然后跳转到另一个控制流导致另一个控制流此时发现锁没有被锁上,导致两个都进入临界区(第一个汇编执行进入了if但没有设置locked导致第二个此时也能进入if并上锁)
在这里插入图片描述

原子操作实现

amoswap.w.aq 将locked值存到寄存器,同时locked的值更新为寄存器的值即为1。不会被打断

这里把值的变化给一气呵成完成了,使得不会出现锁没来得及更新就切换到另一个进程使得其也认为没上锁。(也可以认为让值的更新在判断是否进入临界区之前)

如果不是原子性的,那么假设分为几部分实现更新值和保存原来值的作用,那么可能会得到死锁或者同时进入临界区的结果

发现在只有执行这条指令的执行流会上锁,其他都不会,哪怕是快接触到该指令的执行流
在这里插入图片描述

amoswap.w.aq

在RISC-V架构中,amoswap.w.aq指令是原子内存操作指令之一,主要用于并发环境下的原子读改写内存操作。这个指令的名字来源于几个关键词的组合:

  • amo: AtomiC Memory Operation,原子内存操作,表明这条指令在执行过程中是不可分割的,即使在多线程或多处理器环境下也能确保操作的原子性。
  • swap: 表示该指令执行的是交换操作,即将寄存器中的值与内存位置的内容进行交换。
  • w: 表示操作的数据宽度是32位(word大小)。
  • aq: 是Atomicity Qualifier(原子性限定符)的一部分,RISC-V架构中使用aq和rl两个原子性顺序标签来配合实现内存排序模型。其中,aq(Acquire)确保了指令的执行不会与之前的内存操作重排,并且在指令执行后能够观察到对其他核心的写入操作。

amoswap.w.aq指令的具体功能是这样的:

  • 它同时读取内存位置(通过指定的地址)的原始值,并将寄存器中的值写入该内存位置。
  • 最终,指令会将读取到的原始内存值存储到另一个指定的寄存器中。

这一系列操作作为一个单一的原子步骤完成,这对于维护数据一致性至关重要,特别是在多线程并发访问共享内存区域时。

例如,amoswap.w.aq rs2, rs1, (ra) 指令格式中:

  • rs1 是要写入内存的新值的源寄存器。
  • rs2 是保存内存原值的目标寄存器。
  • ra 是包含要操作的内存地址的寄存器。
  1. aq(Acquire)

    • 当一个带有"aq"标签的指令被执行时,它起到“获取”内存屏障的作用,确保该指令在其之前的内存读写操作都已完成,并且这些操作对于后续的操作(包括本核和其他核)都是可见的。
    • 即,amoswap.w.aq指令不仅本身是原子性的,而且还能保证在执行该指令之后,任何对共享变量的读取操作都能够看到指令之前发生的所有写入操作的效果,有效地阻止了指令重排序。
  2. rl(Release)

    • 相对应的,带有"rl"标签的指令意味着它是一个“释放”内存屏障,确保该指令执行时,它及其之前的所有内存操作全部完成,并且在这条指令之后的写入操作对其他核将是不可见的,直到下一个带有"aq"标签的指令执行。
    • 也就是说,amoswap.w.rl指令在写入共享内存后,其他核心只有在执行了自身的"aq"指令后才能看到这次写入的结果。

例子

假设存在两个核心Core A和Core B,它们共享一块内存区域,并且Core A正在修改某个变量shared_var,而Core B需要读取shared_var的最新值。如果不加控制,可能出现以下情况:

  1. Core A首先修改了shared_var的值,但由于缓存一致性等因素,这个修改还没有刷新到主内存;
  2. Core B此时去读取shared_var,由于没有内存排序保障,可能会读取到旧值而非Core A刚修改的新值。

为了保证Core B能看到Core A的写入操作,我们可以使用带有aq标签的原子指令。例如,在RISC-V架构中,如果我们有一个amoswap.w.aq指令:

amoswap.w.aq t1, t2, (a0)

这条指令会将寄存器t2的值原子性地写入地址a0指向的内存位置,并且返回原来内存位置的值到t1。更重要的是,这里的aq标识确保了在执行此原子操作之前,所有内存操作都已经完成并且对外部核心可见,也就是说Core B在执行amoswap.w.aq指令之前,一定能观察到Core A对该共享内存的先前写入。

另一种方法

上锁可以理解为直接关掉中断,使得只有对应进程上锁后,逻辑就无法被切换,进而一直执行该执行流
在这里插入图片描述

自旋锁的注意事项

上锁需要是原子性操作
不能执行长时间,不然使得其他进程占用CPU大量时间但啥事没做
不能主动放弃CPU不然没有解锁,其他进程永远无法访问临界区
在这里插入图片描述

代码

https://github.com/FULLK/risllkos/tree/main/Fullkenerl9

其他同步技术

在这里插入图片描述
在操作系统和多线程编程中,完成变量(Completion Variable)是一种同步原语,主要用于实现线程或进程间的同步,尤其是在一个任务完成特定工作后通知另一个任务的场景。其核心作用在于简化并发环境下的协作流程。

具体来说,完成变量的主要作用包括:

  1. 任务标记:一个任务在完成某项操作后,它可以设置(或增加计数)一个完成变量,表明某个关键阶段已经结束。

  2. 阻塞与唤醒:其他任务可以在等待这个完成变量,当它们检测到变量被设置或等待计数达到预期值时,会被自动唤醒并恢复执行。这样,一个任务可以在开始执行下一个阶段之前,安全地等待前一个任务完成其工作。

  3. 替代信号量:在某些情况下,完成变量可以作为信号量的轻量级替代品,特别是在只需要一次性通知而不是多次信号控制的情况下。相比于传统的信号量,完成变量通常更易于理解和使用,因为它们直接关联到一个特定的操作完成与否。

例如,在Linux内核中,完成变量 (completion) 是一种内建的数据结构和API,它允许内核线程或其他并发实体之间进行同步。一个典型的使用场景是,当一个内核线程发起I/O操作后,可以挂起自己并在完成变量上等待,直到I/O完成,设备驱动或者其他相关部分会触发这个完成变量以唤醒等待的线程。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 226.翻转二叉树

题目描述 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 示例 1: 输入:root [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1]示例 2: 输入:root [2,1,3] 输出:[2,3,1]示例…

CMake+qt+Visual Studio

#使用qt Creator 创建Cmake 项目,使用Cmake Gui 生成sln 工程,使用Visual Studio 开发 ##使用qt Creator 创建CMake项目 和创建pro工程的步骤一致,只是在选择构建系统的步骤上选择CMake,接下来步骤完全相同 工程新建完成之后,构建cmake 项…

想冲宇宙厂,直接挂了。。。

宇宙厂实际是字节,这个称呼是因为字节跳动主宰了宇宙内一切App,有点家大业大的意思。 今天分享一位字节春招凉经,问了一些数据库和Java八股,没出算法题,直接挂了,竟然最喜欢出算法题的字节,这次…

刷代码随想录有感(49):找树左下角的值

题干&#xff1a; 用层序遍历方便些&#xff0c;因为只需要把res不断替换成每一层第一个节点值即可&#xff0c;代码如下&#xff1a; class Solution { public:int findBottomLeftValue(TreeNode* root) {queue<TreeNode*>que;if(root ! NULL)que.push(root);int res …

C++中的数据结构与算法

随处可见的红黑树 一般会用到[key,value]。 例如github中这个例子&#xff0c;第一个是访问网站&#xff0c;第二个是访问次数&#xff0c;但是这个不是静态的&#xff0c;这有个动态排序&#xff0c;并且当我们需要让相应的访问次数加1的时候&#xff0c;我们用红黑树查找的时…

C++每日一练——杨辉三角

给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例 2: 输入: numRows 1 输出: [[1]]提示: 1 <…

Jsoncpp搭建交叉编译环境(移植到arm)

1. 官网下载源码 github地址&#xff1a;GitHub - open-source-parsers/jsoncpp at update 2. 交叉编译环境 当前平台/开发平台-编译环境&#xff1a; [rootlocalroot ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) [rootlocalroot ~]# uname -a Lin…

ELK创建仪表盘

创建仪表盘步骤&#xff1a; 一、保存search二、生成饼图三、创建仪表盘 一、保存search 首先保存一段时间内的search&#xff0c;可以添加想要的字段&#xff0c;并保存这个search方便下次直接打开该search&#xff0c;并方便在可视化和仪表盘中使用该search. 二、生成饼图…

Mac安装telnet

一、安装Homebrew 1、打开官网&#xff1a;Homebrew — The Missing Package Manager for macOS (or Linux) 2、打开终端输入&#xff1a; /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 二、安装Telnet bre…

数字文旅重塑旅游发展新格局:以数字化转型为突破口,提升旅游服务的智能化水平,为游客带来全新的旅游体验

随着信息技术的迅猛发展&#xff0c;数字化已成为推动各行各业创新发展的重要力量。在旅游业领域&#xff0c;数字文旅的兴起正以其强大的驱动力&#xff0c;重塑旅游发展的新格局。数字文旅以数字化转型为突破口&#xff0c;通过提升旅游服务的智能化水平&#xff0c;为游客带…

急急急!微信朋友圈删除了怎么恢复?

微信朋友圈是我们与朋友分享生活点滴的重要平台&#xff0c;但有时候微信出现异常&#xff0c;导致我们编辑好的朋友圈被删除了&#xff0c;这时候该怎么办呢&#xff1f; 幸运的是&#xff0c;微信提供了一种简单的方式来恢复已删除的朋友圈内容。微信朋友圈删除了怎么恢复&a…

四信数字孪生水库解决方案,加快构建现代化水库运行管理矩阵

近年&#xff0c;水利部先后出台《关于加快构建现代化水库运行管理矩阵的指导意见》与《构建现代化水库运行管理矩阵先行先试工作方案》等文件&#xff0c;明确总体要求及试点水库、先行区域建设技术要求等&#xff0c;为全面推进现代化水库运行管理矩阵建设工作提供依据。 《2…

【Elasticsearch<一>✈️✈️】简单安装使用以及各种踩坑

目录 &#x1f378;前言 &#x1f37b;一、软件安装&#xff08;Windows版&#xff09; 1.1、Elasticsearch 下载 2.1 安装浏览器插件 3.1、安装可视化工具 Kibana 4.1、集成 IK 分词器 &#x1f37a;二、安装问题 &#x1f379;三、测试 IK 分词器 ​&#x1f377; 四、章…

spi接口的基本概念、引脚定义及注意事项

目录 基本概念 引脚定义 注意事项 SPI&#xff08;Serial Peripheral Interface&#xff09;是一种同步串行接口技术&#xff0c;广泛应用于微控制器和各种外围设备之间的短距离通信。 基本概念 SPI接口允许微控制器以串行方式与一个或多个外围设备进行通信。它是一种高速、…

统信UOS下如何配置全局搜索

原文链接&#xff1a;统信UOS下如何配置全局搜索 Hello&#xff0c;大家好啊&#xff01;全局搜索是操作系统中非常实用的一个功能&#xff0c;它可以帮助我们快速定位文件、程序和其他资源。今天&#xff0c;我要给大家介绍如何在统信UOS桌面操作系统上配置全局搜索&#xff0…

IT廉连看——UniApp——样式绑定

IT廉连看——UniApp——样式绑定 一、样式绑定 两种添加样式的方法&#xff1a; 1、第一种写法 写一个class属性&#xff0c;然后将css样式写在style中。 2、第二种写法 直接把style写在class后面 添加一些效果&#xff1a;字体大小 查看效果 证明这样添加样式是没有问题的…

基于阶梯碳交易的含P2G-CCS耦合和燃气掺氢的虚拟电厂优化调度(matlab代码)

目录 1 主要内容 系统结构图 P2G-CCS 耦合模型 系统掺氢分析 其他算例对比 2 部分代码 3 下载链接 1 主要内容 该程序复现《基于阶梯碳交易的含P2G-CCS耦合和燃气掺氢的虚拟电厂优化调度》模型&#xff0c;以碳交易和碳封存成本、燃煤机组启停和煤耗成本、弃风成本、购…

数据结构-二叉搜索树(BST)

目录 什么是二叉搜索树 二叉搜索树的特性 (1)顺序性 (2)局限性 二叉搜索树的应用 二叉搜索树的操作 (1)查找节点 (2)插入节点 (3)删除节点 (4)中序遍历 什么是二叉搜索树 如图所示&#xff0c;二叉搜索树&#xff08;binary search tree&#xff09;满足以下条件。…

2024长三角快递物流展:科技激荡,行业焕发新活力

7月8日&#xff0c;杭州将迎来快递物流科技盛宴&#xff0c;这是一年一度的行业盛会&#xff0c;吸引了全球领先的快递物流企业和创新技术汇聚一堂。届时&#xff0c;会展中心将全方位展示快递物流及供应链、分拣系统、输送设备、智能搬运、智能仓储、自动识别、无人车、AGV机器…

【树莓派】yolov5 Lite,目标检测,行人检测入侵报警,摄像头绑定

延续之前的程序&#xff1a; https://qq742971636.blog.csdn.net/article/details/138172400 文章目录 播放声音pygame不出声音怎么办&#xff08;调节音量&#xff09;树莓派上的音乐播放器&#xff08;可选&#xff09;命令行直接放歌&#xff08;尝试放mp3歌曲&#xff09; …