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