6.S081 lab7 Multithreading
# Uthread: switching between threads
-
为每个线程添加一个
context结构以用于保存/还原寄存器,这部分可以直接把xv6的context搬过来

-
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); }

浙公网安备 33010602011771号