Pintos is a simple operating system framework for the x86 architecture. It supports kernel threads, loading and running user programmes, and a file system, but it implements all of these in a very simple way.
In first project assignment, the goal is to reimplement functions related to threads and timer.
The function I have to extend is the timer_sleep() defined in devices/timer.c.
The original version is working.
1void
2timer_sleep (int64_t ticks)
3{
4 int64_t start = timer_ticks ();
5
6 ASSERT (intr_get_level () == INTR_ON);
7 while (timer_elapsed (start) < ticks)
8 thread_yield ();
9}
1void thread_yield(void) {
2 struct thread *cur = thread_current ();
3 enum intr_level old_level;
4
5 ASSERT (!intr_context ());
6
7 old_level = intr_disable ();
8 if (cur != idle_thread)
9 list_push_back (&ready_list, &cur->elem);
10 cur->status = THREAD_READY;
11 schedule ();
12 intr_set_level (old_level);
13}
But it keep checking the current time and calling thread_yield() because it implemented using while loop. This called “Busy waiting”.
And also, thread_yield() place the current thread at the back of the ready queue, not the waiting queue.
To solve this problem, block the current thread with thread_block() funtion.
1void thread_block (void) {
2 ASSERT (!intr_context ());
3 ASSERT (intr_get_level () == INTR_OFF);
4
5 thread_current ()->status = THREAD_BLOCKED;
6 schedule ();
7}
This function makes the current thread to sleep. It means, the thread will not be scheduled again until awoken by thread_unblock().
We need to make a waiting queue since Pintos doesn’t have a waiting queue. And then put the current thread thread to the waiting queue. Next block that thread. It won’t be make ‘busy waiting’ after this three step process.
Comments