6.s081 学习实验记录(七)Multithreading

文章目录

    • 一、Uthread: switching between threads
      • 简介
      • 提示
      • 实验代码
      • 实验结果
    • 二、Using threads
      • 简介
      • 实验代码
    • 三、Barrier
      • 简介
      • 实验代码
      • 实验结果

一、Uthread: switching between threads

简介

切换到 thread 分支

  • git fetch
  • git checkout thread
  • make clean

实现用户态线程的上下文切换机制,该实验已准备了 user/uthread.cuser/uthread_switch.Smakefile添加了构建规则。但是缺少了创建用户态线程以及线程切换的代码。

我们的任务就是实现一套机制,包含创建用户态线程以及保存/恢复线程上下文的功能。

完成实验之后,执行make qemu,并运行 uthread程序,应该可以看到如下图输出:
在这里插入图片描述

  • user/uthread.c中完善 thread_create()thread_schedule() 函数
  • user/uthread_switch.S 中完善 thread_switch
  • 目标是保证 thread_schedule() 首次调度一个给定的用户态线程时,该线程需要在它的栈上执行通过thread_create()创建线程时传递的函数
  • 另一个目标是保存被切换用户态线程的寄存器上下文,恢复获得cpu的线程的寄存器上下文,以使得其可以从上一次中断的位置继续执行

提示

  • thread_switch只需要保存/恢复仅由被调用者(callee)负责保存的寄存器。为什么? 这是因为线程被切换出去时肯定是在一个函数中,此时寄存器中的值只有被调用者保存的寄存器是可能被线程切换代码导致丢失的。因此需要保存,而由调用者保存的寄存器,已经在函数栈帧中保存了一次。
  • 可以在 user/uthread.asm 中看到 uthread 的汇编代码,这可以帮助调试
  • 使用 riscv64-linux-gnu-gdb 进行 thread_switch 的单步调试,方法如下:
    在这里插入图片描述

实验代码

思路:

  • user/uthread.c:添加一个struct thread_context 结构体,用于记录用户态线程上下文
  • user/uthread.c:thread_create() 完善用户态线程的创建逻辑
  • user/uthread_switch.S:实现 thread_switch() 用于保存被调度用户态线程的上下文,恢复切换用户态线程的上下文

代码:

  • user/uthread.c
//定义用户态线程上下文
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;
};struct thread {char       stack[STACK_SIZE]; /* the thread's stack */int        state;             /* FREE, RUNNING, RUNNABLE */struct thread_context context; // 新增
};void 
thread_create(void (*func)())
{struct thread *t;for (t = all_thread; t < all_thread + MAX_THREAD; t++) {if (t->state == FREE) break;}t->state = RUNNABLE;// YOUR CODE HERE// 新增memset(&t->context, 0, sizeof(struct thread_context));t->context.ra = (uint64)func;t->context.sp = (uint64)t->stack + STACK_SIZE; //栈顶为高地址
}void 
thread_schedule(void)
{struct thread *t, *next_thread;/* Find another runnable thread. */// ...if (current_thread != next_thread) {         /* switch threads?  */next_thread->state = RUNNING;t = current_thread;current_thread = next_thread;/* YOUR CODE HERE* Invoke thread_switch to switch from t to next_thread:* thread_switch(??, ??);*/// 新增:调用 thread_switch(参考内核态 swtch()函数)thread_switch((uint64)&t->context, (uint64)&next_thread->context);}// ...
}
  • user/uthread_switch.S
thread_switch:/* YOUR CODE HERE */sd ra, 0(a0)sd sp, 8(a0)sd s0, 16(a0)sd s1, 24(a0)sd s2, 32(a0)sd s3, 40(a0)sd s4, 48(a0)sd s5, 56(a0)sd s6, 64(a0)sd s7, 72(a0)sd s8, 80(a0)sd s9, 88(a0)sd s10, 96(a0)sd s11, 104(a0)ld ra, 0(a1)ld sp, 8(a1)ld s0, 16(a1)ld s1, 24(a1)ld s2, 32(a1)ld s3, 40(a1)ld s4, 48(a1)ld s5, 56(a1)ld s6, 64(a1)ld s7, 72(a1)ld s8, 80(a1)ld s9, 88(a1)ld s10, 96(a1)ld s11, 104(a1)ret    /* return to ra */

实验结果

  • uthread
    在这里插入图片描述
    在这里插入图片描述

二、Using threads

简介

