33use alloc:: sync:: Arc ;
44
55use crate :: {
6- fs:: { open_file, OpenFlags } ,
7- mm:: { translated_refmut, translated_str} ,
8- task:: {
6+ fs:: { open_file, OpenFlags } , mm:: { translated_physaddr, translated_refmut, translated_str, MapPermission , VirtAddr } , task:: {
97 add_task, current_task, current_user_token, exit_current_and_run_next,
10- suspend_current_and_run_next,
11- } ,
8+ suspend_current_and_run_next, TaskControlBlock
9+ } , timer :: get_time_us
1210} ;
1311
1412#[ repr( C ) ]
@@ -78,6 +76,7 @@ pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
7876 . iter ( )
7977 . any ( |p| pid == -1 || pid as usize == p. getpid ( ) )
8078 {
79+ debug ! ( "no such pid[{}]" , pid) ;
8180 return -1 ;
8281 // ---- release current PCB
8382 }
@@ -95,8 +94,10 @@ pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
9594 let exit_code = child. inner_exclusive_access ( ) . exit_code ;
9695 // ++++ release child PCB
9796 * translated_refmut ( inner. memory_set . token ( ) , exit_code_ptr) = exit_code;
97+ debug ! ( "found pid[{}]" , found_pid) ;
9898 found_pid as isize
9999 } else {
100+ // debug!("pid[{}] is running", pid);
100101 -2
101102 }
102103 // ---- release current PCB automatically
@@ -106,29 +107,83 @@ pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
106107/// HINT: You might reimplement it with virtual memory management.
107108/// HINT: What if [`TimeVal`] is splitted by two pages ?
108109pub 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
110+ trace ! ( "kernel: sys_get_time" ) ;
111+ let pa = translated_physaddr ( current_user_token ( ) , _ts as * const u8 ) ;
112+ let phy_ts = pa. 0 as * mut TimeVal ;
113+
114+ let us = get_time_us ( ) ;
115+ let time_val = TimeVal {
116+ sec : us / 1_000_000 ,
117+ usec : us % 1_000_000 ,
118+ } ;
119+
120+ unsafe { * phy_ts = time_val } ;
121+ 0
114122}
115123
116- /// YOUR JOB: Implement mmap.
124+ #[ derive( Copy , Clone , Debug , Default , Eq , PartialEq ) ]
125+ pub struct Flag ( pub usize ) ;
126+
127+ impl Flag {
128+ pub fn is_readable ( & self ) -> bool {
129+ self . 0 & 0x1 == 0x1
130+ }
131+
132+ pub fn is_writeable ( & self ) -> bool {
133+ self . 0 & 0x2 == 0x2
134+ }
135+
136+ pub fn is_execute ( & self ) -> bool {
137+ self . 0 & 0x4 == 0x4
138+ }
139+ }
140+
141+ // YOUR JOB: Implement mmap.
117142pub 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
143+ trace ! ( "kernel: sys_mmap " ) ;
144+
145+ debug ! ( "mmap start: {}, len: {}, port: {}" , _start, _len, _port) ;
146+
147+ let start_va = VirtAddr :: from ( _start) ;
148+ if !start_va. aligned ( ) {
149+ return -1 ;
150+ }
151+ let end_va: VirtAddr = ( _start + _len) . into ( ) ;
152+ if _port & !0x7 != 0 || _port & 0x7 == 0 {
153+ return -1 ;
154+ }
155+
156+ let mut map_perm: MapPermission = MapPermission :: U ;
157+ let pte_flag = Flag ( _port) ;
158+ if pte_flag. is_readable ( ) {
159+ map_perm |= MapPermission :: R ;
160+ }
161+ if pte_flag. is_writeable ( ) {
162+ map_perm |= MapPermission :: W ;
163+ }
164+ if pte_flag. is_execute ( ) {
165+ map_perm |= MapPermission :: X ;
166+ }
167+
168+ if !current_task ( ) . unwrap ( ) . find_area_insert ( start_va, end_va, map_perm) {
169+ return -1 ;
170+ }
171+ return 0 ;
123172}
124173
125174/// YOUR JOB: Implement munmap.
126175pub 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
176+ trace ! ( "kernel: sys_munmap " ) ;
177+ let start_va = VirtAddr :: from ( _start) ;
178+ if !start_va. aligned ( ) {
179+ return -1 ;
180+ }
181+ let end_va: VirtAddr = ( _start + _len) . into ( ) ;
182+
183+ if !current_task ( ) . unwrap ( ) . find_area_remove ( start_va, end_va) {
184+ return -1 ;
185+ }
186+ return 0 ;
132187}
133188
134189/// change data segment size
@@ -148,7 +203,19 @@ pub fn sys_spawn(_path: *const u8) -> isize {
148203 "kernel:pid[{}] sys_spawn NOT IMPLEMENTED" ,
149204 current_task( ) . unwrap( ) . pid. 0
150205 ) ;
151- -1
206+ let token = current_user_token ( ) ;
207+ let path = translated_str ( token, _path) ;
208+ if let Some ( app_inode) = open_file ( path. as_str ( ) , OpenFlags :: RDONLY ) {
209+ let all_data = app_inode. read_all ( ) ;
210+ let new_task: Arc < TaskControlBlock > = current_task ( ) . unwrap ( ) . spawn ( & all_data) ;
211+ let pid = new_task. getpid ( ) as isize ;
212+ add_task ( new_task) ;
213+ debug ! ( "add task pid[{}]" , pid) ;
214+ return pid;
215+ } else {
216+ debug ! ( "kernel: sys spawn error..." ) ;
217+ return -1 ;
218+ }
152219}
153220
154221// YOUR JOB: Set task priority.
@@ -157,5 +224,9 @@ pub fn sys_set_priority(_prio: isize) -> isize {
157224 "kernel:pid[{}] sys_set_priority NOT IMPLEMENTED" ,
158225 current_task( ) . unwrap( ) . pid. 0
159226 ) ;
160- -1
227+ if _prio < 2 {
228+ return -1 ;
229+ }
230+ current_task ( ) . unwrap ( ) . set_priority ( _prio as usize ) ;
231+ return _prio;
161232}
0 commit comments