上一篇博客 分析了一下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中找到。