当前位置:
文档之家› pintos Lab1 实验报告
pintos Lab1 实验报告
第 4 页 共 14 页
华东师范大学软件学院实验报告
和 release 之时)。 3. 在对一个线程进行优先级设置的时候,如果这个线程处于被捐赠状态,则对 ori_priority 进行设置, 然后如果设置的优先级大于当前优先级,则改变当前优先级,否则在 捐赠状态取消的时候恢复 ori_priority。 4. 在释放锁对一个锁优先级有改变的时候应考虑其余被捐赠优先级和当前优先级。 5. 将信号量的等待队列实现为优先级队列。 6. 将 condition 的 waiters 队列实现为优先级队列。 7. 释放锁的时候若优先级改变则可以发生抢占。 代码实现: 由于对 thread 类改动较大,直接贴出整个类(也包含了 Part3 中的部份):
第 2 页 共 14 页
华东师范大学软件学院实验报告
会将在 "thread.h" 中声明的 thread_ mlfqs 设置为 true,这在 main () 中发生。启用 bsd 计划 程序后, 线程将不再直接控制自己的优先级。应忽略对 thread_ create () 的优先级参数, 以及 对 thread_ set _priority () 的任何调用, 而 thread_ get _ priority() 应返回由计划程序设置的线 程的当前优先级。在以后的任何项目中都不使用高级计划程序。
与之相对应的 thread_unblock():
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 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_insert_ordered (&ready_list, &t->elem, (list_less_func *) &thread_priority_cmp, NULL); //check_queue_priority(); t->status = THREAD_READY; ready_thread++; intr_set_level (old_level); }
完成 Part1 所得结果如下:
Part2: Priority Scheduling 实现思路: 1. 在一个线程获取一个锁的时候,如果拥有这个锁的线程优先级比自己低就提高它的 优先级,并且如果这个锁还被别的锁锁着,将会递归地捐赠优先级,然后在这个线程释放掉 这个锁之后恢复未捐赠逻辑下的优先级。 2. 如果一个线程被多个线程捐赠,维持当前优先级为捐赠优先级中的最大值(acquire
int64_t blocked_ticks;
并添加 block 状态:
1. enum thread_status 2. { 3. THREAD_RUNNING, 4. THREAD_READY, 5. THREAD_BLOCKED, 6. THREAD_DYING 7. };
ቤተ መጻሕፍቲ ባይዱ
/* /* /* /*
Running thread. */ Not running but ready to run. */ Waiting for an event to trigger. */ About to be destroyed. */
在 tick 中 thread_foreach 要对每个线程都执行 check_blocked_ticks()以确定是否将他们激活。
1. void check_blocked_ticks(struct thread *t,void *aux){ 2. if (t->status==THREAD_BLOCKED && t->blocked_ticks>0) { 3. t->blocked_ticks--; 4. if (t->blocked_ticks==0) { 5. thread_unblock(t); 6. } 7. } 8. }
华东师范大学软件学院实验报告
华东师范大学软件学院实验报告
实验课程:操作系统实践 实验名称: Pintos-threads 实验编号: 指导教师: 一、实验目的 Pintos 是一个用于 80x86 体系结构的简单操作系统框架。它支持内核线程、加载和运行 用户程序以及文件系统, 但它以非常简单的方式实现了所有这些。在本次 pintos 项目中, 我 们将加强其在线程这一方面的支持。 在本任务中, 老师为我们提供了一个功能最小的线程系统。我们的工作是扩展此系统的 功能, 以便更好地了解同步问题。我们将主要在此分配的 "线程" 目录中工作, 其中一些工作 是在旁边的 "设备" 目录中进行的。编译应在 "线程" 目录中完成。 年级:大二 姓名: 学号: 组号: 实验日期:2018/11/22 实验时间:4 学时 实验成绩:
其中调用到的 thread_block():
1. void 2. thread_block (void) 3. {
第 3 页 共 14 页
华东师范大学软件学院实验报告
4. 5. 6. 7. 8. 9. 10. }
ASSERT (!intr_context ()); ASSERT (intr_get_level () == INTR_OFF); thread_current ()->status = THREAD_BLOCKED; ready_thread--; schedule ();
三、实验环境 操作系统:Ubuntu 18.04 软件要求:VScode、GCC、GNU、Perl、QEMU、X、Bochs
四、实验过程与分析 Part1: Alarm Clock 实现思路: 调用 timer_sleep 的时候直接把线程阻塞掉,然后给线程结构体加一个成员 blocked_ticks 来记录这个线程被 sleep 了多少时间, 然后利用操作系统自身的时钟中断(每 个 tick 会执行一次)加入对线程状态的检测, 每次检测将 blocked_ticks 减 1, 如果减到 0 就 唤醒这个线程。 首先在 thread.h 中线程类中加入:
改动后的 timer_sleep():
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. void timer_sleep (int64_t ticks) { if (ticks<=0) return; enum intr_level old_level; old_level=intr_disable(); thread_current ()->blocked_ticks=ticks; thread_block(); intr_set_level(old_level); }
二、实验内容与实验步骤 第一步: 阅读和理解初始线程系统的代码。pintos 已经实现了线程创建和线程完成, 这是一个在 线程之间切换的简单调度程序, 以及同步基元 (信号量、锁、条件变量和优化障碍)。我们可 以通读源代码的某些部分, 看看发生了什么。例如:创建线程时, 我们将创建要计划的新上 下文。需要提供了一个要在此上下文中运行的函数, 作为 thread_ create () 的参数。第一次计 划并运行线程时, 它从该函数的开头开始, 并在该上下文中执行。当函数返回时, 线程将终 止。因此, 每个线程的行为就像在 pintos 内部运行的一个小型程序, 函数传递给 thread_ create (), 其作用类似于 main ()。在任何给定的时间, 只有一个线程运行, 其余的线程 (如果 有的话) 变为非活动状态。计划程序决定下一步运行哪个线程。 第二步: 重新实现在 "devicese/timerem. c" 中定义的 timer_sleep ()。目前系统虽然提供了一个工 作实现, 但它 基于"忙等待", 也就是说, 它在循环中旋转, 检查当前时间并调用线程, 直到有 足够的时间过去。我们要重新实现它, 以避免繁忙的等待。 [function] void timer_sleep (int64_t ticks) 暂停执行调用线程, 直到时间提前至少计时器 刻度。除非系统处于空闲状态, 否则线程不需要在 x 刻度后唤醒。只要把它放在准备好的队 列后, 他们已经等待了适当的时间。timer _sleep() 对于实时操作的线程非常有用, 例如, 对于
1. struct thread 2. { 3. /* Owned by thread.c. */ 4. tid_t tid; /* Thread identifier. */ 5. enum thread_status status; /* Thread state. */ 6. char name[16]; /* Name (for debugging purposes). */ 7. uint8_t *stack; /* Saved stack pointer. */ 8. int priority; /* Priority. */ 9. int org_priority; 10. struct list locks; 11. struct lock *waiting_for_lock; 12. struct semaphore *waiting_for_sema; 13. int64_t blocked_ticks; 14. struct list_elem allelem; /* List element for all threads list. */ 15. 16. /* Shared between thread.c and synch.c. */ 17. struct list_elem elem; /* List element. */ 18. 19. #ifdef USERPROG 20. /* Owned by userprog/process.c. */ 21. uint32_t *pagedir; /* Page directory. */ 22. #endif 23. 24. int nice; 25. int recent_cpu; 26. /* Owned by thread.c. */ 27. unsigned magic; /* Detects stack overflow. */ 28. };