上一篇博客 分析了一下Mission 1中的代码,如今咱们来开始正式实现。app
首先,给线程结构体 struct thread{}加上ticks_blocked成员,在threads/thread.h中ide
/* 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()函数:atom
/* 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中修改:idea
/* 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()函数,添加代码spa
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()方法:code
先声明blog
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中找到。