这个实验我只是做了 Uthread
。后面关于 pthread
部分并没有做,一来是懒,二来现在 Pthread 用的不多了,主要还是用 OpenMP
来进行多线程编程。
thread
数据结构:
struct thread { | |
char stack[STACK_SIZE]; /* the thread's stack */ | |
int state; /* FREE, RUNNING, RUNNABLE */ | |
char context[4096]; //for context save. 这里的 context 实际上是 char * 类型,也就是 4096 字节的地址空间。 | |
}; |
create_thread
:
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 | |
*(uint64*)(t->context) = (uint64)func; // 这个就是使用 func | |
*(uint64*)(t->context + 8) = (uint64)(t->stack+STACK_SIZE); | |
} |
进程调度
:
void | |
thread_schedule(void) | |
{ | |
struct thread *t, *next_thread; | |
/* Find another runnable thread. */ | |
next_thread = 0; | |
t = current_thread + 1; | |
for(int i = 0; i < MAX_THREAD; i++){ | |
if(t >= all_thread + MAX_THREAD) | |
t = all_thread; | |
if(t->state == RUNNABLE) { | |
next_thread = t; | |
break; | |
} | |
t = t + 1; | |
} | |
if (next_thread == 0) { | |
printf("thread_schedule: no runnable threads\n"); | |
exit(-1); | |
} | |
if (current_thread != next_thread) { /* switch threads? */ | |
next_thread->state = RUNNING; | |
t = current_thread; | |
current_thread = next_thread; | |
thread_switch((uint64)t->context, (uint64)current_thread->context); | |
/* YOUR CODE HERE | |
* Invoke thread_switch to switch from t to next_thread: | |
* thread_switch(??, ??); | |
*/ | |
} else | |
next_thread = 0; | |
} |
切换函数
:
.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 */
主要有意思的点就是,create 的时候,自己制定了 ra 和 sp 两个寄存器的数据。这种直接用指针进行操作内存的方式,不得不感叹真的自由度高。