6.S081 lab7 Multithreading
# Uthread: switching between threads#
-
thread_yield
类似于xv6
中的yield
,它的作用是把当前的进程设置为RUNNABLE
,并调用thread_schedule
切换至下一个可执行的线程。main
函数对a,b,c
三个线程都调用了thread_create
,该函数应设置线程的ra
(返回地址)和sp
(栈顶指针),再调用thread_yield
切换线程。由于thread_create
函数只在创建线程时调用,故ra
应该设置为线程的开始位置,也就是func
。sp
设置为线程的栈顶t->stack+STACK_SIZE
(这里特别注意栈顶不是t->stack
!) -
在thread_scheduler中加入
thread_switch
,并且补充thread_switch
切换线程时,要保存和恢复寄存器。
thread_switch
函数可以直接把xv6
的swtch
搬过来复制
.text /* * save the old thread's registers, * restore the new thread's registers. */ .globl thread_switch thread_switch: 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
#Using threads#
-
在
put
操作中,用insert
添加键时,采用的是头插法。若不使用锁,当多个线程同时对某个哈希桶进行insert
时候,会导致一个键被覆盖。 -
为所有哈希桶添加锁
在
main
函数中初始化所有锁在
put
和get
中加入获取锁和释放锁的操作
#Barrier#
-
每次进入
barrier
时,线程首先获取锁,对nthread
+1,也就是已到达屏障的线程数增加了一个。如果已到达屏障的线程数与总线程数相等,说明所有线程都到达了,对轮数round
+1,并且唤醒所有休眠线程,若不相等, 则调用wait
让线程释放锁并且休眠。复制
static void barrier() { pthread_mutex_lock(&bstate.barrier_mutex); bstate.nthread++; if (bstate.nthread == nthread){ bstate.round++; bstate.nthread = 0; pthread_cond_broadcast(&bstate.barrier_cond); } else{ pthread_cond_wait(&bstate.barrier_cond, &bstate.barrier_mutex); } pthread_mutex_unlock(&bstate.barrier_mutex); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现