【MIT 6.S081】2020, 实验记录(7),Lab: Multithreading

2024-03-13 21:44

本文主要是介绍【MIT 6.S081】2020, 实验记录(7),Lab: Multithreading,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

    • Task 1: Uthread: switching between threads
    • Task 2:Using threads
    • Task 3:Barrier

Task 1: Uthread: switching between threads

这个实验是要求实现用户级线程的创建和调度,有点类似于有栈协程。非常有意思,值得多学习。

在完成这个实验前,需要了解 XV6 如何实现的进程的调度,然后通过在模拟进程切换的逻辑实现用户级线程的创建和切换。

在 kernel 调度进程时,会使用 context 来保存被挂起的进程的寄存器上下文,我们这里也需要一个类似的结构体来保存这些上下文(在 uthread.c 中声明):

// 模仿 kernel/proc.h 中的 struct context
// 保存用户线程的上下文
struct thread_context {uint64 ra;uint64 sp;// callee-saveduint64 s0;uint64 s1;uint64 s2;uint64 s3;uint64 s4;uint64 s5;uint64 s6;uint64 s7;uint64 s8;uint64 s9;uint64 s10;uint64 s11;
};

然后将我们声明的 thread_context 结构体放入 struct thread 中:

thread_context
thread_create() 中初始化这个字段,让其中的 ra 字段指向线程需要执行的函数(因为线程切换后会执行 ra 寄存器所指向的位置),让其中的栈指针指向合适的位置:

thread-create

然后模仿 kernel 中用来切换进程的 swtch 函数,实现线程切换时上下文的切换(也就是保存现有的各个寄存器值到 context 中,把新线程的 context 中保存的各个寄存器的值写入寄存器中),函数 thread_switch() 已经声明在了 uthread.c 中,但这部分的实现需要我们模仿 kernel/swtch.S 使用汇编语言实现在 uthread_switch.S 中:

uthread_switch.S
这个最后的 ret 会回到 ra 寄存器所指向的位置,也就是我们想让这个线程所执行的函数。

最后在线程调度的函数中加入 thread_switch() 的调用,参数就是现在线程和新线程的 context 指针:

在这里插入图片描述
至此,第一个 task 就完成了。

Task 2:Using threads

这个 task 就不是在 xv6 中写代码了,而是使用 Unix 提供的 pthread 及相关工具来实现一个并发安全的 hash map。

最简单的思路就是有一个 lock,每一次对 hash map 的读写都需要先获取这个 lock 再操作。但是这会存在效率问题,因为一个 map 有很多 buckets,而大多数情况下两个线程同时写 hash map 时涉及的 buckets 并没有关联。为了解决这个问题,可以让每个 bucket 都关联一个 lock,需要访问一个 bucket 时就需要先获取这个 bucket 所关联的 lock。

首先声明 locks,锁的数量与 bucket 的数量相同:

locks 声明

然后初始化 locks:

初始化 locks

然后在 hash map 的 get 和 put 函数操作内加锁。

get 函数中,首先计算出在 entry 哪个 bucket 中,然后对这个 bucket 相关联的 lock 上锁,操作完成后再解锁:

get 操作

put 函数也是类似:

put 函数

上面完成后,这个 task 就通过了:

task 2

Task 3:Barrier

最后一个 task 的难度也不大,主要考察 pthread 中条件变量的使用,task 是实现 barrier() 函数,一共有 n 个进程,每个进程调用了 barrier() 后会等待,直到所有 n 个进程都调用了 barrier() 后才能继续进行下去。

实现难度不大,利用好 mutex 和 cond 就行:

barrier
实现好这个函数后,就可以通过测试了。

task 3

这篇关于【MIT 6.S081】2020, 实验记录(7),Lab: Multithreading的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/806290

相关文章

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Python MySQL如何通过Binlog获取变更记录恢复数据

《PythonMySQL如何通过Binlog获取变更记录恢复数据》本文介绍了如何使用Python和pymysqlreplication库通过MySQL的二进制日志(Binlog)获取数据库的变更记录... 目录python mysql通过Binlog获取变更记录恢复数据1.安装pymysqlreplicat

Servlet中配置和使用过滤器的步骤记录

《Servlet中配置和使用过滤器的步骤记录》:本文主要介绍在Servlet中配置和使用过滤器的方法,包括创建过滤器类、配置过滤器以及在Web应用中使用过滤器等步骤,文中通过代码介绍的非常详细,需... 目录创建过滤器类配置过滤器使用过滤器总结在Servlet中配置和使用过滤器主要包括创建过滤器类、配置过滤

正则表达式高级应用与性能优化记录

《正则表达式高级应用与性能优化记录》本文介绍了正则表达式的高级应用和性能优化技巧,包括文本拆分、合并、XML/HTML解析、数据分析、以及性能优化方法,通过这些技巧,可以更高效地利用正则表达式进行复杂... 目录第6章:正则表达式的高级应用6.1 模式匹配与文本处理6.1.1 文本拆分6.1.2 文本合并6

python与QT联合的详细步骤记录

《python与QT联合的详细步骤记录》:本文主要介绍python与QT联合的详细步骤,文章还展示了如何在Python中调用QT的.ui文件来实现GUI界面,并介绍了多窗口的应用,文中通过代码介绍... 目录一、文章简介二、安装pyqt5三、GUI页面设计四、python的使用python文件创建pytho

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件

记录每次更新到仓库 —— Git 学习笔记 10

记录每次更新到仓库 文章目录 文件的状态三个区域检查当前文件状态跟踪新文件取消跟踪(un-tracking)文件重新跟踪(re-tracking)文件暂存已修改文件忽略某些文件查看已暂存和未暂存的修改提交更新跳过暂存区删除文件移动文件参考资料 咱们接着很多天以前的 取得Git仓库 这篇文章继续说。 文件的状态 不管是通过哪种方法,现在我们已经有了一个仓库,并从这个仓

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

学习记录:js算法(二十八):删除排序链表中的重复元素、删除排序链表中的重复元素II

文章目录 删除排序链表中的重复元素我的思路解法一:循环解法二:递归 网上思路 删除排序链表中的重复元素 II我的思路网上思路 总结 删除排序链表中的重复元素 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 图一 图二 示例 1:(图一)输入:head = [1,1,2]输出:[1,2]示例 2:(图