Skip to content

Uthread: switching between threads (moderate)

在给定的代码基础上实现用户级线程切换

修改结构体

定义存储上下文的结构体tcontext

修改thread结构体,添加context字段

diff --git a/user/uthread.c b/user/uthread.c
index 8e46826..ed044a6 100644
--- a/user/uthread.c
+++ b/user/uthread.c
@@ -10,11 +10,30 @@
 #define STACK_SIZE  8192
 #define MAX_THREAD  4
 
// 用户线程的上下文结构体
struct tcontext {
  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;
};
 
 struct thread {
   char       stack[STACK_SIZE]; /* the thread's stack */
   int        state;             /* FREE, RUNNING, RUNNABLE */

  struct tcontext context;            /* 用户进程上下文 */
 };
 struct thread all_thread[MAX_THREAD];
 struct thread *current_thread;

添加 thread_switch 的代码

此处 struct ctx 与内核的 struct context 结构体的成员是相同的

因此该函数可以直接复用 kernel/swtch.S 中的 swtch 代码

diff --git a/user/uthread_switch.S b/user/uthread_switch.S
index 5defb12..a6ac075 100644
--- a/user/uthread_switch.S
+++ b/user/uthread_switch.S
@@ -8,4 +8,33 @@
        .globl thread_switch
 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_schedule() 函数

thread_schedule() 函数负责进行用户多线程间的调度

diff --git a/user/uthread.c b/user/uthread.c
index 8e46826..ed044a6 100644
--- a/user/uthread.c
+++ b/user/uthread.c
@@ -63,6 +82,7 @@ thread_schedule(void)
      * Invoke thread_switch to switch from t to next_thread:
      * thread_switch(??, ??);
      */
    thread_switch((uint64)&t->context, (uint64)&current_thread->context);
   } else
     next_thread = 0;
 }

添加代码到 thread_create() 函数

thread_create() 函数主要进行线程的初始化操作:

其先在线程数组中找到一个状态为 FREE 即未初始化的线程, 然后设置其状态为 RUNNABLE 等进行初始化

diff --git a/user/uthread.c b/user/uthread.c
index 8e46826..ed044a6 100644
--- a/user/uthread.c
+++ b/user/uthread.c
@@ -77,6 +97,8 @@ thread_create(void (*func)())
   }
   t->state = RUNNABLE;
   // YOUR CODE HERE
  t->context.ra = (uint64)func;                   // 设定函数返回地址
  t->context.sp = (uint64)t->stack + STACK_SIZE;  // 设定栈指针
 }
 
 void

测试

bash
init: starting sh
$ uthread
thread_a started
thread_b started
thread_c started
thread_c 0
...
thread_b 99
thread_c: exit after 100
thread_a: exit after 100
thread_b: exit after 100
thread_schedule: no runnable threads