【MIT 6.S081】Lab7: Multithreading

MIT6.S081学习总结-lab7:Multithreading lab7 是多线程相关,将会实现一个用户级线程,使用多线程加速程序以及实现一个barrier Uthread:switching between threads 实现用户级线程的切换,主要修改thread_create()、thread_schedule()和thread_switch. 实现: 刚开始没怎么懂,照着kernel里的swtch写了一下,竟然过了 新增上下文数据结构: thread_create里初始化该线程上下文信息中的ra和sp寄存器值,ra是返回地址,就是函数返回之后继续执行的点,sp 阅读详情

本Lab比较简单,就是为xv6添加一个用户级的多线程功能,然后熟悉一下Linux下多线程编程。
笔者用时约2h

Uthread: switching between threads

这一部分的代码不涉及内核代码,所以也比较简单,根据提示修改user/uthread.c中的代码即可。仿照内核中进程转换函数swtch的实现即可。首先,添加一个context上下文结构体用于保存被调用者保存寄存器(从kernel/proc.h中复制过来就行啦)。

struct context {
  uint64 ra;
  uint64 sp;

  // callee-saved
  uint64 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 {
  char       stack[STACK_SIZE]; /* the thread's stack */
  int        state;             /* FREE, RUNNING, RUNNABLE */
  struct context context;
};

然后需要仿照swtch函数(定义在kernel/swtch.S中)实现一个thread_switch函数(定义在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 */

然后为thread_create函数添加代码,为线程初始化上下文字段,最重要的两个寄存器是ra和sp,其中ra寄存器需要指向传进来的线程函数,在thread_switch函数中将被替换到CPU的ra,作为返回地址,即起到了一个跳板的作用,跳到了线程函数中;sp寄存器则需要指向线程的栈。

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
  t->context.ra = (uint64) func;
  t->context.sp = (uint64) (t->stack + STACK_SIZE);
}

在thread_schedule函数中,增加一句代码调用thread_switch函数进行线程转换即可。

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((uint64)&t->context, (uint64)&current_thread->context);
  }

Using threads

首先回答一个问题:
Q: 为什么两个线程都丢失了键,而不是一个线程?确定可能导致键丢失的具有2个线程的事件序列。
A: 当两个线程同时调用put且插入的哈希bucket是同一个时,涉及到链表插入的并发性问题,
其实在xv6-book中第六章有讲到过。由于这里是头插法,修改头指针指向当前新插入的节点时,
如果两个线程的操作交叉运行,则后运行的一个会被前运行的一个覆盖,使得插入的节点少了一个,
这种行为是不可预测的,所以两个线程都有可能丢失。

然后需要为代码加锁以修复并发put的问题,考虑如果两个线程并发put到两个不同的bucket中,不会引发问题,于是为每一个bucket设置一个锁即可。

pthread_mutex_t lock[NBUCKET];

然后在put函数中加上锁即可。

if(e){
    pthread_mutex_lock(&lock[i]);
    // update the existing key.
    e->value = value;
    pthread_mutex_unlock(&lock[i]);
} else {
    // the new is new.
    pthread_mutex_lock(&lock[i]);
    insert(key, value, &table[i], table[i]);
    pthread_mutex_unlock(&lock[i]);
}

Barrier

这一部分据文档描述就是加上一层屏障,进行线程同步,需要使用条件变量的知识,这里就不细说了,简单来说就是,让一些快的线程等一会,让最后一个到达的线程通知大家说可以继续走了,实现起来也很简单。

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);
    pthread_mutex_unlock(&bstate.barrier_mutex);
    return;
  }
  bstate.nthread = 0;
  bstate.round ++;
  pthread_mutex_unlock(&bstate.barrier_mutex);
  pthread_cond_broadcast(&bstate.barrier_cond);
}
操作系统:操作系统(MIT 6.S081 2020年秋季)代码 MIT 6.S081操作系统2020秋季 课程网页: : 我们在课程中实施实验室实验。 我们还将实现讲义中的一些示例 以及讲座视频。 当文件来自分配时,文件名与分配中的文件名相同。 当它们是示例时,我们使用“ example_xxx”。 立即下载

