MIT6.S081Lab7:Multithreading

Uthread: switching between threads

两个要求,一是当第一次运行某个线程时要运行对应的函数(在create函数中传入的那个函数),并且要运行在对应的堆栈中;二是切换上下文。第二个很简单,就是往thread结构体中加一个和context一样的元素,然后和kernel/swtch.S一样的汇编切换即可。关键在于第一个,如何在第一次运行时执行对应的函数呢,很简单,将ra的值改为函数地址即可,而运行在对应的堆栈中也同样的道理,将sp的值改为stack数组的末尾地址即可(栈是由高到低增长)。

uthread.c

struct usercontext {
  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 */
  void       (*func)();
  struct usercontext usercontext;

};
struct thread all_thread[MAX_THREAD];
struct thread *current_thread;
extern void thread_switch(struct usercontext *, struct usercontext *);


if (current_thread != next_thread) {         /* switch threads?  */
    next_thread->state = RUNNING;
    t = current_thread;
    current_thread = next_thread;
    /* YOUR CODE HERE
     * Invoke thread_switch to switch from t to next_thread:
     * thread_switch(??, ??);
     */
    thread_switch(&t->usercontext, &next_thread->usercontext);
  } else
    next_thread = 0;
}



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
  t->usercontext.ra = (uint64)func;
  t->usercontext.sp = (uint64)(t->stack + STACK_SIZE);
}

Using threads

这个我感觉很简单,只要明白哪里产生临界情况就很容易写出来。其实产生临界情况的就一种情况,就是put时,当前没有这个key,所以要insert,而另一个线程也在插入,覆盖了另一个插入。其实key对应的value不重要,在get_thread不关心value的情况,只要key存在即可。

所以创建一个lock,然后在insert前后保护即可。

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;


// the new is new.
pthread_mutex_lock(&lock);
insert(key, value, &table[i], table[i]);
pthread_mutex_unlock(&lock);
}

Barrier

emm,感觉这个也很简单。按照题意,就是到barrier的时候检查是否全部线程到达,如果全部到达就唤醒之前等待的线程,如果没有全部到达就wait,用bstate.nthread==nthread来判断是否全部到达,每次到一个线程bstate.nthread加1,当全部线程到达了将bstate.ntrhead置零并将bstate.round加1。注意上面的修改全在临界区中。

static void 
barrier()
{
  // YOUR CODE HERE
  //
  // Block until all threads have called barrier() and
  // then increment bstate.round.
  //
  pthread_mutex_lock(&bstate.barrier_mutex);
  if (++bstate.nthread == nthread) {
    bstate.nthread = 0;
    ++bstate.round;
    pthread_cond_broadcast(&bstate.barrier_cond);
  } else {
    pthread_cond_wait(&bstate.barrier_cond, &bstate.barrier_mutex);
  }
  pthread_mutex_unlock(&bstate.barrier_mutex);
  
}

总结

总的来说这几个实验都不难,只要把已有的代码看懂加上提示做出来还是没问题的,第一个实验对我的提升最大,进一步理解了ra和sp,尤其是sp,原来更改堆栈这么简单,所谓程序的状态,其实主要也就是那几个寄存器的值而已。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值