问题描述:

实现linux中的thread.sleep()函数,其功能是让调用他的线程睡眠一段时间(ticks),然后唤醒。

pintos 本身的sleep函数

void timer_sleep(int 64_t ticks){
	Int 64_t start = timer_ticks();
	ASSERT(intr_get_level ==INTR_ON);
	while(timer_elapsed(start)<ticks)
		thread_yield();
		}

pintos 本身的sleep函数是忙等待的实现方式,其睡眠应为一种伪睡眠,睡眠的线程不断查询自己的睡眠时间,如果没有到给定的睡眠时长,则将自己放到队列的末端,这一操作持续进行,浪费cpu资源。
改进:我们不让线程去不断查询自己的睡眠时长,而是通过中断机制,在每一次时间终端到来时,判读该线程是否已经休眠够了睡眠时长,若是则唤醒它,否则让他的继续睡眠,在睡眠时间上减一。

为此 我们需要在thread,h的thread结构体中增加block_ticks 这一变量,通过它来初始化睡眠总时长。
同时在thread.c中增加thread_block_ticks_check函数,同时在thread.c的thread_ticks()函数中通过thread_foreach()函数遍历所有线程来唤醒满足唤醒条件的线程。

同时重写 sleep函数 对线程的睡眠时间进行设定,并将该线程阻塞,进入睡眠。

1、添加block_ticks变量

struct thread
  {
    /* Owned by thread.c. */
    tid_t tid;                          /* Thread identifier. */
    enum thread_status status;          /* Thread state. */
    char name[16];                      /* Name (for debugging purposes). */
    uint8_t *stack;                     /* Saved stack pointer. */
    int priority;                       /* Priority. */
    long long block_ticks;              /*Blocl_ticks */
    struct list_elem allelem;           /* List element for all threads list. *
    /* Shared between thread.c and synch.c. */
    struct list_elem elem;              /* List element. */
}

2、在thread.c中加入thread_block_ticks_check函数

void thread_block_ticks_check(struct thread *t){
  if(t->status ==THREAD_BLOCKED){
	if(t->block_ticks ==1){
		thread_unblock(t);
	   }
	if(t->block_ticks !=0){

		t->block_ticks--;
	     }
    }
}

3、 修改thread.c中的thread_ticks()函数

void
thread_tick (void)
{
  struct thread *t = thread_current ();

  /* Update statistics. */
  if (t == idle_thread)
    idle_ticks++;
#ifdef USERPROG
  else if (t->pagedir != NULL)
    user_ticks++;
#endif
  else
    kernel_ticks++;

  /* Enforce preemption. */
  if (++thread_ticks >= TIME_SLICE)
    intr_yield_on_return ();
  enum intr_level old_level = intr_disable();
  thread_foreach(thread_block_ticks_check,NULL);
  intr_set_level(old_level);
}

4、重写sleep函数

timer_sleep (int64_t ticks) 
{
  //int64_t start = timer_ticks ();

  //ASSERT (intr_get_level () == INTR_ON);
  //while (timer_elapsed (start) < ticks) 
    //thread_yield ();

   if(ticks<=0) return ;
   enum intr_level old_level = intr_disable(); //close interupt
   thread_current()->block_ticks = ticks;
   thread_block();
   intr_set_level(old_level);
}

在 /home/xd/os/pintos/src/thread 中
make check

得到结果

有关alarmcloc的测试均通过

Logo

更多推荐