本实验将使用哈希表来探索锁和线程的并发编程。
notxv6/ph.c中包含一个简单的不保证并发安全的哈希表实现,可以在xv6的主目录使用 make ph./ph 1 将产生如下结果(需要使用gcc编译,而不是riscv的交叉工具链,且结果的数值取决于具体的机器):
在这里插入图片描述
然后通过 ./ph 2尝试并发版本,将得到如下结果:
在这里插入图片描述

实验代码

本实验比较简单

static
void put(int key, int value)
{int i = key % NBUCKET;// is the key already present?struct entry *e = 0;for (e = table[i]; e != 0; e = e->next) {if (e->key == key)break;}if(e){// update the existing key.e->value = value;} else {// the key is new.pthread_mutex_lock(&locks[i]);insert(key, value, &table[i], table[i]);pthread_mutex_unlock(&lock[i]);}
}

三、Barrier

简介

实现一个 barrier,即每个线程都要在 barrier 处等待所有线程到达 barrier 之后才能继续运行。因此我们需要用到 unix 提供的条件变量以及 wait/broadcast 机制。

实验代码

static void
barrier()
{// YOUR CODE HERE//// Block until all threads have called barrier() and// then increment bstate.round.//pthread_mutex_lock(&bstate.barrier_mutex);bstate.nthread++;if (bstate.nthread < nthread) {pthread_cond_wait(&bstate.barrier_cond, &bstate.barrier_mutex);} else {bstate.round++;bstate.nthread = 0;pthread_cond_broadcast(&bstate.barrier_cond);}pthread_mutex_unlock(&bstate.barrier_mutex);
}

实验结果

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

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

相关文章

Python学习路线图

防止忘记&#xff0c;温故知新 进阶路线

使用手持激光三维扫描仪进行建筑立面测量需要注意些什么?

在进行采集作业前&#xff0c;首先需对作业区域进行实地勘察。对于某些有设计感、结构较为特殊的建筑物&#xff0c;若不提前对作业区域勘探&#xff0c;直接进行采集工作&#xff0c;往往会漏掉建筑物的某些结构特征&#xff0c;造成返工。对于建筑物结构相对简单的场景&#…

WordPress主题YIA移动端文章页的面包屑不显示怎么办?

平时我们一般都会在文章页导航菜单下方显示面包屑&#xff0c;类似于“当前位置&#xff1a;boke112百科 WordPress 正文”。平时用浏览器调试站点的时候&#xff0c;在Edge浏览器的“切换设备仿真”中&#xff0c;不管是选择什么设备都会显示面包屑。具体如下图所示&#xf…

数据库数据加密的 4 种常见思路的对比

应用层加解密方案数据库前置处理方案磁盘存取环节&#xff1a;透明数据加密DB 后置处理 最近由于工作需要&#xff0c;我对欧洲的通用数据保护条例做了调研和学习&#xff0c;其中有非常重要的一点&#xff0c;也是常识性的一条&#xff0c;就是需要对用户的个人隐私数据做好加…

【Java程序设计】【C00252】基于Springboot的实习管理系统(有论文)

基于Springboot的实习管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的实习管理系统 本系统分为前台功能模块、管理员功能模块、教师功能模块、学生功能模块以及实习单位功能模块。 前台功能模块&#xf…

Vue-router中使用pinia,const xxxStore = usexxxStore()报错

“getActivePinia()” was called but there was no active Pinia. Are you trying to use a store before calling “app.use(pinia)”? See https://pinia.vuejs.org/core-concepts/outside-component-usage.html for help. This will fail in production. at useStore (pin…

达梦数据库——数据迁移sqlserver-dm报错问题整理

报错情况一&#xff1a;Sql server迁移达梦连接报错’驱动程序无法通过使用安全套接字Q层(SSL)加密与SQL Server 建立安全连接。错误:“The server selected protocol version TLS10 is not accepted by client preferencesITLS127‘ 原因&#xff1a;历史版本的SOL SERVER服务…

D3846——三极管驱动,内置差动电流检测放大器, 共模输入范围宽,大电流输出,工作 频率可高达500KHz

D3846是一块电流模式的PWM控制电路 主要特点: 。自动前馈补偿 。可编程控制的逐个脉冲限流功能 。推挽输出结构^下自动对称校正 。负载响应特性好 。可并联运行&#xff0c;适用于模块系统内置差动电流检测放大器&#xff0c;共模输入范围宽双脉冲抑制功能 。大电流输出&#…

“挖矿”系列:细说Python、conda 和 pip 之间的关系

