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,一经查实,立即删除!

相关文章

从Unity到Three.js(动态创建mesh)

js var let const基础 手动创建模型mesh功能测试&#xff0c;此功能跑通就可以实现很多功能了&#xff0c;如点云转mesh&#xff0c;磨碎效果等等。 import * as THREE from three;const scene new THREE.Scene(); const camera new THREE.PerspectiveCamera(60, window.in…

Python学习路线图

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

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

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

LLM(2)之指令提示词(Prompt)基础教学

LLM(2)之指令提示词 Author&#xff1a;Once Day Date&#xff1a;2024年2月15日 全系列专栏请查看:LLM实践成长_Once_day的博客-CSDN博客 参考文章&#xff1a; 中文完整版全9集ChatGPT提示工程师&#xff5c;AI大神吴恩达教你写提示词ChatGPT Shortcut - 简单易用的 Chat…

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…

MySQL篇之索引创建与失效

一、索引创建的原则 1). 针对于数据量较大&#xff0c;且查询比较频繁的表建立索引。 2). 针对于常作为查询条件&#xff08;where&#xff09;、排序&#xff08;order by&#xff09;、分组&#xff08;group by&#xff09;操作的字段建立索引。 3). 尽量选择区分度高的列作…

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;共模输入范围宽双脉冲抑制功能 。大电流输出&#…

代码随想录算法训练营第44天(动态规划06 ● 完全背包 ● 518. 零钱兑换 II ● 377. 组合总和 Ⅳ

动态规划part06 完全背包518. 零钱兑换 II解题思路 377. 组合总和 Ⅳ解题思路 详细布置 力扣上没有纯粹的完全背包的题目&#xff0c;所以大家看本篇了解一下 完全背包的理论 后面的两道题目&#xff0c;都是完全背包的应用&#xff0c;做做感受一下 完全背包 视频讲解&#xf…

bat脚本 创建计划任务 一分钟设置ntp同步周期为60s

要在Windows中使用批处理脚本&#xff08;.bat&#xff09;创建一个计划任务来每分钟同步一次NTP时间&#xff0c;你可以使用schtasks命令来创建计划任务。下面是一个示例脚本&#xff0c;展示了如何创建这样一个计划任务&#xff1a; echo off set "taskNameSyncNTP"…

“挖矿”系列:细说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、…

ES实战--性能提升

触发冲刷的条件: 1.内存缓冲区已满 2.自上次冲刷后超过了一定时间 3.事务日志达到了一定阀值 对名为get-together的Elasticsearch索引执行优化操作&#xff0c;将索引中的数据段&#xff08;segments&#xff09;合并到指定的数量1 GET /get-together/_optimize?max_num_segm…

【微信小程序】小程序的双线程架构,为什么要设计成双线程的

微信小程序是双线程的&#xff0c;有渲染层和逻辑层两个执行环境&#xff0c;渲染层负责页面的渲染和样式&#xff0c;逻辑层负责小程序的逻辑和数据处理。 渲染线程&#xff1a;负责渲染界面&#xff0c;包括解析 wxml&#xff0c;wxss&#xff0c;样式计算&#xff0c;布局排…

可视化低代码表单设计器

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

Python函数——函数介绍

一、引言 在Python编程中&#xff0c;函数是构建高效代码的关键。通过创建可重用的代码块&#xff0c;我们可以使程序更加清晰、易读且易于维护。在本文中&#xff0c;我们将深入了解Python函数的基本概念及其特性。 二、Python函数的基本概念 函数是一段具有特定功能的代码块…