Fork the current user thread
(current_context: &mut Context)
| 632 | /// |
| 633 | /// |
| 634 | pub fn fork_current_thread(current_context: &mut Context) { |
| 635 | |
| 636 | if let Some(current_thread) = CURRENT_THREAD.read().as_ref() { |
| 637 | |
| 638 | // Allocate user stack |
| 639 | let page_table_ptr = memory::active_pagetable_ptr(); |
| 640 | if let Ok((user_stack_start, user_stack_end)) = memory::allocate_user_stack(page_table_ptr) { |
| 641 | let new_thread = { |
| 642 | // Create a new kernel stack |
| 643 | let kernel_stack = Vec::with_capacity(KERNEL_STACK_SIZE); |
| 644 | let kernel_stack_start = VirtAddr::from_ptr(kernel_stack.as_ptr()); |
| 645 | let kernel_stack_end = (kernel_stack_start + KERNEL_STACK_SIZE).as_u64(); |
| 646 | |
| 647 | Box::new(Thread { |
| 648 | tid: unique_id(), |
| 649 | process: current_thread.process.clone(), // Shared state |
| 650 | page_table_physaddr: current_thread.page_table_physaddr, // Shared page table |
| 651 | kernel_stack, |
| 652 | kernel_stack_end, |
| 653 | user_stack_end, |
| 654 | context: kernel_stack_end - INTERRUPT_CONTEXT_SIZE as u64, |
| 655 | }) |
| 656 | }; |
| 657 | |
| 658 | let new_context = unsafe {&mut *(new_thread.context as *mut Context)}; |
| 659 | *new_context = current_context.clone(); |
| 660 | |
| 661 | // Set new stack pointer |
| 662 | new_context.rsp = new_thread.user_stack_end as usize; |
| 663 | |
| 664 | // Set return values in rax |
| 665 | new_context.rax = 0; // No error |
| 666 | new_context.rdi = 0; // Indicates that this is the new thread |
| 667 | current_context.rax = 0; // No error |
| 668 | current_context.rdi = new_thread.tid as usize; |
| 669 | |
| 670 | RUNNING_QUEUE.write().push_back(new_thread); |
| 671 | } else { |
| 672 | // Failed to allocate user stack |
| 673 | current_context.rax = syscalls::SYSCALL_ERROR_MEMALLOC; // Error code |
| 674 | } |
| 675 | } else { |
| 676 | // Somehow no current thread |
| 677 | current_context.rax = 2; // Error code |
| 678 | } |
| 679 | } |
| 680 | |
| 681 | /// This function is called via syscall (and maybe other mechanism) |
| 682 | /// to remove the current thread. |
no test coverage detected