相关推荐

xv6-labs-2020:MIT 6.S081 2020秋季操作系统

xv6-riscv-lab MIT 6.S081 / 2020年秋季实验室 进度 Lab1 Lab2 Lab3 Lab4陷阱 Lab5延迟分配 Lab6写时复制 Lab7多线程 Lab8锁 Lab9文件系统 Lab10 mmap Lab11网络驱动程序 文件 Lab1 Lab2 Lab3

6.S081 lab7 Multithreading

1. 任务   任务主要有3个:将所给代码补充完整,简单实现用户级的多线程;使用多线程+锁体验程序速度提升;实现barrier函数(多线程同步机制)。 1.5 补充   在barrier函数的实现中,用到了之前没用过的pthread函数,在此记录一下函数语义。 int pthread_cond_init(pthread_cond_t* cond, pthread_condattr_t *cond_attr); int pthread_cond_destroy(pthread_cond_t* cond);

passenger12234的博客 463

MIT6.S081

MIT6.S081

[MIT 6.S081] Lab 7: Multithreading

Lab 7: Multithreading Lab Guidance: https://pdos.csail.mit.edu/6.828/2020/labs/thread.html Lab Code: https://github.com/VastRock-Huang/xv6-labs-2020/tree/thread Uthread: switching between threads (moderate) 要点 添加代码到 user/uthread.c 的 thread_create(), thr

LostUnravel的博客 4984

人工势场法在自动驾驶避障中的实践与优化

本文深入探讨了人工势场法在自动驾驶避障中的核心原理与实践优化。通过解析引力与斥力模型,揭示了经典算法在局部最优和目标不可达等问题上的局限性,并重点介绍了改进斥力场函数、引入道路边界斥力及动态参数调整等关键优化策略,有效提升了该局部路径规划算法在复杂动态场景下的实用性与鲁棒性。

weixin_29208327的博客 925

VMware + ubuntu20.04 + qemu安装

遇到报错可参考:(从ubuntu裸系统开始安装)

NosONE 3230

【mit 6.S081】学习笔记 Lab7 Multithreading

另外一个,无论是程序主动 sleep,还是时钟中断,都是通过 trampoline 跳转到内核态 usertrap(保存 trapframe),然后再到达 swtch 保存上下文的。的功能,所以说对照内核中的线程调度机制很有必要,这里的线程感觉更像协程,原因是这里的线程是完全用户态实现的,多个线程也只能运行在一个 CPU 上,并且没有时钟中断来强制执行调度,需要线程函数本身在合适的时候主动 yield 释放 CPU。上锁的粒度会影响程序的效率,所以我将锁的粒度降低到每一个桶一个锁。

zhu_hao_jie的博客 640

基于Open Cluster Management构建企业级多Kubernetes集群管理平台OpenClaw

在云原生架构中,Kubernetes已成为容器编排的事实标准。随着业务规模扩大,企业往往需要管理分布在多个云环境或数据中心的Kubernetes集群,这带来了集群管理、应用分发、策略统一和监控运维等复杂挑战。多集群管理技术通过提供统一控制平面,实现了对分布式资源的集中管控,其核心价值在于提升运维效率、保障安全合规并降低管理成本。Open Cluster Management(OCM)作为CNCF沙箱项目,采用Kubernetes原生架构,通过自定义资源定义(CRD)和控制器模式,为构建多集群管理平台提供了标

weixin_33747129的博客 367

MIT6.S081最详解析与归纳——lab7:Multithreading

又因为get()是只读操作,不会修改临界资源的值,所以,我们只需要给put()的临界区上锁即可。调用编写好的thread_switch即可完成工作,此处不涉及锁,也没有所谓的调度线程,直接从旧线程的上下文切换到新线程的上下文即可。额外提一点,这里增加桶的数量NBUCKET,会减少访问临界资源的概率,也就减少了锁导致的性能开销,因此也可以大大提高程序的并行效率。在多线程编程中,Barrier(屏障)是一种同步机制,用于使一组线程在某个特定的同步点(即屏障点)等待,直到所有线程都达到这个点。