继续挖矿&#xff0c;挖“金矿”&#xff01; 1. Python、conda 和 pip&#xff08;挖“金矿”工具&#xff09; Python、conda 和 pip 是在现代数据科学和软件开发中常用的工具&#xff0c;它们各自有不同的作用&#xff0c;但相互之间存在密切的关系&#xff1a; Python&…

《白话C++》第10章 STL和boost,Page67~70 std::auto_ptr

std::auto_ptr可以不经意间转移裸指针控制权 std::auto_ptr持有裸指针的控制权&#xff0c;却可以随随便便看似不经意地转移给另一个auto_ptr: #include <iostream> #include <memory>using namespace std;struct S {int a;void SetA(int a){this->a a;}~S()…

SQL Extractor 数据库修复取证大师-数据库修复专家

SQL Extractor 数据库修复取证大师介绍 SQL Extractor 数据库修复取证大师 功能介绍&#xff1a;SQL Extractor数据库修复取证大师最新版本10.94软件特色:针对勒索病毒加密的SQL 数据库有特殊的修复算法,可匹配用友,金蝶数据库结构关系. 支持7.0、SQL2000、SQL2005、SQL2008、…

可视化低代码表单设计器

JNPF 表单设计器是一款在线可视化表单建模工具&#xff0c;基于VueSpringboot技术开发&#xff0c;具有组件丰富、操作简单、所见即所得等特性&#xff0c;既能够设计普通的数据录入表单&#xff0c;也能够配合流程设计出各类审批流转表单。 应用地址&#xff1a;https://www.j…

ForkJoin 的使用以及原理

原理 Fork-Join 是一种并行计算模式&#xff0c;它通常用于解决递归式或者分治式的问题。其原理基于将一个大的任务划分成若干个小任务&#xff0c;然后并行地执行这些小任务&#xff0c;最后将它们的结果合并起来得到最终的结果。 具体来说&#xff0c;Fork-Join 模式包含两个…

报错405(errAxiosError: Request failed with status code 405)

errAxiosError: Request failed with status code 405 前端调用接口的方法跟后台定义接口的方法不一致

论文阅读:MotionNet基于鸟瞰图的自动驾驶联合感知和运动预测

MotionNet: Joint Perception and Motion Prediction for Autonomous Driving Based on Bird’s Eye View Maps MotionNet&#xff1a;基于鸟瞰图的自动驾驶联合感知和运动预测 论文地址&#xff1a;MotionNet: Joint Perception and Motion Prediction for Autonomous Drivi…

C++-opencv的imread、imshow、waitkey、namedWindow

在C中使用OpenCV时&#xff0c;imread和imshow是两个非常基础且常用的函数&#xff0c;用于读取图像和显示图像。以下是这两个函数的简要说明和如何一起使用它们的示例。 imread函数 imread用于从指定的文件路径读取图像。它将图像读入为cv::Mat对象&#xff0c;这是OpenCV中…

走进水墨世界,寻找传统之美

为深入了解中国传统水墨文化的底蕴及其在当代的价值&#xff0c;2024年2月16日&#xff0c;曲阜师范大学计算机学院“古韵新声&#xff0c;格物致‘知’”实践队的队员王涵智走进山东省高唐县巩德春艺术馆展开社会实践。实践队员以探访艺术馆为契机&#xff0c;领略传统水墨文化…

Academic Inquiry|投稿状态分享(ACS,Wiley,RSC,Elsevier,MDPI,Springer Nature出版社)

作为科研人员&#xff0c;我们经常会面临着向学术期刊投稿的问题。一般来说&#xff0c;期刊的投稿状态会在官方网站上进行公示&#xff0c;我们可以通过期刊的官方网站或者投稿系统查询到我们投稿的论文的状态&#xff0c;对于不同的期刊在投稿系统中会有不同的显示。 说明&am…

如何查看HP打印机的Wi-Fi密码?这里提供三种方法

如果你计划通过Wi-Fi Direct从笔记本电脑或智能手机无线打印&#xff0c;则需要HP打印机密码。有了这个功能&#xff0c;打印机可以创建自己的Wi-Fi网络&#xff0c;你不需要依赖其他Wi-Fi网络。你只需转到设备的Wi-Fi设置&#xff0c;将其连接到Wi-Fi Direct&#xff0c;然后立…

OpenAI全新发布的Sora,到底意味着什么?

16日凌晨&#xff0c;OpenAI发布了文本视频的工具&#xff08;text-do-video&#xff09;Sora&#xff0c;整个世界再次被震撼。 Sora的出现&#xff0c;到底意味着什么&#xff1f; 目录 Sora的背景与概述Sora是什么&#xff1f;能为我们做些什么&#xff1f;存在的一些问题 文…