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