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,原来更改堆栈这么简单,所谓程序的状态,其实主要也就是那几个寄存器的值而已。

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
class MainWindow(QMainWindow): def init(self, user_id): super().init() self.user_id = user_id self.initUI() # 打开串口 self.ser = serial.Serial('COM7', 9600, timeout=1) def initUI(self): # 创建用于显示员工信息的控件 self.info_label = QLabel("员工信息", self) self.info_label.move(100, 50) self.info_label.setStyleSheet("font-size: 24px; color: black; background-color: #eee; border-radius: 10px;") self.id_label = QLabel("员工ID:", self) self.id_label.move(70, 100) self.id_label.setStyleSheet("font-size: 18px; color: black;") self.name_label = QLabel("姓名:", self) self.name_label.move(70, 150) self.name_label.setStyleSheet("font-size: 18px; color: black;") self.six_label = QLabel("性别:", self) self.six_label.move(70, 200) self.six_label.setStyleSheet("font-size: 18px; color: black;") self.sfz_label = QLabel("身份证:", self) self.sfz_label.move(70, 250) self.sfz_label.setStyleSheet("font-size: 18px; color: black;") self.tel_label = QLabel("电话:", self) self.tel_label.move(70, 300) self.tel_label.setStyleSheet("font-size: 18px; color: black;") self.setFixedSize(800, 500) self.setWindowTitle('员工信息') # 查询员工信息 def query_employee(self, id): conn = pymysql.connect(host='39.99.214.172', user='root', password='Solotion.123', database='jj_tset') cursor = conn.cursor() cursor.execute("SELECT * FROM employee_table WHERE user_id='%s'" % id) result = cursor.fetchone() conn.close() return result # 读取数据 def read_data(self): data = self.ser.readline() if data: # 解析数据 id = data.decode().strip() # 查询员工信息 result = self.query_employee(id) if result: # 更新UI界面 self.id_label.setText("员工ID:" + result[0]) self.name_label.setText("姓名:" + str(result[1])) self.six_label.setText("性别:" + result[2]) self.sfz_label.setText("身份证:" + str(result[3])) self.tel_label.setText("电话:" + result[4]) print(result[0],result[1],result[2],result[3],result[4]) else: # 显示空白信息 self.id_label.setText("员工ID:") self.name_label.setText("姓名:") self.six_label.setText("性别:") self.sfz_label.setText("身份证:") self.tel_label.setText("电话:") # 定时读取数据 QTimer.singleShot(100, self.read_data) def closeEvent(self, event): # 关闭串口 self.ser.close()用多线程改写代码,防止主线程阻塞
05-27

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值