|
2 | 2 | use alloc::sync::Arc; |
3 | 3 |
|
4 | 4 | use crate::{ |
5 | | - loader::get_app_data_by_name, |
6 | | - mm::{translated_refmut, translated_str}, |
7 | | - task::{ |
8 | | - add_task, current_task, current_user_token, exit_current_and_run_next, |
9 | | - suspend_current_and_run_next, |
10 | | - }, |
| 5 | + loader::get_app_data_by_name, mm::{translated_physaddr, translated_refmut, translated_str, MapPermission, VirtAddr}, task::{add_task, current_task, current_user_token, exit_current_and_run_next, suspend_current_and_run_next}, timer::get_time_us |
11 | 6 | }; |
12 | 7 |
|
13 | 8 | #[repr(C)] |
@@ -106,29 +101,83 @@ pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize { |
106 | 101 | /// HINT: You might reimplement it with virtual memory management. |
107 | 102 | /// HINT: What if [`TimeVal`] is splitted by two pages ? |
108 | 103 | pub fn sys_get_time(_ts: *mut TimeVal, _tz: usize) -> isize { |
109 | | - trace!( |
110 | | - "kernel:pid[{}] sys_get_time NOT IMPLEMENTED", |
111 | | - current_task().unwrap().pid.0 |
112 | | - ); |
113 | | - -1 |
| 104 | + trace!("kernel: sys_get_time"); |
| 105 | + let pa = translated_physaddr(current_user_token(), _ts as *const u8); |
| 106 | + let phy_ts = pa.0 as *mut TimeVal; |
| 107 | + |
| 108 | + let us = get_time_us(); |
| 109 | + let time_val = TimeVal { |
| 110 | + sec : us / 1_000_000, |
| 111 | + usec: us % 1_000_000, |
| 112 | + }; |
| 113 | + |
| 114 | + unsafe { *phy_ts = time_val }; |
| 115 | + 0 |
114 | 116 | } |
115 | 117 |
|
116 | | -/// YOUR JOB: Implement mmap. |
| 118 | +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] |
| 119 | +pub struct Flag(pub usize); |
| 120 | + |
| 121 | +impl Flag { |
| 122 | + pub fn is_readable(&self) -> bool { |
| 123 | + self.0 & 0x1 == 0x1 |
| 124 | + } |
| 125 | + |
| 126 | + pub fn is_writeable(&self) -> bool { |
| 127 | + self.0 & 0x2 == 0x2 |
| 128 | + } |
| 129 | + |
| 130 | + pub fn is_execute(&self) -> bool { |
| 131 | + self.0 & 0x4 == 0x4 |
| 132 | + } |
| 133 | +} |
| 134 | + |
| 135 | +// YOUR JOB: Implement mmap. |
117 | 136 | pub fn sys_mmap(_start: usize, _len: usize, _port: usize) -> isize { |
118 | | - trace!( |
119 | | - "kernel:pid[{}] sys_mmap NOT IMPLEMENTED", |
120 | | - current_task().unwrap().pid.0 |
121 | | - ); |
122 | | - -1 |
| 137 | + trace!("kernel: sys_mmap "); |
| 138 | + |
| 139 | + debug!("mmap start: {}, len: {}, port: {}", _start, _len, _port); |
| 140 | + |
| 141 | + let start_va = VirtAddr::from(_start); |
| 142 | + if !start_va.aligned() { |
| 143 | + return -1; |
| 144 | + } |
| 145 | + let end_va: VirtAddr = (_start + _len).into(); |
| 146 | + if _port & !0x7 != 0 || _port & 0x7 == 0 { |
| 147 | + return -1; |
| 148 | + } |
| 149 | + |
| 150 | + let mut map_perm: MapPermission = MapPermission::U; |
| 151 | + let pte_flag = Flag(_port); |
| 152 | + if pte_flag.is_readable() { |
| 153 | + map_perm |= MapPermission::R; |
| 154 | + } |
| 155 | + if pte_flag.is_writeable() { |
| 156 | + map_perm |= MapPermission::W; |
| 157 | + } |
| 158 | + if pte_flag.is_execute() { |
| 159 | + map_perm |= MapPermission::X; |
| 160 | + } |
| 161 | + |
| 162 | + if !current_task().unwrap().find_area_insert(start_va, end_va, map_perm) { |
| 163 | + return -1; |
| 164 | + } |
| 165 | + return 0; |
123 | 166 | } |
124 | 167 |
|
125 | 168 | /// YOUR JOB: Implement munmap. |
126 | 169 | pub fn sys_munmap(_start: usize, _len: usize) -> isize { |
127 | | - trace!( |
128 | | - "kernel:pid[{}] sys_munmap NOT IMPLEMENTED", |
129 | | - current_task().unwrap().pid.0 |
130 | | - ); |
131 | | - -1 |
| 170 | + trace!("kernel: sys_munmap "); |
| 171 | + let start_va = VirtAddr::from(_start); |
| 172 | + if !start_va.aligned() { |
| 173 | + return -1; |
| 174 | + } |
| 175 | + let end_va: VirtAddr = (_start + _len).into(); |
| 176 | + |
| 177 | + if !current_task().unwrap().find_area_remove(start_va, end_va) { |
| 178 | + return -1; |
| 179 | + } |
| 180 | + return 0; |
132 | 181 | } |
133 | 182 |
|
134 | 183 | /// change data segment size |
|
0 commit comments