线程调度测试

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

1. // src/process/mod.rs

3. use scheduler::RRScheduler;
4. use thread_pool::ThreadPool;
5. use alloc::boxed::Box;

7. pub fn init() {
8. // 使用 Round Robin Scheduler
9. let scheduler = RRScheduler::new(1);
10. // 新建线程池
11. let thread_pool = ThreadPool::new(100, Box::new(scheduler));
12. // 新建内核线程 idle ,其入口为 Processor::idle_main
13. let idle = Thread::new_kernel(Processor::idle_main as usize);
14. // 我们需要传入 CPU 的地址作为参数
15. idle.append_initial_arguments([&CPU as *const Processor as usize, 0, 0]);
16. // 初始化 CPU
17. CPU.init(idle, Box::new(thread_pool));

19. // 依次新建 5 个内核线程并加入调度单元
20. for i in 0..5 {
21. CPU.add_thread({
22. let thread = Thread::new_kernel(hello_thread as usize);
23. // 传入一个编号作为参数
24. thread.append_initial_arguments([i, 0, 0]);
25. thread
26. });
27. }
28. println!("++++ setup process!   ++++");
29. }

31. pub fn run() {
32. CPU.run();
33. }

35. // src/process/processor.rs

37. impl Processor {
38. pub fn run(&self) {
39. // 运行,也就是从启动线程切换到调度线程 idle
40. Thread::get_boot_thread().switch_to(&mut self.inner().idle);
41. }
42. }

内核线程的入口点是:

1. // src/process/mod.rs

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

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

1. // src/init.rs

3. #[no_mangle]
4. pub extern "C" fn rust_main() -> ! {
5. crate::interrupt::init();

7. extern "C" {
8. fn end();
9. }
10. crate::memory::init(
11. ((end as usize - KERNEL_BEGIN_VADDR + KERNEL_BEGIN_PADDR) >> 12) + 1,
12. PHYSICAL_MEMORY_END >> 12
13. );
14. crate::process::init();
15. crate::timer::init();
16. crate::process::run();
17. loop {}
18. }

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

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

线程调度成功

``` 1. ++++ setup interrupt! ++++ 2. switch satp from 0x8000000000080221 to 0x8000000000080a37 3. ++++ setup memory! ++++ 4. ++++ setup process! ++++ 5. ++++ setup timer! ++++

  1. will switch_to thread 0 in idie_main!

  2. begin of thread 0
  3. 0000000000000000000000000000000000000000000000000000000000000000000000000
  4. 0000000000000000000000000000000000000000000000000000000000000000000000000
  5. 0000000000000000000000000000000000000000000000000000000000000000000000000
  6. 0000000000000000000000000000000000000000000000000000000000000000000000000
  7. 0000000000000000000000000000000000000000000000000000000000000000000000000
  8. 000000000000
  9. <<<< switch_back to idle in idle_main!

  10. will switch_to thread 1 in idie_main!

  11. begin of thread 1
  12. 1111111111111111111111111111111111111111111111111111111111111111111111111
  13. 1111111111111111111111111111111111111111111111111111111111111111111111111
  14. 1111111111111111111111111111111111111111111111111111111111111111111111111
  15. 1111111111111111111111111111111111111111111111111111111111111111111111111
  16. 1111111111111111111111111111111111111111111111111111111111111111111111111
  17. 1111111111111111111111111111111111111111111111111111111111111111111111111
  18. 11111111111111111111111
  19. <<<< switch_back to idle in idle_main!
  20. ...... ```

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

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