@@ -2,6 +2,36 @@ use crate::sync::{Condvar, Mutex, MutexBlocking, MutexSpin, Semaphore};
2
2
use crate :: task:: { block_current_and_run_next, current_process, current_task} ;
3
3
use crate :: timer:: { add_timer, get_time_ms} ;
4
4
use alloc:: sync:: Arc ;
5
+ use alloc:: vec;
6
+ use alloc:: vec:: Vec ;
7
+
8
+ fn detect_deadlock (
9
+ mut available : Vec < isize > ,
10
+ alloc : & Vec < Vec < isize > > ,
11
+ need : & Vec < Vec < isize > > ,
12
+ ) -> bool {
13
+ let mut finish = vec ! [ false ; alloc. len( ) ] ;
14
+ let mut changed = true ;
15
+ while changed {
16
+ changed = false ;
17
+ for ( index, ( task_need, task_alloc) ) in need. iter ( ) . zip ( alloc. iter ( ) ) . enumerate ( ) {
18
+ if finish[ index] {
19
+ continue ;
20
+ }
21
+ if available. iter ( ) . zip ( task_need) . all ( |( a, b) | a >= b) {
22
+ available = available
23
+ . iter ( )
24
+ . zip ( task_alloc)
25
+ . map ( |( a, b) | a + b)
26
+ . collect ( ) ;
27
+ finish[ index] = true ;
28
+ changed = true ;
29
+ }
30
+ }
31
+ }
32
+ !finish. iter ( ) . all ( |& x| x)
33
+ }
34
+
5
35
/// sleep syscall
6
36
pub fn sys_sleep ( ms : usize ) -> isize {
7
37
trace ! (
@@ -49,49 +79,82 @@ pub fn sys_mutex_create(blocking: bool) -> isize {
49
79
. map ( |( id, _) | id)
50
80
{
51
81
process_inner. mutex_list [ id] = mutex;
82
+ process_inner. resource_available [ 0 ] [ id] = 1 ;
83
+ process_inner. resource_alloc [ 0 ]
84
+ . iter_mut ( )
85
+ . for_each ( |resource_alloc| resource_alloc[ id] = 0 ) ;
86
+ process_inner. resource_need [ 0 ]
87
+ . iter_mut ( )
88
+ . for_each ( |resource_need| resource_need[ id] = 0 ) ;
52
89
id as isize
53
90
} else {
54
91
process_inner. mutex_list . push ( mutex) ;
92
+ process_inner. resource_available [ 0 ] . push ( 1 ) ;
93
+ process_inner. resource_alloc [ 0 ]
94
+ . iter_mut ( )
95
+ . for_each ( |resource_alloc| resource_alloc. push ( 0 ) ) ;
96
+ process_inner. resource_need [ 0 ]
97
+ . iter_mut ( )
98
+ . for_each ( |resource_need| resource_need. push ( 0 ) ) ;
55
99
process_inner. mutex_list . len ( ) as isize - 1
56
100
}
57
101
}
58
102
/// mutex lock syscall
59
103
pub fn sys_mutex_lock ( mutex_id : usize ) -> isize {
104
+ let tid = current_task ( )
105
+ . unwrap ( )
106
+ . inner_exclusive_access ( )
107
+ . res
108
+ . as_ref ( )
109
+ . unwrap ( )
110
+ . tid ;
60
111
trace ! (
61
112
"kernel:pid[{}] tid[{}] sys_mutex_lock" ,
62
113
current_task( ) . unwrap( ) . process. upgrade( ) . unwrap( ) . getpid( ) ,
63
- current_task( )
64
- . unwrap( )
65
- . inner_exclusive_access( )
66
- . res
67
- . as_ref( )
68
- . unwrap( )
69
- . tid
114
+ tid
70
115
) ;
71
116
let process = current_process ( ) ;
72
- let process_inner = process. inner_exclusive_access ( ) ;
117
+ let mut process_inner = process. inner_exclusive_access ( ) ;
118
+ process_inner. resource_need [ 0 ] [ tid] [ mutex_id] += 1 ;
73
119
let mutex = Arc :: clone ( process_inner. mutex_list [ mutex_id] . as_ref ( ) . unwrap ( ) ) ;
74
- drop ( process_inner) ;
75
- drop ( process) ;
76
- mutex. lock ( ) ;
77
- 0
120
+ if detect_deadlock (
121
+ process_inner. resource_available [ 0 ] . clone ( ) ,
122
+ & process_inner. resource_alloc [ 0 ] ,
123
+ & process_inner. resource_need [ 0 ] ,
124
+ ) {
125
+ process_inner. resource_need [ 0 ] [ tid] [ mutex_id] -= 1 ;
126
+ -0xDEAD
127
+ } else {
128
+ drop ( process_inner) ;
129
+ drop ( process) ;
130
+ mutex. lock ( ) ;
131
+ let process = current_process ( ) ;
132
+ let mut process_inner = process. inner_exclusive_access ( ) ;
133
+ process_inner. resource_available [ 0 ] [ mutex_id] -= 1 ;
134
+ process_inner. resource_alloc [ 0 ] [ tid] [ mutex_id] += 1 ;
135
+ process_inner. resource_need [ 0 ] [ tid] [ mutex_id] -= 1 ;
136
+ 0
137
+ }
78
138
}
79
139
/// mutex unlock syscall
80
140
pub fn sys_mutex_unlock ( mutex_id : usize ) -> isize {
141
+ let tid = current_task ( )
142
+ . unwrap ( )
143
+ . inner_exclusive_access ( )
144
+ . res
145
+ . as_ref ( )
146
+ . unwrap ( )
147
+ . tid ;
81
148
trace ! (
82
149
"kernel:pid[{}] tid[{}] sys_mutex_unlock" ,
83
150
current_task( ) . unwrap( ) . process. upgrade( ) . unwrap( ) . getpid( ) ,
84
- current_task( )
85
- . unwrap( )
86
- . inner_exclusive_access( )
87
- . res
88
- . as_ref( )
89
- . unwrap( )
90
- . tid
151
+ tid
91
152
) ;
92
153
let process = current_process ( ) ;
93
- let process_inner = process. inner_exclusive_access ( ) ;
154
+ let mut process_inner = process. inner_exclusive_access ( ) ;
94
155
let mutex = Arc :: clone ( process_inner. mutex_list [ mutex_id] . as_ref ( ) . unwrap ( ) ) ;
156
+ process_inner. resource_available [ 0 ] [ mutex_id] += 1 ;
157
+ process_inner. resource_alloc [ 0 ] [ tid] [ mutex_id] -= 1 ;
95
158
drop ( process_inner) ;
96
159
drop ( process) ;
97
160
mutex. unlock ( ) ;
@@ -120,54 +183,89 @@ pub fn sys_semaphore_create(res_count: usize) -> isize {
120
183
. map ( |( id, _) | id)
121
184
{
122
185
process_inner. semaphore_list [ id] = Some ( Arc :: new ( Semaphore :: new ( res_count) ) ) ;
186
+ process_inner. resource_available [ 1 ] [ id] = res_count as isize ;
187
+ process_inner. resource_alloc [ 1 ]
188
+ . iter_mut ( )
189
+ . for_each ( |resource_alloc| resource_alloc[ id] = 0 ) ;
190
+ process_inner. resource_need [ 1 ]
191
+ . iter_mut ( )
192
+ . for_each ( |resource_need| resource_need[ id] = 0 ) ;
123
193
id
124
194
} else {
125
195
process_inner
126
196
. semaphore_list
127
197
. push ( Some ( Arc :: new ( Semaphore :: new ( res_count) ) ) ) ;
198
+ process_inner. resource_available [ 1 ] . push ( res_count as isize ) ;
199
+ process_inner. resource_alloc [ 1 ]
200
+ . iter_mut ( )
201
+ . for_each ( |resource_alloc| resource_alloc. push ( 0 ) ) ;
202
+ process_inner. resource_need [ 1 ]
203
+ . iter_mut ( )
204
+ . for_each ( |resource_need| resource_need. push ( 0 ) ) ;
128
205
process_inner. semaphore_list . len ( ) - 1
129
206
} ;
130
207
id as isize
131
208
}
132
209
/// semaphore up syscall
133
210
pub fn sys_semaphore_up ( sem_id : usize ) -> isize {
211
+ let tid = current_task ( )
212
+ . unwrap ( )
213
+ . inner_exclusive_access ( )
214
+ . res
215
+ . as_ref ( )
216
+ . unwrap ( )
217
+ . tid ;
134
218
trace ! (
135
219
"kernel:pid[{}] tid[{}] sys_semaphore_up" ,
136
220
current_task( ) . unwrap( ) . process. upgrade( ) . unwrap( ) . getpid( ) ,
137
- current_task( )
138
- . unwrap( )
139
- . inner_exclusive_access( )
140
- . res
141
- . as_ref( )
142
- . unwrap( )
143
- . tid
221
+ tid
144
222
) ;
145
223
let process = current_process ( ) ;
146
- let process_inner = process. inner_exclusive_access ( ) ;
224
+ let mut process_inner = process. inner_exclusive_access ( ) ;
225
+ process_inner. resource_alloc [ 1 ] [ tid] [ sem_id] -= 1 ;
226
+ process_inner. resource_available [ 1 ] [ sem_id] += 1 ;
147
227
let sem = Arc :: clone ( process_inner. semaphore_list [ sem_id] . as_ref ( ) . unwrap ( ) ) ;
148
228
drop ( process_inner) ;
149
229
sem. up ( ) ;
150
230
0
151
231
}
152
232
/// semaphore down syscall
153
233
pub fn sys_semaphore_down ( sem_id : usize ) -> isize {
234
+ let tid = current_task ( )
235
+ . unwrap ( )
236
+ . inner_exclusive_access ( )
237
+ . res
238
+ . as_ref ( )
239
+ . unwrap ( )
240
+ . tid ;
154
241
trace ! (
155
242
"kernel:pid[{}] tid[{}] sys_semaphore_down" ,
156
243
current_task( ) . unwrap( ) . process. upgrade( ) . unwrap( ) . getpid( ) ,
157
- current_task( )
158
- . unwrap( )
159
- . inner_exclusive_access( )
160
- . res
161
- . as_ref( )
162
- . unwrap( )
163
- . tid
244
+ tid
164
245
) ;
165
246
let process = current_process ( ) ;
166
- let process_inner = process. inner_exclusive_access ( ) ;
247
+ let mut process_inner = process. inner_exclusive_access ( ) ;
248
+ process_inner. resource_need [ 1 ] [ tid] [ sem_id] += 1 ;
167
249
let sem = Arc :: clone ( process_inner. semaphore_list [ sem_id] . as_ref ( ) . unwrap ( ) ) ;
168
- drop ( process_inner) ;
169
- sem. down ( ) ;
170
- 0
250
+ if process_inner. detect_deadlock
251
+ && detect_deadlock (
252
+ process_inner. resource_available [ 1 ] . clone ( ) ,
253
+ & process_inner. resource_alloc [ 1 ] ,
254
+ & process_inner. resource_need [ 1 ] ,
255
+ )
256
+ {
257
+ process_inner. resource_need [ 1 ] [ tid] [ sem_id] -= 1 ;
258
+ -0xDEAD
259
+ } else {
260
+ drop ( process_inner) ;
261
+ sem. down ( ) ;
262
+ let process = current_process ( ) ;
263
+ let mut process_inner = process. inner_exclusive_access ( ) ;
264
+ process_inner. resource_available [ 1 ] [ sem_id] -= 1 ;
265
+ process_inner. resource_alloc [ 1 ] [ tid] [ sem_id] += 1 ;
266
+ process_inner. resource_need [ 1 ] [ tid] [ sem_id] -= 1 ;
267
+ 0
268
+ }
171
269
}
172
270
/// condvar create syscall
173
271
pub fn sys_condvar_create ( ) -> isize {
@@ -247,5 +345,17 @@ pub fn sys_condvar_wait(condvar_id: usize, mutex_id: usize) -> isize {
247
345
/// YOUR JOB: Implement deadlock detection, but might not all in this syscall
248
346
pub fn sys_enable_deadlock_detect ( _enabled : usize ) -> isize {
249
347
trace ! ( "kernel: sys_enable_deadlock_detect NOT IMPLEMENTED" ) ;
250
- -1
251
- }
348
+ let process = current_process ( ) ;
349
+ let mut process_inner = process. inner_exclusive_access ( ) ;
350
+ match _enabled {
351
+ 0 => {
352
+ process_inner. detect_deadlock = false ;
353
+ 0
354
+ }
355
+ 1 => {
356
+ process_inner. detect_deadlock = true ;
357
+ 0
358
+ }
359
+ _ => -1 ,
360
+ }
361
+ }
0 commit comments