qq_45456064的博客 1122

超详细YOLOv8姿态检测全程概述:环境、训练、验证与预测详解

本篇博客详细介绍了使用YOLOv8-pose进行姿态估计的全过程,包括不同版本模型的性能比较、训练与验证步骤,以及预测代码的实现。它对模型参数、训练过程和输出结果进行了解释,同时提供了详细的配置文件示例和标签数据格式说明。此外,还演示了如何使用预训练模型进行图像预测,并如何处理和理解预测结果。最后,它还讨论了如何评估和比较不同模型的性能。如果有哪里写的不够清晰,小伙伴本可以给评论或者留言,我这边会尽快的优化博文内容,另外如有需要,我这边可支持技术答疑与支持。

CDBmax的博客 3万+

保姆级教程:在RK3568上搞定PR2100K+GC2385双摄(从DTS配置到HAL层补丁)

本文详细介绍了在RK3568平台上调试PR2100K+GC2385双摄系统的完整流程,从DTS配置到HAL层补丁。涵盖硬件连接、媒体控制器拓扑验证、Camera3配置、HAL层特殊补丁及性能优化等关键步骤,帮助开发者快速解决双摄调试中的常见问题,提升嵌入式视觉系统开发效率。

weixin_28724661的博客 195

MIT 6.S081 Lab 7 Multithreading

作用:声明一个互斥锁变量。功能:用于保护共享资源,确保同一时间只有一个线程可以访问临界区代码,防止数据竞争(Data Race)。互斥锁需要先初始化后使用。静态初始化可使用宏,动态初始化需调用。作用:初始化互斥锁。&lock:指向互斥锁的指针。NULL:表示使用默认属性(如非递归锁)。也可通过属性对象设置特殊行为(如递归锁、优先级继承等)。注意:动态初始化的互斥锁需在不再使用时调用释放资源。作用:尝试获取互斥锁。若锁未被持有,线程立即获得锁并继续执行。

weixin_51972899的博客 1042

欧姆龙 CJ1W-SCU模块使用通配符+结束码实现非固定长度数据的接收

实验设备:CJ2M-CPU33、CJ1W-SCU21、XW2Z-200T 实验目的:了解 CJ1W-SCU 通配符使用 1.硬件接线: CJ1W-SCU21单元号拨码置于8,使用串口1(232口)。 2.软件设置: ① 新建工程,选择PLC型号CJ2M-CPU33,切换到编程模式,如下图: 、 ② 创建I/O并进行相关配置,如下图: ③ 设置为用户设置,协议宏模式,8位数据位,2位停止位,偶校验9600波特率,如下图: 、 ④ 打开CX-Protocal软件,新建工程: .

weixin_42118352的博客 1984

MIT6.S081 - Lab7 Multithreading(进程调度)

本篇是 MIT6.S081 操作系统课程 Lab7 的实验笔记,任务是模仿内核进程切换,写一个用户级线程切换功能。同时,我也会结合源码,介绍 xv6 是如何完成进程切换的。

1153

基于FFT+BP神经网络/决策树的轴承故障诊断

基于FFT+BP神经网络/决策树的轴承故障诊断

天天酷科研的博客 131

创建 Fiori Space 时看不到传输请求的根因与排查路径

摘要: 在创建Fiori Space时,若Transport字段下拉列表为空,通常是因为系统未找到符合要求的传输请求。主要原因是: 请求类型不匹配:需使用Customizing request而非Workbench request。 用户权限问题:当前用户需在请求下有可用的task。 客户端或系统不一致:请求需在当前客户端和正确系统(如后端)中创建。 解决方法: 在当前客户端和系统中新建Customizing request,确保包含用户task。 检查是否为前后端分离架构,确保请求创建在正确的系统。 验证

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 107

MIT 6.S081 Lab7: Multithreading

这个实验是多线程安全和同步的内容,实验地址在这里。说实话,有点简单,用了一天时间就写完了,感觉最近的实验,从实验三之后难度就降低了很多。但是实验的内容还是很有用的,主要学习了一遍线程的切换过程,感觉受益很多,建议看一下课程里对应的多线程部分。我的实验代码在 github 上,感觉这个实验没太多代码和步骤需要分析,主要是基础知识,这里就随便写点我觉得重要的了。

