警告
本文最后更新于 2023-04-18,文中内容可能已过时。
MIT 6.1810 中第六个 lab 的 solution
Your job is to come up with a plan to create threads and save/restore registers to switch between threads, and implement that plan. When you’re done, make grade
should say that your solution passes the uthread test.
这个就是抄就行了。
struct thread
结构体加一个新元素:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| 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;
};
struct thread {
char stack[STACK_SIZE]; /* the thread's stack */
int state; /* FREE, RUNNING, RUNNABLE */
struct context context;
};
|
thread_schedule()
函数让加的那个部分只需要加个对注释里说的那个函数的引用:
1
| thread_switch((uint64)&t->context, (uint64)&next_thread->context);
|
thread_create()
函数在初始化线程的时候需要初始化新加的context
这个变量
1
2
3
| t->state = RUNNABLE;
t->context.ra = (uint64)func;
t->context.sp = (uint64)t->stack + STACK_SIZE;
|
至于uthread_switch.S也只需要抄之前在调度那里见过的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| 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
|
In this assignment you will explore parallel programming with threads and locks using a hash table. You should do this assignment on a real Linux or MacOS computer (not xv6, not qemu) that has multiple cores. Most recent laptops have multicore processors.
全局定义一个lock
在main()
首先初始化这个lock
1
| pthread_mutex_init(&lock, NULL);
|
然后在put的时候加锁就行了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| static
void put(int key, int value)
{
int i = key % NBUCKET;
// is the key already present?
struct entry *e = 0;
for (e = table[i]; e != 0; e = e->next) {
if (e->key == key)
break;
}
pthread_mutex_lock(&lock);
if(e){
// update the existing key.
e->value = value;
} else {
// the new is new.
insert(key, value, &table[i], table[i]);
}
pthread_mutex_unlock(&lock);
}
|
In this assignment you’ll implement a barrier: a point in an application at which all participating threads must wait until all other participating threads reach that point too. You’ll use pthread condition variables, which are a sequence coordination technique similar to xv6’s sleep and wakeup.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| static void
barrier()
{
int tmp = bstate.round;
pthread_mutex_lock(&bstate.barrier_mutex);
if(++bstate.nthread != nthread)
pthread_cond_wait(&bstate.barrier_cond, &bstate.barrier_mutex);
else
pthread_cond_broadcast(&bstate.barrier_cond);
if(bstate.round == tmp){
bstate.round++;
bstate.nthread = 0;
}
pthread_mutex_unlock(&bstate.barrier_mutex);
}
|