pintos project (2) Project 1 Thread -Mission 1 Code

  上一篇博客 分析了一下Mission 1中的代码,现在我们来开始正式实现。

 

首先,给线程结构体 struct thread{}加上ticks_blocked成员,在threads/thread.h中

  

 /* Record the time the thread has been blocked. */
    int64_t ticks_blocked;

在线程创建的时候,ticks_blocked应该被初始化为0,在threads/thread.c中,找到thread_create()函数,添加如下代码:

/*Set default ticks_blocked = 0*/
  t->ticks_blocked = 0;

修改timer_sleep()函数:

/* Sleeps for approximately TICKS timer ticks.  Interrupts must
   be turned on. */
void
timer_sleep (int64_t ticks)
{
  if (ticks <= 0)
  {
    return;
  }
  ASSERT (intr_get_level () == INTR_ON);
  enum intr_level old_level = intr_disable ();
  struct thread *current_thread = thread_current ();
  current_thread->ticks_blocked = ticks;
  thread_block ();
  intr_set_level (old_level);
}

在这里我们调用了一个thread_block()函数,在threads/thread.c中修改:

/* Puts the current thread to sleep.  It will not be scheduled
   again until awoken by thread_unblock().

   This function must be called with interrupts turned off.  It
   is usually a better idea to use one of the synchronization
   primitives in synch.h. */
void
thread_block (void)
{
  ASSERT (!intr_context ());
  ASSERT (intr_get_level () == INTR_OFF);

  thread_current ()->status = THREAD_BLOCKED;
  schedule ();
}

然后,修改时钟中断处理函数,找到devices/timer.中的timer_interrupt()函数,添加代码

  thread_foreach (blocked_thread_check, NULL);

这里的thread_foreach()函数,即对每个函数都执行blocked_thread_check(),在threads/thread.c中修改。

/* Invoke function 'func' on all threads, passing along 'aux'.
   This function must be called with interrupts off. */
void
thread_foreach (thread_action_func *func, void *aux)
{
  struct list_elem *e;

  ASSERT (intr_get_level () == INTR_OFF);

  for (e = list_begin (&all_list); e != list_end (&all_list);
       e = list_next (e))
    {
      struct thread *t = list_entry (e, struct thread, allelem);
      func (t, aux);
    }
}

最后,给thread添加一个blocked_thread_check()方法:

先声明

void blocked_thread_check (struct thread *, void * UNUSED);

然后在thread.c中添加:

/* Check the blocked thread */
void
blocked_thread_check (struct thread *t, void *aux UNUSED)
{
  if (t->status == THREAD_BLOCKED && t->ticks_blocked > 0)
  {
      t->ticks_blocked--;
      if (t->ticks_blocked == 0)
      {
          thread_unblock(t);
      }
  }
}

这里又修改了一个thread_unblock()函数,作用是将线程丢到ready队列中:

/* Transitions a blocked thread T to the ready-to-run state.
   This is an error if T is not blocked.  (Use thread_yield() to
   make the running thread ready.)

   This function does not preempt the running thread.  This can
   be important: if the caller had disabled interrupts itself,
   it may expect that it can atomically unblock a thread and
   update other data. */
void
thread_unblock (struct thread *t)
{
  enum intr_level old_level;

  ASSERT (is_thread (t));

  old_level = intr_disable ();
  ASSERT (t->status == THREAD_BLOCKED);
  list_push_back (&ready_list, &t->elem);
  t->status = THREAD_READY;
  intr_set_level (old_level);
}

这样一来,timer_sleep()的唤醒机制我们就实现了,将更改过的代码push上去。

中间发现自己犯了几个小错误,fix bug之后才跑通。

具体的代码可以在我的Github中找到。

posted @ 2015-05-28 21:36  crayygy  阅读(1520)  评论(0编辑  收藏  举报