MCPcopy Create free account
hub / github.com/bendudson/EuraliOS / allocate_user_stack

Function allocate_user_stack

kernel/src/memory.rs:712–786  ·  view source on GitHub ↗

Allocate memory for a thread's user stack Uses 8 pages per thread: 7 for user stack, one guard page # Returns (user_stack_start, user_stack_end)

(
    level_4_table: *mut PageTable
)

Source from the content-addressed store, hash-verified

710/// (user_stack_start, user_stack_end)
711///
712pub fn allocate_user_stack(
713 level_4_table: *mut PageTable
714) -> Result<(u64, u64), &'static str> {
715
716 let memory_info = unsafe {MEMORY_INFO.as_mut().unwrap()};
717
718 let mut table = unsafe {&mut *level_4_table};
719 for index in THREAD_STACK_PAGE_INDEX {
720 let entry = &mut table[index as usize];
721 if entry.is_unused() {
722 // Page not allocated -> Create page table
723 let (_new_table_ptr, new_table_physaddr) = create_empty_pagetable();
724 entry.set_addr(PhysAddr::new(new_table_physaddr),
725 PageTableFlags::PRESENT |
726 PageTableFlags::WRITABLE |
727 PageTableFlags::USER_ACCESSIBLE);
728 }
729 table = unsafe {&mut *(memory_info.physical_memory_offset
730 + entry.addr().as_u64()).as_mut_ptr()};
731 }
732
733 // Table should now be the level 1 page table
734 //
735 // Find an unused set of 8 pages. The lowest page is always unused
736 // (guard), but the first should be used so look in pages
737 // (1 + 8*n) where n=0..64
738 //
739 // Choose a random n to start looking, and check entries
740 // sequentially from there. For now just use process::unique_id
741 use crate::process;
742 let n_start = process::unique_id(); // Modulo 64 soon
743 for i in 0..64 {
744 let n = ((n_start + i) % 64) as usize;
745
746 if table[n * 8 + 1].is_unused() {
747 // Found an empty slot:
748 // [n * 8] -> Empty (guard)
749 // [n * 8 + 1] -> User stack (read-only)
750 // ...
751 // [n * 8 + 7] -> User stack (writable)
752
753 // Note: Only one frame is going to be allocated, and the rest
754 // are going to be read-only references to the same frame.
755 // When a thread tries to write to them a page fault will
756 // be triggered and the frame allocated.
757 let frame = memory_info.frame_allocator.allocate_frame()
758 .ok_or("Failed to allocate frame")?;
759
760 for j in 1..7 {
761 // These pages are read-only
762 let entry = &mut table[n * 8 + j];
763 entry.set_addr(frame.start_address(),
764 PageTableFlags::PRESENT |
765 PageTableFlags::USER_ACCESSIBLE);
766 }
767 let entry = &mut table[n * 8 + 7];
768 entry.set_addr(frame.start_address(),
769 PageTableFlags::PRESENT |

Callers 2

new_user_threadFunction · 0.85
fork_current_threadFunction · 0.85

Calls 5

create_empty_pagetableFunction · 0.85
unique_idFunction · 0.85
as_mut_ptrMethod · 0.80
allocate_frameMethod · 0.80
as_u64Method · 0.45

Tested by

no test coverage detected