落队的飞行兵 1411

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

MIT 6.S081 lab 7:Multithreading

1 Uthread: switching between threads 在本次练习中,你将要设计面向用户级线程系统的上下文切换机制,然后实现它。为了帮助你开始实现它,xv6提供了两个文件,user/uthread.c和user/uthread_switch.S,和一个在Makefile文件中提供的build uthread 程序的规则。uthread.c包括绝大多数用户级线程包,和三个简单的线程测试样例。这个线程包中丢失了部分创建线程和转换线程的代码。 你的任务是提出一种创建线程和在线程切换中保存/恢复寄

weixin_43174477的博客 1110

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

MIT 6s081 lab7:Multithreading

在调用本函数 uthread_switch() 的过程中,caller-saved registers 已经被调用者保存到栈帧中了,所以这里无需保存这一部分寄存器。当线程进入barrier时,将已进入屏障的线程数+1,然后判断是否全部到达,如果未到达,则休眠等待,如果已经到达,就唤醒所有在等待的线程,所有线程继续运行。这个实验其实相当于在用户态重新实现一遍 xv6 kernel 中的 scheduler() 和 swtch() 的功能,所以大多数代码都是可以借鉴的。实现一个用户态的线程库。

厚积而薄发 501

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

「实验记录」MIT 6.S081 Lab7 multithreading

MIT 6.S081 Lab7 multithreading

士全的优快云,用心连载,欢迎关注 1012

【MIT6.S081】Lab7: Multithreading(详细解答版)

实验内容网址:https://xv6.dgs.zone/labs/requirements/lab7.html本实验的代码分支:https://gitee.com/dragonlalala/xv6-labs-2020/tree/thread2/关键点:线程切换、swtch。

lllllllllljg的博客 1839

MIT 6.S081 2020 Lab7 Multithreading 个人全流程

本实验将使你熟悉多线程编程。你将实现一个用户级线程库中的线程切换,使用多个线程加速程序运行,并实现一个屏障(Barrier)机制。

EQUINOX1的博客 950

mit6s081 lab7 Multithreading

实验的主要内容就是了解线程是如何切换的,通过保存和恢复上下文信息,使得线程可以透明地切换。同时对于多线程并行的情况,对于共享数据的更改,需要上锁保证共享变量不会因为线程并行出错。

qq_55841287的博客 679

MIT6.S081 Lab7 Multithreading

your xv6 has two files user/uthread.c and user/uthread_switch.S a rule in the Makefile to build a uthread program 你的任务是创建一个线程,并保留不同线程之间的寄存器值 add code to thread_create() and thread_schedule() in user/uthread.c, and thread_switch in user/uthread_switch.

newbaby2012的专栏 491

操作系统实验Mit6.S081笔记 Lab7:Multithreading

Uthread: switching between threads (moderate) 要求: 在本练习中,您将为用户级线程系统设计上下文切换机制,然后实现它。为了让您开始,您的 xv6 有两个文件 user/uthread.c 和 user/uthread_switch.S,以及 Makefile 中用于构建 uthread 程序的规则。uthread.c 包含大部分用户级线程包,以及三个简单测试线程的代码。threading 包缺少一些用于创建线程和在线程之间切换的代码。 您的工作是制定一个计划来创

weixin_46477226的博客 2373

[mit6.s081] 笔记 Lab7: Multithreading

本实验将使您熟悉多线程。您将在用户级线程包中实现线程之间的切换,使用多个线程来加速程序,并实现一个屏障。Attention在编写代码之前,您应该确保已经阅读了xv6手册中的“第7章: 调度”,并研究了相应的代码。

m0_61705102的博客 817
上一篇: 【MIT 6.S081】Lab6: Copy-on-Write Fork for xv6
下一篇: 【MIT 6.S081】Lab8: Locks
juruo_c
博客等级 码龄6年 520粉丝 116原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值