Pintos Project 1

序:

  这是我第二次写Pintos内核,第一次上这课的时候由于刚接触操作系统,这个project难度又是非常大,所以其实写出的代码有很多bug,一些测试也没有通过,希望通过这次重写Pintos,加深对操作系统内核的理解,并力争通过所有测试。

Part1:

  第一部分的目的是让我们修改timer_sleep(int64_t ticks)函数的忙等机制。thread结构体如下

 1 struct thread
 2   {
 3     /* Owned by thread.c. */
 4     tid_t tid;                          /* Thread identifier. */
 5     enum thread_status status;          /* Thread state. */
 6     char name[16];                      /* Name (for debugging purposes). */
 7     uint8_t *stack;                     /* Saved stack pointer. */
 8     int priority;                       /* Priority. */
 9     struct list_elem allelem;           /* List element for all threads list. */
10 
11     /* Shared between thread.c and synch.c. */
12     struct list_elem elem;              /* List element. */
13 
14 #ifdef USERPROG
15     /* Owned by userprog/process.c. */
16     uint32_t *pagedir;                  /* Page directory. */
17 #endif
18 
19     /* Owned by thread.c. */
20     unsigned magic;                     /* Detects stack overflow. */
21 
22     int64_t ticks_blocked;              /* Time for blocked. */
23   };

  这里我们添加了一个变量ticks_blocked用于记录剩余阻塞时间。在timer_sleep函数中,将该线程阻塞并设置阻塞时间。注意这一过程需要解除中断。

 1 /* Sleeps for approximately TICKS timer ticks.  Interrupts must
 2    be turned on. */
 3 void
 4 timer_sleep (int64_t ticks) 
 5 {
 6   if(ticks <= 0) return;
 7   ASSERT (intr_get_level () == INTR_ON);
 8   enum intr_level old_level = intr_disable ();
 9   struct thread *current_thread = thread_current ();
10   current_thread->ticks_blocked = ticks;
11   thread_block ();
12   intr_set_level (old_level);
13 }

  thread_block()的底层实现是将当前线程的状态设置为THREAD_BLOCKED,然后重新调度。状态为THREAD_BLOCKED的线程将从就绪队列中移除。

 1 /* Puts the current thread to sleep.  It will not be scheduled
 2    again until awoken by thread_unblock().
 3 
 4    This function must be called with interrupts turned off.  It
 5    is usually a better idea to use one of the synchronization
 6    primitives in synch.h. */
 7 void
 8 thread_block (void) 
 9 {
10   ASSERT (!intr_context ());
11   ASSERT (intr_get_level () == INTR_OFF);
12 
13   thread_current ()->status = THREAD_BLOCKED;
14   schedule ();
15 }

  接下来就是在适当的时间唤醒线程。我们在每个tick内遍历所有线程,并将ticks_blocked值减一,如果该值小于等于0,则将其从阻塞队列中移除重新参与调度。每次时间片轮转时都会调度timer_interrupt函数。

1 /* Timer interrupt handler. */
2 static void
3 timer_interrupt (struct intr_frame *args UNUSED)
4 {
5   ticks++;
6   thread_tick ();
7   thread_foreach(check_blocked_time,NULL);
8 }

  thread_foreach函数的作用是对每个线程调用func函数,thread_action_func是用户定义类型typedef void thread_action_func (struct thread *t, void *aux);它规定了函数的返回值为void且有struct thread和void*两个参数。

 1 /* Invoke function 'func' on all threads, passing along 'aux'.
 2    This function must be called with interrupts off. */
 3 void
 4 thread_foreach (thread_action_func *func, void *aux)
 5 {
 6   struct list_elem *e;
 7 
 8   ASSERT (intr_get_level () == INTR_OFF);
 9 
10   for (e = list_begin (&all_list); e != list_end (&all_list);
11        e = list_next (e))
12     {
13       struct thread *t = list_entry (e, struct thread, allelem);
14       func (t, aux);
15     }
16 }

  每次时间片用完时,我们都需要将每个线程的ticks_blocked减1,如果该线程ticks_blocked小于0,则将其唤醒,因此我们实现函数如下。

1 /* Check every threads whether they should be awaked. */
2 void check_blocked_time(struct thread *t, void *aux){
3   if (t->status == THREAD_BLOCKED && t->ticks_blocked > 0){
4     t->ticks_blocked--;
5     if (t->ticks_blocked == 0)
6       thread_unblock(t);
7   }
8 }

  别忘记在头文件里添加定义

1 void check_blocked_time(struct thread *t, void *aux);

  至此,part1通过大半部分

  下面来部署线程的优先级系统

------------------------------------------------------

未完待续

猜你喜欢

转载自www.cnblogs.com/haoweizh/p/10214223.html