@@ -3,11 +3,10 @@ use alloc::sync::Arc;
3
3
4
4
use crate :: {
5
5
loader:: get_app_data_by_name,
6
- mm:: { translated_refmut, translated_str} ,
6
+ mm:: { translated_byte_buffer , translated_refmut, translated_str, MapPermission , VPNRange , VirtAddr , VirtPageNum , FRAME_ALLOCATOR } ,
7
7
task:: {
8
- add_task, current_task, current_user_token, exit_current_and_run_next,
9
- suspend_current_and_run_next,
10
- } ,
8
+ add_task, current_task, current_user_token, exit_current_and_run_next, suspend_current_and_run_next
9
+ } , timer:: get_time_us,
11
10
} ;
12
11
13
12
#[ repr( C ) ]
@@ -105,30 +104,92 @@ pub fn sys_waitpid(pid: isize, exit_code_ptr: *mut i32) -> isize {
105
104
/// YOUR JOB: get time with second and microsecond
106
105
/// HINT: You might reimplement it with virtual memory management.
107
106
/// HINT: What if [`TimeVal`] is splitted by two pages ?
108
- 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
107
+ pub fn sys_get_time ( ts : * mut TimeVal , _tz : usize ) -> isize {
108
+ trace ! ( "kernel: sys_get_time" ) ;
109
+ // let token = current_user_token();
110
+ // let page_table = PageTable::from_token(token);
111
+ // let va = VirtAddr::from(ts as usize);
112
+ // let vpn = va.floor();
113
+ // let ppn = page_table.translate(vpn).unwrap().ppn();
114
+ // let offset = va.page_offset();
115
+ // let pa: PhysAddr = (Into::<usize>::into(Into::<PhysAddr>::into(ppn)) + offset).into();
116
+ // let ts: &mut TimeVal = pa.get_mut();
117
+ // let us = get_time_us();
118
+ // *ts = TimeVal {
119
+ // sec: us / 1_000_000,
120
+ // usec: us % 1_000_000,
121
+ // };
122
+ // 上面这个实现并不完美,无法处理跨页的情况
123
+ let token = current_user_token ( ) ;
124
+ let buf = translated_byte_buffer ( token, ts as * const u8 , core:: mem:: size_of :: < TimeVal > ( ) ) ;
125
+ let us = get_time_us ( ) ;
126
+ let ts = TimeVal {
127
+ sec : us / 1_000_000 ,
128
+ usec : us % 1_000_000 ,
129
+ } ;
130
+ let src = unsafe {
131
+ core:: slice:: from_raw_parts ( & ts as * const TimeVal as * const u8 , core:: mem:: size_of :: < TimeVal > ( ) )
132
+ } ;
133
+ let mut offset = 0 ;
134
+ for dst in buf {
135
+ let len = dst. len ( ) ;
136
+ dst. copy_from_slice ( & src[ offset..offset + len] ) ;
137
+ offset += len;
138
+ }
139
+ 0
114
140
}
115
141
116
- /// YOUR JOB: Implement mmap.
117
- 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
142
+ // YOUR JOB: Implement mmap.
143
+ pub fn sys_mmap ( start : usize , len : usize , prot : usize ) -> isize {
144
+ trace ! ( "kernel: sys_mmap" ) ;
145
+ let start_va = VirtAddr :: from ( start) ;
146
+ if !start_va. aligned ( ) || ( prot & !0x7 != 0 ) || ( prot & 0x7 == 0 ) {
147
+ trace ! ( "kernel: sys_mmap failed, invalid parameters!" ) ;
148
+ return -1 ;
149
+ }
150
+ let end_va: VirtAddr = VirtAddr :: from ( start + len) . ceil ( ) . into ( ) ;
151
+ let start_vpn: VirtPageNum = start_va. into ( ) ;
152
+ let end_vpn: VirtPageNum = end_va. into ( ) ;
153
+
154
+ // Check if there are enough free pages
155
+ if end_vpn. 0 - start_vpn. 0 > FRAME_ALLOCATOR . exclusive_access ( ) . free_page_count ( ) {
156
+ trace ! ( "kernel: sys_mmap failed, not enough free pages!" ) ;
157
+ return -1 ;
158
+ }
159
+
160
+ // Check if the new memory area overlaps with existing areas
161
+ let current = current_task ( ) . unwrap ( ) ;
162
+ let mut inner = current. inner_exclusive_access ( ) ;
163
+ let new_vpn_range = VPNRange :: new ( start_vpn, end_vpn) ;
164
+ for area in inner. memory_set . areas . iter ( ) {
165
+ if area. vpn_range . has_intersection ( & new_vpn_range) {
166
+ trace ! ( "kernel: sys_mmap failed, overlapping memory area!" ) ;
167
+ return -1 ;
168
+ }
169
+ }
170
+
171
+ let mut permission = MapPermission :: U ;
172
+ permission |= MapPermission :: from_bits ( ( prot << 1 ) as u8 ) . unwrap ( ) ;
173
+ inner. memory_set . insert_framed_area ( start_va, end_va, permission) ;
174
+ 0
123
175
}
124
176
125
- /// YOUR JOB: Implement munmap.
126
- 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
177
+ // YOUR JOB: Implement munmap.
178
+ pub fn sys_munmap ( start : usize , len : usize ) -> isize {
179
+ trace ! ( "kernel: sys_munmap" ) ;
180
+ let start_va = VirtAddr :: from ( start) ;
181
+ if !start_va. aligned ( ) {
182
+ trace ! ( "kernel: sys_munmap failed, invalid parameters!" ) ;
183
+ return -1 ;
184
+ }
185
+ let end_va: VirtAddr = VirtAddr :: from ( start + len) . ceil ( ) . into ( ) ;
186
+
187
+ let current = current_task ( ) . unwrap ( ) ;
188
+ let mut inner = current. inner_exclusive_access ( ) ;
189
+ match inner. memory_set . remove_framed_area ( start_va, end_va) {
190
+ Some ( _) => 0 ,
191
+ None => -1
192
+ }
132
193
}
133
194
134
195
/// change data segment size
0 commit comments