This is called by the timer interrupt handler Returns the stack containing the process state (interrupts::Context struct)
(context_addr: usize)
| 705 | /// Returns the stack containing the process state |
| 706 | /// (interrupts::Context struct) |
| 707 | pub fn schedule_next(context_addr: usize) -> usize { |
| 708 | let mut running_queue = RUNNING_QUEUE.write(); |
| 709 | let mut current_thread = CURRENT_THREAD.write(); |
| 710 | |
| 711 | if let Some(mut thread) = current_thread.take() { |
| 712 | // Put the current thread to the back of the queue |
| 713 | |
| 714 | // Store context location. This should almost always be in the same |
| 715 | // location on the kernel stack. The exception is the |
| 716 | // first time a context switch occurs from the original kernel |
| 717 | // stack to the first kernel thread stack. |
| 718 | thread.context = context_addr as u64; |
| 719 | |
| 720 | // Save the page table. This is to enable context |
| 721 | // switching during functions which manipulate page tables |
| 722 | // for example new_user_thread |
| 723 | thread.page_table_physaddr = memory::active_pagetable_physaddr(); |
| 724 | |
| 725 | running_queue.push_back(thread); |
| 726 | } |
| 727 | *current_thread = running_queue.pop_front(); |
| 728 | |
| 729 | match current_thread.as_ref() { |
| 730 | Some(thread) => { |
| 731 | // Set the kernel stack for the next interrupt |
| 732 | gdt::set_interrupt_stack_table( |
| 733 | gdt::TIMER_INTERRUPT_INDEX as usize, |
| 734 | // Note: Point to the end of the stack |
| 735 | VirtAddr::new(thread.kernel_stack_end)); |
| 736 | |
| 737 | if thread.page_table_physaddr != 0 { |
| 738 | // Change page table |
| 739 | // Note: zero for kernel thread |
| 740 | memory::switch_to_pagetable(thread.page_table_physaddr); |
| 741 | } |
| 742 | |
| 743 | // Point the stack to the new context |
| 744 | // (which is usually stored on the kernel stack) |
| 745 | thread.context as usize |
| 746 | }, |
| 747 | None => 0 |
| 748 | } |
| 749 | } |
| 750 | |
| 751 | /// Open the given path |
| 752 | /// Returns either a Rendezvous handle and path match length, or an error |
no test coverage detected