Rev 829 | Rev 874 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
221 | giacomo | 1 | //===================================================================== |
2 | // FFFFFFIII RRRRR SSTTTTTTT |
||
3 | // FF IIR RR SS |
||
4 | // FF IR SS |
||
5 | // FFFFFF RRRR SSSSST |
||
6 | // FF FI RRR SS |
||
7 | // FF II RRR SS |
||
8 | // FF IIIIIR RS |
||
9 | // |
||
10 | // Basic FSF(FIRST Scheduling Framework) contract management |
||
11 | // S.Ha.R.K. Implementation |
||
12 | //===================================================================== |
||
13 | |||
868 | trimarchi | 14 | #include "fsf_core.h" |
808 | trimarchi | 15 | #include "fsf_server.h" |
868 | trimarchi | 16 | #include "fsf_shared_objects.h" |
17 | #include "fsf_hierarchical.h" |
||
18 | #include "fsf_spare_capacity.h" |
||
808 | trimarchi | 19 | #include <kernel/descr.h> |
20 | #include <kernel/func.h> |
||
21 | #include <pistar.h> |
||
221 | giacomo | 22 | |
808 | trimarchi | 23 | struct hash_entry { |
24 | mutex_t mx; |
||
868 | trimarchi | 25 | FSF_SHARED_OBJ_HANDLE_T_OPAQUE id; |
808 | trimarchi | 26 | }; |
27 | |||
28 | |||
868 | trimarchi | 29 | #define MAX_HASH_ENTRY FSF_MAX_N_SHARED_OBJECTS |
808 | trimarchi | 30 | struct hash_entry htable[MAX_HASH_ENTRY]; |
31 | |||
32 | |||
33 | /*----------------------------------------------------------------------*/ |
||
34 | /* hash_fun() : address hash table */ |
||
35 | /*----------------------------------------------------------------------*/ |
||
868 | trimarchi | 36 | static int hash_fun(fsf_shared_obj_id_t id) |
808 | trimarchi | 37 | { |
38 | return (*id % MAX_HASH_ENTRY); |
||
39 | } |
||
40 | |||
811 | trimarchi | 41 | void fsf_register_shared_object(void) { |
42 | int i=0; |
||
43 | // Init Hash table |
||
44 | //kern_printf("(IT SO)\n"); |
||
45 | for (i=0; i<MAX_HASH_ENTRY; i++) { |
||
46 | htable[i].id=-1; |
||
808 | trimarchi | 47 | |
811 | trimarchi | 48 | } |
49 | |||
50 | } |
||
51 | |||
52 | |||
221 | giacomo | 53 | int fsf_initialize_contract |
54 | (fsf_contract_parameters_t *contract) |
||
55 | { |
||
56 | struct timespec default_deadline = FSF_DEFAULT_DEADLINE; |
||
57 | |||
58 | /* Check */ |
||
868 | trimarchi | 59 | if (!contract) return FSF_ERR_BAD_ARGUMENT; |
221 | giacomo | 60 | |
61 | /* Set to default value */ |
||
62 | NULL_TIMESPEC(&contract->budget_min); |
||
63 | NULL_TIMESPEC(&contract->budget_max); |
||
64 | NULL_TIMESPEC(&contract->period_min); |
||
65 | NULL_TIMESPEC(&contract->period_max); |
||
66 | |||
67 | contract->workload = FSF_DEFAULT_WORKLOAD; |
||
68 | |||
868 | trimarchi | 69 | contract->policy = FSF_DEFAULT_SCHED_POLICY; |
221 | giacomo | 70 | |
71 | contract->d_equals_t = FSF_DEFAULT_D_EQUALS_T; |
||
72 | |||
73 | TIMESPEC_ASSIGN(&contract->deadline,&default_deadline); |
||
74 | |||
75 | contract->budget_overrun_sig_notify = 0; |
||
76 | memset(&contract->budget_overrun_sig_value,0,sizeof(union sigval)); |
||
77 | |||
78 | contract->deadline_miss_sig_notify = 0; |
||
79 | memset(&contract->deadline_miss_sig_value,0,sizeof(union sigval)); |
||
80 | |||
81 | contract->granularity = FSF_DEFAULT_GRANULARITY; |
||
82 | contract->utilization_set.size = 0; |
||
83 | contract->quality = FSF_DEFAULT_QUALITY; |
||
84 | contract->importance = FSF_DEFAULT_IMPORTANCE; |
||
85 | |||
86 | contract->preemption_level = 0; |
||
87 | contract->critical_sections.size = 0; |
||
88 | |||
89 | return 0; |
||
90 | |||
91 | } |
||
92 | |||
93 | int fsf_set_contract_basic_parameters |
||
94 | (fsf_contract_parameters_t *contract, |
||
95 | const struct timespec *budget_min, |
||
868 | trimarchi | 96 | const struct timespec *period_max, |
221 | giacomo | 97 | fsf_workload_t workload) |
98 | { |
||
99 | |||
868 | trimarchi | 100 | if (!contract) return FSF_ERR_BAD_ARGUMENT; |
221 | giacomo | 101 | |
868 | trimarchi | 102 | if (budget_min) { |
103 | TIMESPEC_ASSIGN(&contract->budget_min,budget_min); |
||
104 | TIMESPEC_ASSIGN(&contract->budget_max,budget_min); |
||
105 | } |
||
106 | if (period_max) { |
||
107 | TIMESPEC_ASSIGN(&contract->period_max,period_max); |
||
108 | TIMESPEC_ASSIGN(&contract->period_min,period_max); |
||
109 | } |
||
110 | |||
221 | giacomo | 111 | contract->workload = workload; |
112 | |||
113 | return 0; |
||
114 | |||
115 | } |
||
116 | |||
117 | int fsf_get_contract_basic_parameters |
||
118 | (const fsf_contract_parameters_t *contract, |
||
119 | struct timespec *budget_min, |
||
120 | struct timespec *period_max, |
||
121 | fsf_workload_t *workload) |
||
122 | { |
||
123 | |||
868 | trimarchi | 124 | if (!contract) return FSF_ERR_BAD_ARGUMENT; |
221 | giacomo | 125 | |
126 | TIMESPEC_ASSIGN(budget_min,&contract->budget_min); |
||
868 | trimarchi | 127 | TIMESPEC_ASSIGN(period_max,&contract->period_max); |
221 | giacomo | 128 | |
129 | *workload = contract->workload; |
||
130 | |||
131 | return 0; |
||
132 | |||
133 | } |
||
134 | |||
135 | int fsf_set_contract_timing_requirements |
||
136 | (fsf_contract_parameters_t *contract, |
||
137 | bool d_equals_t, |
||
138 | const struct timespec *deadline, |
||
139 | int budget_overrun_sig_notify, |
||
140 | union sigval budget_overrun_sig_value, |
||
141 | int deadline_miss_sig_notify, |
||
142 | union sigval deadline_miss_sig_value) |
||
143 | { |
||
144 | |||
868 | trimarchi | 145 | if (!contract) return FSF_ERR_BAD_ARGUMENT; |
221 | giacomo | 146 | |
147 | contract->d_equals_t = d_equals_t; |
||
148 | |||
149 | if (deadline) TIMESPEC_ASSIGN(&contract->deadline,deadline); |
||
150 | |||
151 | contract->budget_overrun_sig_notify = budget_overrun_sig_notify; |
||
152 | contract->budget_overrun_sig_value = budget_overrun_sig_value; |
||
153 | contract->deadline_miss_sig_notify = deadline_miss_sig_notify; |
||
154 | contract->deadline_miss_sig_value = deadline_miss_sig_value; |
||
155 | |||
156 | return 0; |
||
157 | |||
158 | } |
||
159 | |||
160 | int fsf_get_contract_timing_requirements |
||
161 | (const fsf_contract_parameters_t *contract, |
||
162 | bool *d_equals_t, |
||
163 | struct timespec *deadline, |
||
164 | int *budget_overrun_sig_notify, |
||
165 | union sigval *budget_overrun_sig_value, |
||
166 | int *deadline_miss_sig_notify, |
||
167 | union sigval *deadline_miss_sig_value) |
||
168 | { |
||
169 | |||
868 | trimarchi | 170 | if (!contract) return FSF_ERR_BAD_ARGUMENT; |
221 | giacomo | 171 | |
172 | *d_equals_t = contract->d_equals_t; |
||
173 | |||
174 | TIMESPEC_ASSIGN(deadline,&contract->deadline); |
||
175 | |||
176 | *budget_overrun_sig_notify = contract->budget_overrun_sig_notify; |
||
177 | *budget_overrun_sig_value = contract->budget_overrun_sig_value; |
||
178 | *deadline_miss_sig_notify = contract->deadline_miss_sig_notify; |
||
179 | *deadline_miss_sig_value = contract->deadline_miss_sig_value; |
||
180 | |||
181 | return 0; |
||
182 | |||
183 | } |
||
184 | |||
868 | trimarchi | 185 | int |
186 | fsf_set_contract_reclamation_parameters |
||
187 | (fsf_contract_parameters_t *contract, |
||
188 | const struct timespec *budget_max, |
||
189 | const struct timespec *period_min, |
||
221 | giacomo | 190 | fsf_granularity_t granularity, |
868 | trimarchi | 191 | const fsf_utilization_set_t *utilization_set, |
221 | giacomo | 192 | int quality, |
193 | int importance) |
||
194 | { |
||
195 | |||
868 | trimarchi | 196 | if (!contract) return FSF_ERR_BAD_ARGUMENT; |
221 | giacomo | 197 | |
198 | contract->granularity = granularity; |
||
199 | |||
200 | if (utilization_set) memcpy(&contract->utilization_set,utilization_set,sizeof(fsf_utilization_set_t)); |
||
868 | trimarchi | 201 | |
202 | if (budget_max) TIMESPEC_ASSIGN(&contract->budget_max,budget_max); |
||
203 | if (period_min) TIMESPEC_ASSIGN(&contract->period_min,period_min); |
||
204 | |||
221 | giacomo | 205 | contract->quality = quality; |
206 | contract->importance = importance; |
||
207 | |||
208 | return 0; |
||
209 | |||
210 | } |
||
211 | |||
212 | int fsf_get_contract_reclamation_parameters |
||
213 | (const fsf_contract_parameters_t *contract, |
||
868 | trimarchi | 214 | struct timespec *budget_max, |
215 | struct timespec *period_min, |
||
221 | giacomo | 216 | fsf_granularity_t *granularity, |
217 | fsf_utilization_set_t *utilization_set, |
||
218 | int *quality, |
||
219 | int *importance) |
||
220 | { |
||
221 | |||
868 | trimarchi | 222 | if (!contract) return FSF_ERR_BAD_ARGUMENT; |
221 | giacomo | 223 | |
224 | *granularity = contract->granularity; |
||
225 | |||
226 | memcpy(utilization_set,&contract->utilization_set,sizeof(fsf_utilization_set_t)); |
||
868 | trimarchi | 227 | |
228 | TIMESPEC_ASSIGN(budget_max,&contract->budget_max); |
||
229 | TIMESPEC_ASSIGN(period_min,&contract->period_min); |
||
221 | giacomo | 230 | |
231 | *quality = contract->quality; |
||
232 | *importance = contract->importance; |
||
233 | |||
234 | return 0; |
||
235 | |||
236 | } |
||
237 | |||
238 | int fsf_set_contract_synchronization_parameters |
||
239 | (fsf_contract_parameters_t *contract, |
||
240 | const fsf_critical_sections_t *critical_sections) |
||
241 | { |
||
242 | |||
868 | trimarchi | 243 | if (!contract) return FSF_ERR_BAD_ARGUMENT; |
221 | giacomo | 244 | |
245 | if (critical_sections) memcpy(&contract->critical_sections,critical_sections,sizeof(fsf_critical_sections_t)); |
||
246 | |||
247 | return 0; |
||
248 | |||
249 | } |
||
250 | |||
251 | int |
||
252 | fsf_get_contract_synchronization_parameters |
||
253 | (const fsf_contract_parameters_t *contract, |
||
254 | fsf_critical_sections_t *critical_sections) |
||
255 | { |
||
256 | |||
868 | trimarchi | 257 | if (!contract) return FSF_ERR_BAD_ARGUMENT; |
258 | |||
221 | giacomo | 259 | memcpy(critical_sections,&contract->critical_sections,sizeof(fsf_critical_sections_t)); |
260 | |||
261 | return 0; |
||
262 | |||
263 | } |
||
264 | |||
868 | trimarchi | 265 | int |
266 | fsf_set_contract_scheduling_policy |
||
221 | giacomo | 267 | (fsf_contract_parameters_t *contract, |
868 | trimarchi | 268 | fsf_sched_policy_t sched_policy) |
221 | giacomo | 269 | { |
270 | |||
868 | trimarchi | 271 | if (!contract) return FSF_ERR_BAD_ARGUMENT; |
221 | giacomo | 272 | |
868 | trimarchi | 273 | contract->policy = sched_policy; |
221 | giacomo | 274 | |
275 | return 0; |
||
276 | |||
277 | } |
||
278 | |||
279 | int |
||
868 | trimarchi | 280 | fsf_get_contract_scheduling_policy |
221 | giacomo | 281 | (const fsf_contract_parameters_t *contract, |
868 | trimarchi | 282 | fsf_sched_policy_t *sched_policy) |
221 | giacomo | 283 | { |
284 | |||
868 | trimarchi | 285 | if (!contract) return FSF_ERR_BAD_ARGUMENT; |
221 | giacomo | 286 | |
868 | trimarchi | 287 | *sched_policy = contract->policy; |
221 | giacomo | 288 | |
289 | return 0; |
||
290 | |||
291 | } |
||
292 | |||
868 | trimarchi | 293 | /* OLD VERSION |
808 | trimarchi | 294 | // mutex lock function |
221 | giacomo | 295 | |
808 | trimarchi | 296 | int fsf_lock_object(fsf_shared_operation_t *op) { |
297 | int index, oldindex; |
||
811 | trimarchi | 298 | |
299 | index=hash_fun(&(op->obj_id)); |
||
300 | //kern_printf("index %d, htableid %d, obj_op_id %d", index, htable[index].id,op->obj_id); |
||
221 | giacomo | 301 | |
808 | trimarchi | 302 | if (htable[index].id!=op->obj_id) { |
303 | oldindex=index; |
||
304 | index = (index + 1) % MAX_HASH_ENTRY; |
||
305 | // find |
||
811 | trimarchi | 306 | while (htable[index].id != op->obj_id && index!=oldindex) index=(index+1) % MAX_HASH_ENTRY; |
808 | trimarchi | 307 | if (index==oldindex) return -1; |
308 | } |
||
811 | trimarchi | 309 | //kern_printf("(SO LK)"); |
808 | trimarchi | 310 | // we need a special implementation for mutex_lock ... additional parameter |
829 | giacomo | 311 | return PISTAR_lock(FSF_get_shared_object_level(), &htable[index].mx,TIMESPEC2USEC(&op->wcet)); |
808 | trimarchi | 312 | |
313 | } |
||
314 | |||
315 | int fsf_unlock_object(fsf_shared_operation_t *op) { |
||
316 | |||
317 | int index, oldindex; |
||
318 | |||
319 | index=hash_fun(&op->obj_id); |
||
320 | |||
321 | if (htable[index].id!=op->obj_id) { |
||
322 | oldindex=index; |
||
323 | index = (index + 1) % MAX_HASH_ENTRY; |
||
324 | // find |
||
811 | trimarchi | 325 | while (htable[index].id != op->obj_id && index!=oldindex) index=(index+1) % MAX_HASH_ENTRY; |
808 | trimarchi | 326 | if (index==oldindex) return -1; |
327 | } |
||
811 | trimarchi | 328 | //kern_printf("UNLOCK index %d", index); |
329 | |||
808 | trimarchi | 330 | return mutex_unlock(&htable[index].mx); |
331 | |||
332 | |||
333 | |||
334 | } |
||
335 | |||
868 | trimarchi | 336 | */ |
337 | |||
338 | int fsf_init_shared_object |
||
339 | (fsf_shared_obj_id_t id, |
||
340 | fsf_shared_obj_handle_t *obj, |
||
341 | pthread_mutex_t *mutex) { |
||
808 | trimarchi | 342 | int index; |
343 | int oldindex; |
||
344 | PISTAR_mutexattr_t a; |
||
811 | trimarchi | 345 | SYS_FLAGS f; |
808 | trimarchi | 346 | |
347 | PISTAR_mutexattr_default(a); |
||
811 | trimarchi | 348 | //kern_printf("(SI SO)\n"); |
349 | f=kern_fsave(); |
||
829 | giacomo | 350 | |
868 | trimarchi | 351 | index=hash_fun(id); |
811 | trimarchi | 352 | //kern_printf("Index %d Hash %d", index, htable[index].id); |
829 | giacomo | 353 | |
868 | trimarchi | 354 | if (htable[index].id == index) { |
829 | giacomo | 355 | kern_frestore(f); |
356 | return -1; |
||
357 | } |
||
358 | |||
808 | trimarchi | 359 | if (htable[index].id>=0) { |
360 | oldindex=index; |
||
361 | index = (index + 1) % MAX_HASH_ENTRY; |
||
362 | // collision detection |
||
811 | trimarchi | 363 | while (htable[index].id >=0 && index!=oldindex) index=(index+1) % MAX_HASH_ENTRY; |
808 | trimarchi | 364 | // table is full |
825 | trimarchi | 365 | if (index==oldindex) { |
366 | kern_frestore(f); |
||
829 | giacomo | 367 | return -1; |
825 | trimarchi | 368 | } |
808 | trimarchi | 369 | } |
829 | giacomo | 370 | |
868 | trimarchi | 371 | //obj->size=0; |
829 | giacomo | 372 | |
808 | trimarchi | 373 | mutex_init(&(htable[index]).mx, &a); |
868 | trimarchi | 374 | mutex=&(htable[index]).mx; |
375 | htable[index].id=index; |
||
376 | *obj=*id; |
||
811 | trimarchi | 377 | kern_frestore(f); |
829 | giacomo | 378 | |
379 | return 0; |
||
380 | |||
811 | trimarchi | 381 | //kern_printf("(EI SO)\n"); |
808 | trimarchi | 382 | } |
383 | |||
868 | trimarchi | 384 | /* OLD VERSION |
808 | trimarchi | 385 | // Declare an operation |
386 | // This function is used to declare that a shared object has |
||
387 | // a synchronized operation on it. |
||
388 | // It checks if another operation with the same id has already been |
||
389 | // declared; if so, return false (-1). |
||
390 | // The obj_id field of the operation is set equal to the shared object id. |
||
391 | // the structure op is copied in the first free element in the array |
||
392 | // shared_op pof the structure obj. If there are no more free element, |
||
393 | // returns -1. |
||
394 | // Returns 0 if the operation has been completed, -1 otherwise. |
||
395 | |||
396 | int fsf_declare_shared_object_operation(fsf_shared_object_t *obj, |
||
397 | fsf_shared_operation_t *op) { |
||
398 | int i; |
||
825 | trimarchi | 399 | SYS_FLAGS f; |
400 | |||
401 | f=kern_fsave(); |
||
402 | |||
808 | trimarchi | 403 | for (i=0; i<obj->size; i++) { |
404 | // fail if the operation already declared |
||
825 | trimarchi | 405 | if (op->op_id==obj->shared_op[i].op_id) { |
406 | kern_frestore(f); |
||
808 | trimarchi | 407 | return -1; |
825 | trimarchi | 408 | } |
808 | trimarchi | 409 | } |
410 | |||
411 | // fail if the object is full |
||
825 | trimarchi | 412 | if (obj->size>(FSF_MAX_SHARED_OPERATION-1)) { |
413 | kern_frestore(f); |
||
808 | trimarchi | 414 | return -1; |
825 | trimarchi | 415 | } |
829 | giacomo | 416 | |
823 | trimarchi | 417 | //kern_printf("(DO SO)"); |
808 | trimarchi | 418 | obj->size++; |
829 | giacomo | 419 | obj->shared_op[i].op_id = op->op_id; |
420 | TIMESPEC_ASSIGN(&obj->shared_op[i].wcet,&op->wcet); |
||
421 | obj->shared_op[i].obj_id = obj->obj_id; |
||
422 | op->obj_id = obj->obj_id; |
||
423 | |||
825 | trimarchi | 424 | kern_frestore(f); |
829 | giacomo | 425 | |
808 | trimarchi | 426 | return 0; |
427 | |||
428 | |||
429 | } |
||
868 | trimarchi | 430 | */ |
808 | trimarchi | 431 | |
868 | trimarchi | 432 | /* OLD VERSION |
808 | trimarchi | 433 | int fsf_set_contract_synchronization_parameters( |
434 | fsf_contract_parameters_t *contract, |
||
435 | const fsf_shared_operation_t *shared_ops, |
||
436 | size_t op_num) |
||
437 | { |
||
438 | if (shared_ops && op_num < FSF_MAX_SHARED_OPERATION) |
||
439 | memcpy(&contract->shared_operations,shared_ops,op_num); |
||
440 | else return -1; |
||
441 | |||
442 | return 0; |
||
443 | } |
||
868 | trimarchi | 444 | */ |