Pintos 实验1 Mission2记录(上)
首先,我们要将FCFS改成优先级调度,经过阅读源码,我们发现,系统在schedule()函数里调用list_pop_front()函数让ready_list里的第一个线程运行,那么我们就只需要维护ready_list是按照优先级从大到小排列的即可。
首先,thread_yield()函数会让一个线程暂时放弃CPU而被放到等待队列中,原本是放到等待队列末尾(FCFS),我们把thread_yield()、thread_create()都改成按优先级插入,并且让当前线程放弃CPU,并从等待队列中选出优先级最高的,岂不是完成了优先级调度?
说干就干,我们先让thread_yield()将当前线程插入到队列中合适的位置。
(网上查资料得知),list.c里面有一个list_insert_ordered()函数,照着它的使用方法,我们将thread_yield()里的
list_push_back(&ready_list, &cur->elem);
改成
list_insert_ordered(&ready_list, &cur->elem, compare_priority, NULL);
如图:
这里插一句,compare_priority是用线程的elem元素为输入,对比对应的线程优先级的函数,里面用到了list_entry(),也是照猫画虎。
然后是thread_create()直接改其调用的thread_unblock(),更妙,顺便把解锁线程的问题解决了:
这样alarm_priority测试点就pass了。
接下来我们看priority-change测试点。
先贴代码:
大概过程如下:主线程先创建子线程,其线程优先级更高(PRI_DEFAULT -+1),根据优先级调度,此时主线程应该放弃CPU,由子线程先执行。而在子线程中,它降低了自己的优先级,到PRI_DEFAULT - 1,而此时比主线程优先级更低,应该放弃CPU,让主线程执行。
所以为了让修改优先级、创建优先级时都判断是否会对调度产生影响,thread_set_priority和thread_create函数里都需要加yield:
thread_set_priority
thread_create
接下来是priority-sema。
同样,先贴代码:
可以看到,测试点创建了一个信号量sema,现将当前线程优先级设置为PRI_MIN(也就是0),让后创建10个线程,优先级分别比PRI_DEFAULT(31)低4、5、6、7、8、9、10、1、2、3,而这些被创建的线程都对信号量进行P操作,结果都被阻塞,而主线程在创建完十个子线程之后,循环对该信号量进行10次V操作,每次都会解锁1个创建进程。按照优先级调度,子线程应该按照优先级从大到小解锁。
所以我们在主线程执行V操作时,要让主线程放弃CPU,这样才能释放子线程来运行,所以我们只需要在sema_up()函数里增加一个thread_yield(),再把sema_down()里的list_push_back换成list_insert_ordered即可。
最后还有一个priority_condvar测试点,我们看到cond_signal()里面把cond->waiters的第一个元素弹出,所以我们如果能把cond->waiter里的元素按照对应的线程的优先级排序就好了,所以我们在semaphore_elem结构体里加一个priority的量,表示对应线程的优先级,然后和前面一样,用list_insert_ordered()插入,同样需要自己写一个比较函数compare_cond():
这样优先级调度部分就完全实现了。
-------------------------------------------------------------------------------------------------------------------分割线-------------------------------------------------------------------------------------------------------------------
接下来是实现优先级捐赠。
未完待续....