PINTOS——Project 1: Threads

目录

1. Task 1:Alarm Clock

1.1 实验要求

1.2 基础知识

1.3 设计思路

1.4 实验过程

1.5实验结果:

1.6 收获与总结

2. Task 2:优先级调度

2.1 实验要求

2.2 实验过程

2.3 实验结果

3. Task 3:多级反馈调度

3.1 实验要求

3.2 基础知识

3.3 实验过程

3.4 实验结果

3.5 收获与总结


 

1. Task 1:Alarm Clock

1.1 实验要求

重新实现timer_sleep()。

将“忙等待“变为可避免繁忙的等待

暂停执行调用线程,直到时间提前至少x个计时单位。除非系统处于空闲状态,否则线程在x个计时单位之后才唤醒。在等待一定时间后,将它放在就绪队列中。

1.2 基础知识

timer_sleep()函数解析:

void timer_sleep (int64_t ticks)           //在ticks时间内,如果线程处于running状态就不断把他扔到就绪队列不让他执行

{

 int64_t start = timer_ticks ();         //返回自OS启动以来的计时器tick数。禁止当前行为被中断,保存禁止被中断前的中断状态(用old_level储存)。

 ASSERT (intr_get_level () == INTR_ON);           //如果它的条件返回错误,则终止程序执行。

                                                                                           //intr_get_level ()这个函数一样是调用了汇编指令,把标志寄存器的东西放到处理器棧上,然后把值pop到flags(代表标志寄存器IF位)上,通过判断flags来返回当前终端状态(intr_level)。

 while (timer_elapsed (start) < ticks)   //返回了当前时间距离start的时间间隔。

   thread_yield();              //把当前线程扔到就绪队列里,然后重新schedule,注意这里如果ready队列为空的话当前线程会继续在cpu执行。

}

1.3 设计思路

调用timer_sleep的时候直接把线程阻塞掉,然后给线程结构体加一个成员ticks_blocked来记录这个线程被sleep了多少时间,然后利用操作系统自身的时钟中断(每个tick会执行一次)加入对线程状态的检测,每次检测将ticks_blocked减1, 如果减到0就唤醒这个线程。

1.4 实验过程

  1. 为线程增加一个新的状态,表示线程正处在sleep中。
  2. 在内核中增加一个列表sleep_list,用于存放处于THREAD_SLEEP状态的线程。
  3. 在struct thread结构体中添加两个成员变量,用于保存与THREAD_SLEEP状态相关的信息。
  4. 为了实现非忙等待的timer_sleep(),需要实现几个函数,具体功能下文会解释。
  5. 实现thread_sleep()函数,该函数会将当前线程放入sleep_list队列中,并更新线程信息,最后调用schedule()进行新线程调度。该函数会在timer_sleep()中被调用。
  6. 实现thread_foreach_sleep()函数,该函数会遍历sleep_list队列,并将其中的每个线程的sleep_ticks减1;若某个线程的sleep_ticks为0,即该线程不需要再继续等待,便将该线程从sleep_list队列移至就绪队列中。该函数会在timer_interrupt()中被调用。
  7. 实现thread_less_priority()函数,该函数会比较传入线程a和b的优先级,若a的优先级小于b的,则返回真,否则返回假。该函数会在next_thread_to_run中被调用,用来从就绪队列中选择优先级最高的线程。
  8. 修改timer_sleep()函数:一是要对输入参数进行合法性检查,输入参数ticks必须大于0才有意义;二是要将其改为非忙等待,看了上面的内容,其实思路已经很清楚了,只要调用thread_sleep()将当前线程扔到sleep_list队列中就行了。
  9. 修改timer_interrupt()函数:当每个ticks中断到来时,需要对sleep_list中的线程进行更新,否则sleep中的线程将永远不会被唤醒。
  10. 需要对新加入的sleep_list在系统启动后进行初始化。
  11. 收尾工作,因为project要求在调度下一个进程时,选择优先级最高的来执行,所以需要修改next_thread_to_run()函数。该函数原先选择就绪队列中的第一个线程来执行,现在我们利用库函数中提供的list_max()来选择其中优先级最高的线程。

1.5实验结果:

1.6 收获与总结

通过配置pintos学习到了一些bochs的配置方法。通过完成实验一,更深层次地理解了阻塞线线程的过程。

 

2. Task 2:优先级调度

2.1 实验要求

Pintos中实现优先级调度。当一个线程被添加到具有比当前运行的线程更高优先级的就绪列表时,当前线程应该立即将处理器放到新线程中。类似地,当线程正在等待锁,信号量或条件变量时,应首先唤醒优先级最高的等待线程。线程可以随时提高或降低自己的优先级,但降低其优先级以使其不再具有最高优先级必须使其立即产生CPU

实施优先捐赠。您需要考虑需要优先捐赠的所有不同情况。务必处理多个捐赠,其中多个优先级捐赠给单个线程。您还必须处理嵌套捐赠:如果H等待M持有的锁定且M正在等待持有的锁定,则ML应该被提升为H的优先级。如有必要,您可以对嵌套优先级捐赠的深度施加合理限制,例如8级。

您必须为锁实现优先捐赠。您无需为其他Pintos同步构造实现优先级捐赠。您确实需要在所有情况下实施优先级安排。

最后,实现以下允许线程检查和修改自己的优先级的函数。这些函数的骨架在threads / thread.c中提供。2

2.2 实验过程

这个测试集主要是要求实现锁的优先级捐赠,及将cond改为按优先级选择下一线程,并且保证执行中的线程始终是优先级最高的。 

因为原先的实现中是将lock视为值为1的信号量来处理的,为了实现优先级捐赠,需要用到其中的等待队列,但这样包裹一层结构体觉得很麻烦,所以对lock做了较大改动。

1.为了实现优先级捐赠,我们先考虑struct thread需要增加哪些变量:

1)  我们需要记录当前线程的基础优先级,这样当捐赠结束时才能恢复原先的优先级;

  • 3
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值