//! Process management syscalls use crate::config::PAGE_SIZE; use crate::mm::{MapPermission, VPNRange, VirtAddr}; use crate::task::{change_program_brk, create_new_map_area, exit_current_and_run_next, get_current_task_page_table_entry, suspend_current_and_run_next, unmap_virtual_page}; use crate::timer::get_time_ms; /// task exits and submit an exit code pub fn sys_exit(exit_code: i32) -> ! { println!("[kernel] Application exited with code {}", exit_code); exit_current_and_run_next(); panic!("Unreachable in sys_exit!"); } /// current task gives up resources for other tasks pub fn sys_yield() -> isize { suspend_current_and_run_next(); 0 } /// get current time pub fn sys_get_time() -> isize { get_time_ms() as isize } /// change data segment size pub fn sys_sbrk(size: i32) -> isize { if let Some(old_brk) = change_program_brk(size) { old_brk as isize } else { -1 } } /// map files or devices into memory pub fn sys_mmap(start: usize, len: usize, prot: usize) -> isize { if start % PAGE_SIZE != 0 || prot & !0x7 != 0 || prot & 0x7 == 0 { return -1; } let vpn_start = VirtAddr::from(start).floor(); let vpn_end = VirtAddr::from(start + len).ceil(); let vpn_range = VPNRange::new(vpn_start, vpn_end); for vpn in vpn_range { if let Some(pte) = get_current_task_page_table_entry(vpn) { if pte.is_valid() { return -1; } } } create_new_map_area( vpn_start.into(), vpn_end.into(), MapPermission::from_bits_truncate((prot << 1) as u8) | MapPermission::U ); 0 } /// unmap files or devices into memory pub fn sys_munmap(start: usize, len: usize) -> isize { if start % PAGE_SIZE != 0 { return -1; } let vpn_start = VirtAddr::from(start).floor(); let vpn_end = VirtAddr::from(start + len).ceil(); let vpn_range = VPNRange::new(vpn_start, vpn_end); for vpn in vpn_range { if let Some(pte) = get_current_task_page_table_entry(vpn) { if !pte.is_valid() { return -1; } unmap_virtual_page(vpn) } else { return -1; } } 0 }