线程调度测试

我们终于可以来测试一下这一章的代码实现的有没有问题了!

  1. // src/process/mod.rs
  2. use scheduler::RRScheduler;
  3. use thread_pool::ThreadPool;
  4. use alloc::boxed::Box;
  5. pub fn init() {
  6. // 使用 Round Robin Scheduler
  7. let scheduler = RRScheduler::new(1);
  8. // 新建线程池
  9. let thread_pool = ThreadPool::new(100, Box::new(scheduler));
  10. // 新建内核线程 idle ,其入口为 Processor::idle_main
  11. let idle = Thread::new_kernel(Processor::idle_main as usize);
  12. // 我们需要传入 CPU 的地址作为参数
  13. idle.append_initial_arguments([&CPU as *const Processor as usize, 0, 0]);
  14. // 初始化 CPU
  15. CPU.init(idle, Box::new(thread_pool));
  16. // 依次新建 5 个内核线程并加入调度单元
  17. for i in 0..5 {
  18. CPU.add_thread({
  19. let thread = Thread::new_kernel(hello_thread as usize);
  20. // 传入一个编号作为参数
  21. thread.append_initial_arguments([i, 0, 0]);
  22. thread
  23. });
  24. }
  25. println!("++++ setup process! ++++");
  26. }
  27. pub fn run() {
  28. CPU.run();
  29. }
  30. // src/process/processor.rs
  31. impl Processor {
  32. pub fn run(&self) {
  33. // 运行,也就是从启动线程切换到调度线程 idle
  34. Thread::get_boot_thread().switch_to(&mut self.inner().idle);
  35. }
  36. }

内核线程的入口点是:

  1. // src/process/mod.rs
  2. #[no_mangle]
  3. pub extern "C" fn hello_thread(arg: usize) -> ! {
  4. println!("begin of thread {}", arg);
  5. for i in 0..800 {
  6. print!("{}", arg);
  7. }
  8. println!("\nend of thread {}", arg);
  9. // 通知 CPU 自身已经退出
  10. CPU.exit(0);
  11. loop {}
  12. }

随后我们在rust_main主函数里添加调用crate::process::init()函数和crate::process::run()函数:

  1. // src/init.rs
  2. #[no_mangle]
  3. pub extern "C" fn rust_main() -> ! {
  4. crate::interrupt::init();
  5. extern "C" {
  6. fn end();
  7. }
  8. crate::memory::init(
  9. ((end as usize - KERNEL_BEGIN_VADDR + KERNEL_BEGIN_PADDR) >> 12) + 1,
  10. PHYSICAL_MEMORY_END >> 12
  11. );
  12. crate::process::init();
  13. crate::timer::init();
  14. crate::process::run();
  15. loop {}
  16. }

make run 一下,终于可以看到结果了!

这里开始就已经没有确定性的运行显示结果了,一个参考结果如下:

线程调度成功

  1. ++++ setup interrupt! ++++
  2. switch satp from 0x8000000000080221 to 0x8000000000080a37
  3. ++++ setup memory! ++++
  4. ++++ setup process! ++++
  5. ++++ setup timer! ++++
  6. >>>> will switch_to thread 0 in idie_main!
  7. begin of thread 0
  8. 0000000000000000000000000000000000000000000000000000000000000000000000000
  9. 0000000000000000000000000000000000000000000000000000000000000000000000000
  10. 0000000000000000000000000000000000000000000000000000000000000000000000000
  11. 0000000000000000000000000000000000000000000000000000000000000000000000000
  12. 0000000000000000000000000000000000000000000000000000000000000000000000000
  13. 000000000000
  14. <<<< switch_back to idle in idle_main!
  15. >>>> will switch_to thread 1 in idie_main!
  16. begin of thread 1
  17. 1111111111111111111111111111111111111111111111111111111111111111111111111
  18. 1111111111111111111111111111111111111111111111111111111111111111111111111
  19. 1111111111111111111111111111111111111111111111111111111111111111111111111
  20. 1111111111111111111111111111111111111111111111111111111111111111111111111
  21. 1111111111111111111111111111111111111111111111111111111111111111111111111
  22. 1111111111111111111111111111111111111111111111111111111111111111111111111
  23. 11111111111111111111111
  24. <<<< switch_back to idle in idle_main!
  25. ......

我们可以清楚的看到在每一个时间片内每个线程所做的事情。

如果结果不对的话,这里可以看到至今的所有代码。