开发者学堂课程【高校精品课-西安电子科技大学-操作系统课程设计:priority task2 实验过程】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/74/detail/15856
priority task2 实验过程
实操演示
本节课讲解优先级反转部分的相关实验代码。
在线程部分的源码中,加入如下结构体:
Struct pri_stack
{
Int priority;
//用于保存被捐赠前的优先级
Struct lock *lock;//标明捐赠者捐赠时需要什么锁
其中 priority 用于保存被捐赠前的优先级,lock 标明捐赠者捐赠时需要什么锁。
接下来在同文件中加入如下声明,这四行代码为:
Struct pri_stack pri【64】
Int top;
//pri 的栈顶
Struct semaphore *block sema;/
/被哪个信号量阻塞
Struct lock *block lock;
//在等待哪个 lock
分别表示:线程优先级的站以及线程优先级的站点,以及表明在哪个信号量阻塞和在等待哪个锁。
接下来在线程的优先级设置函数中修改如下代码:
If(thread_current()->top>0)
{
Thread_current()-> priority = new priority
}
Else
{
Thread_current()->priority = new priority
这段代码表示,如果当前线程的优先级的站点元素优先级大于0,则将新的线程优先级复制给当前线程的站点优先级,否则将新的优先级复制给当前线程的优先级。
由于在结构体中定义了本次实验锁需要的一些声明,所以在初始化线程中,需要为当前的线程增加以下属性,分别是站点元素阻塞、信号量和阻塞锁。
t->top = 0
T->block_sema = NULL
T->block_lock = NULL
在线程的同步机制模块中,需要修改信号量下降函数(sema_dowm)。当在信号量下降函数中,需要记入当前线程的阻塞信号量。接下来修改信号量上升函数(sema_up)。在该函数中需要修改选中区域的部分代码:
If ( !list_ empty (&sema ->waiters))
t=list_entry (list_ pop_ front (&sema-»waiters), struct thread, elem);
thread unblock (t);
t->block sema = NULL;
在这部分代码中需要判断,如果一个线程唤醒时,需要将它的阻塞信号量设为空。
接下来在换取锁的函数中,需要增加以下代码:
if(lock->semaphore.value = 0)
thread current()->block_ lock = lock;
priority donate(thread current()),lock);
在这部分代码中,如果当前锁的信号量值为0,需要将当前线程的阻塞锁记录为锁获得的锁资源,然后将当前线程的锁资源进行优先级捐赠。
接下来修改锁资源的释放代码在 lock release 代码中,需要进行如下判断,首先需要判断当前线程的占点优先级是否大于0,如果大于零则代表当前线程被捐赠过,则需要判断是否进行优先级还原。如果当前线程的锁资源在占点,则还原当前线程的优先级并删除记录;如果当前线程的锁资源在占中,则直接删除记录;如果当前线程的锁资源在占底部,则为当前优先级复制为初始优先级,然后删除记录。
最后需要在线程部分的原法中增加自己写的 priority donate 优先级选择函数,该函数的大致内容如下;
在该函数中需要判断,如果当前线程的优先级大于占领锁资源的优先级,则需要进行选择。在选择逻辑中需要判断,如果占用锁资源的线程为就绪状态,则就绪队列需要进行重新排序。如果占用锁资源的线程为阻塞状态,并且占用锁资源的线程也在等待信号量,则需要重新排序等待队列。
在修改完所有的代码逻辑之后,在 pintos 操作系统源码的 src/threads 目录下运行 make check 命令。
运行完之后可以看到与 priority donate 相关的状态为 pass 状态,这代表实验成功。