Rev 235 | Rev 334 | 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 <time.h> |
||
15 | #include <sys/boolean.h> |
||
16 | #include <sys/types.h> |
||
17 | |||
18 | #include "fsf_configuration_parameters.h" |
||
19 | #include "fsf_opaque_types.h" |
||
20 | |||
224 | giacomo | 21 | #include "edfstar.h" |
235 | giacomo | 22 | #include "rmstar.h" |
224 | giacomo | 23 | #include "posixstar.h" |
24 | |||
221 | giacomo | 25 | #ifndef _FSF_CONTRACT_H_ |
26 | #define _FSF_CONTRACT_H_ |
||
27 | |||
224 | giacomo | 28 | /* S.Ha.R.K. Init */ |
241 | giacomo | 29 | int FSF_register_module(int server_level); |
224 | giacomo | 30 | |
221 | giacomo | 31 | ////////////////////////////////////////////////////////////////// |
32 | // BASIC TYPES AND CONSTANTS |
||
33 | ////////////////////////////////////////////////////////////////// |
||
34 | |||
35 | typedef enum {FSF_BOUNDED, FSF_INDETERMINATE} fsf_workload_t; |
||
36 | |||
37 | typedef enum {FSF_CONTINUOUS, FSF_DISCRETE} fsf_granularity_t; |
||
38 | |||
39 | typedef struct { |
||
40 | struct timespec budget; // Execution time |
||
41 | struct timespec period; // Period |
||
42 | } fsf_utilization_value_t; |
||
43 | |||
44 | typedef struct { |
||
45 | int size; // = 0 |
||
46 | fsf_utilization_value_t unit[FSF_MAX_N_UTILIZATION_VALUES]; |
||
47 | } fsf_utilization_set_t; |
||
48 | |||
49 | typedef unsigned long fsf_preemption_level_t; // range 1..2**32-1 |
||
50 | |||
51 | typedef struct { |
||
52 | struct timespec wcet; // Execution time |
||
53 | fsf_preemption_level_t plevel; // Preemption_Level, range 1..2**32-1 |
||
54 | } fsf_critical_section_data_t; |
||
55 | |||
56 | typedef struct { |
||
57 | int size; // = 0 |
||
58 | fsf_critical_section_data_t section[FSF_MAX_N_CRITICAL_SECTIONS]; |
||
59 | } fsf_critical_sections_t; |
||
60 | |||
61 | typedef int fsf_scheduler_id_t; |
||
62 | |||
63 | #define FSF_SCHEDULER_POSIX 0 |
||
64 | #define FSF_SCHEDULER_EDF 1 |
||
65 | #define FSF_SCHEDULER_RM 2 |
||
66 | |||
67 | // Constants for assigning default values |
||
68 | #define FSF_DEFAULT_WORKLOAD FSF_INDETERMINATE |
||
69 | #define FSF_DEFAULT_GRANULARITY FSF_CONTINUOUS |
||
70 | #define FSF_DEFAULT_QUALITY 0 |
||
71 | #define FSF_DEFAULT_IMPORTANCE 1 |
||
72 | #define FSF_DEFAULT_D_EQUALS_T false |
||
73 | #define FSF_DEFAULT_DEADLINE {0,0} |
||
74 | #define FSF_DEFAULT_SCHEDULER FSF_SCHEDULER_POSIX |
||
75 | |||
76 | // Constants for omitting the assignment of values to specific arguments |
||
77 | // in calls to initialization functions |
||
78 | #define FSF_NULL_CRITICAL_SECTIONS (fsf_critical_sections_t *)NULL |
||
79 | #define FSF_NULL_UTILIZATION_SET (fsf_utilization_set_t *)NULL |
||
80 | #define FSF_NULL_DEADLINE (struct timespec *)NULL |
||
81 | #define FSF_NULL_SIGNAL 0 |
||
82 | |||
83 | |||
84 | // Error codes |
||
85 | #define FSF_ERR_NOT_INITIALIZED 2003001 |
||
86 | #define FSF_ERR_TOO_MANY_TASKS 2003002 |
||
87 | #define FSF_ERR_ALREADY_INITIALIZED 2003003 |
||
88 | #define FSF_ERR_BAD_ARGUMENT 2003004 |
||
89 | #define FSF_ERR_INVALID_SYNCH_OBJECT_HANDLE 2003005 |
||
90 | #define FSF_ERR_NO_RENEGOTIATION_REQUESTED 2003006 |
||
91 | #define FSF_ERR_CONTRACT_REJECTED 2003007 |
||
92 | #define FSF_ERR_TOO_MANY_SERVERS 2003008 |
||
241 | giacomo | 93 | #define FSF_ERR_CREATE_THREAD 2003009 |
94 | #define FSF_ERR_SERVER_USED 2003010 |
||
95 | #define FSF_ERR_INVALID_SERVER 2003011 |
||
96 | #define FSF_ERR_CREATE_SERVER 2003012 |
||
221 | giacomo | 97 | |
98 | ////////////////////////////////////////////////////////////// |
||
99 | // CONTRACT PARAMETERS |
||
100 | ////////////////////////////////////////////////////////////// |
||
101 | |||
102 | // Contract parameters type; it is an opaque type |
||
103 | typedef FSF_CONTRACT_PARAMETERS_T_OPAQUE fsf_contract_parameters_t; |
||
104 | |||
105 | int |
||
106 | fsf_initialize_contract(fsf_contract_parameters_t *contract); |
||
107 | |||
108 | //Description: The operation receives a pointer to a contract parameters |
||
109 | //object and initializes it, setting it to the default values. |
||
110 | // budget_min => {0,0}; |
||
111 | // period_max => {0,0}; |
||
112 | // budget_max => {0,0}; |
||
113 | // period_min => {0,0}; |
||
114 | // workload => DEFAULT_WORKLOAD; |
||
115 | |||
116 | // d_equals_t => DEFAULT_D_EQUALS_T; (false or true) |
||
117 | // deadline => DEFAULT_DEADLINE; |
||
118 | // budget_overrun_sig_notify => 0; (signal number) |
||
119 | // budget_overrun_sig_value => {0, NULL}; |
||
120 | // deadline_miss_sig_notify => 0; (signal number) |
||
121 | // deadline_miss_sig_value => {0, NULL}; |
||
122 | // |
||
123 | // granularity => DEFAULT_GRANULARITY; |
||
124 | // utilization_set; => size = 0 |
||
125 | // quality => DEFAULT_QUALITY; (range 0..100) |
||
126 | // importance => DEFAULT_IMPORTANCE; (range 1..5) |
||
127 | // |
||
128 | // preemption_level => 0; (range 1..2**32-1) |
||
129 | // critical_sections; => size = 0 |
||
130 | |||
131 | int |
||
132 | fsf_set_contract_basic_parameters |
||
133 | (fsf_contract_parameters_t *contract, |
||
134 | const struct timespec *budget_min, |
||
135 | const struct timespec *period_max, |
||
136 | const struct timespec *budget_max, |
||
137 | const struct timespec *period_min, |
||
138 | fsf_workload_t workload); |
||
139 | |||
140 | //Description: The operation updates the specified contract parameters |
||
141 | //object by setting its budget, period, and workload to the specified |
||
142 | //input parameters. (Note: the workload is a basic parameter because |
||
143 | //bounded tasks are triggered by the scheduler (see the Timed Schedule |
||
144 | //Next Job operation, later), while indeterminate tasks are not; |
||
145 | //therefore, their programming model is quite different). |
||
146 | |||
147 | int |
||
148 | fsf_get_contract_basic_parameters |
||
149 | (const fsf_contract_parameters_t *contract, |
||
150 | struct timespec *budget_min, |
||
151 | struct timespec *period_max, |
||
152 | struct timespec *budget_max, |
||
153 | struct timespec *period_min, |
||
154 | fsf_workload_t *workload); |
||
155 | |||
156 | //Description: This operation obtains from the specified contract parameters |
||
157 | //object its budget, period, and workload, and copies them to the places |
||
158 | //pointed to by the corresponding input parameters. |
||
159 | |||
160 | int |
||
161 | fsf_set_contract_timing_requirements |
||
162 | (fsf_contract_parameters_t *contract, |
||
163 | bool d_equals_t, |
||
164 | const struct timespec *deadline, |
||
165 | int budget_overrun_sig_notify, |
||
166 | union sigval budget_overrun_sig_value, |
||
167 | int deadline_miss_sig_notify, |
||
168 | union sigval deadline_miss_sig_value); |
||
169 | |||
170 | //Description: The operation updates the specified contract parameters |
||
171 | //object. d_equals_t is used as a boolean, deadline must be |
||
172 | //NULL_DEADLINE if d_equals_t is true, budget_overrun_sig_notify or |
||
173 | //deadline_miss_sig_notify may be NULL_SIGNAL (no notification) or any |
||
174 | //posix signal. budget_overrun_sig_value and deadline_miss_sig_value |
||
175 | //are the values to be delivered with the signal. |
||
176 | |||
177 | int |
||
178 | fsf_get_contract_timing_requirements |
||
179 | (const fsf_contract_parameters_t *contract, |
||
180 | bool *d_equals_t, |
||
181 | struct timespec *deadline, |
||
182 | int *budget_overrun_sig_notify, |
||
183 | union sigval *budget_overrun_sig_value, |
||
184 | int *deadline_miss_sig_notify, |
||
185 | union sigval *deadline_miss_sig_value); |
||
186 | |||
187 | //Description: The operation obtains the corresponding input |
||
188 | //parameters from the specified contract parameters object. If |
||
189 | //d_equals_t is true, the deadline will not be updated. |
||
190 | |||
191 | int |
||
192 | fsf_set_contract_reclamation_parameters |
||
193 | (fsf_contract_parameters_t *contract, |
||
194 | fsf_granularity_t granularity, |
||
195 | const fsf_utilization_set_t *utilization_set, |
||
196 | int quality, |
||
197 | int importance); |
||
198 | |||
199 | //Description: The operation updates the specified contract parameters |
||
200 | //object by setting its granularity, utilization set, quality, and |
||
201 | //importance to the specified input parameters. |
||
202 | |||
203 | int |
||
204 | fsf_get_contract_reclamation_parameters |
||
205 | (const fsf_contract_parameters_t *contract, |
||
206 | fsf_granularity_t *granularity, |
||
207 | fsf_utilization_set_t *utilization_set, |
||
208 | int *quality, |
||
209 | int *importance); |
||
210 | |||
211 | //Description: The operation obtains from the specified contract parameters |
||
212 | //object its granularity, utilization set, quality, and importance. Then |
||
213 | //copies them to the places pointed to by the specified input parameters. |
||
214 | //Only the utilization_values of the utilization_set that are in use, are |
||
215 | //copied (according to its size field). |
||
216 | |||
217 | int |
||
218 | fsf_set_contract_synchronization_parameters |
||
219 | (fsf_contract_parameters_t *contract, |
||
220 | fsf_preemption_level_t preemption_level, |
||
221 | const fsf_critical_sections_t *critical_sections); |
||
222 | |||
223 | //Description: The operation updates the specified contract parameters |
||
224 | //object by setting its preemption level and critical sections to the |
||
225 | //specified input parameters. |
||
226 | |||
227 | int |
||
228 | fsf_get_contract_synchronization_parameters |
||
229 | (const fsf_contract_parameters_t *contract, |
||
230 | fsf_preemption_level_t *preemption_level, |
||
231 | fsf_critical_sections_t *critical_sections); |
||
232 | |||
233 | //Description: The operation obtains from the specified contract |
||
234 | //parameters object its preemption level and critical sections, and |
||
235 | //copies them to the places pointed to by the specified input |
||
236 | //parameters. Only those critical_section_data records that are in use |
||
237 | //in the critical_sections structure are copied (according to its size |
||
238 | //field). |
||
239 | |||
240 | int |
||
241 | fsf_set_local_scheduler_parameter |
||
242 | (fsf_contract_parameters_t *contract, |
||
243 | fsf_scheduler_id_t local_scheduler_id); |
||
244 | |||
241 | giacomo | 245 | //Description: Set the local scheduler |
246 | |||
221 | giacomo | 247 | int |
248 | fsf_get_local_scheduler_parameter |
||
249 | (const fsf_contract_parameters_t *contract, |
||
250 | fsf_scheduler_id_t *local_scheduler_id); |
||
251 | |||
241 | giacomo | 252 | //Description: Get the local scheduler |
253 | |||
221 | giacomo | 254 | ////////////////////////////////////////////////////////////// |
255 | // SYNCHRONIZATION OBJECTS |
||
256 | ////////////////////////////////////////////////////////////// |
||
257 | |||
258 | //An abstract synchronization object is defined by the application. |
||
259 | //This object can be used by an application to wait for an event to |
||
260 | //arrive by invoking the Event Triggered Schedule Next Job operation. |
||
261 | //It can also be used to signal the event either causing a waiting |
||
262 | //server to wake up, or the event to be queued if no server is waiting |
||
263 | //for it. It is defined by the following opaque type and has the |
||
264 | //following operations: |
||
265 | |||
266 | typedef FSF_SYNCH_OBJECT_HANDLE_T_OPAQUE fsf_synch_object_handle_t; |
||
267 | |||
268 | int |
||
269 | fsf_create_synchobject(fsf_synch_object_handle_t *synch_handle); |
||
270 | |||
271 | //Description: This operation creates and initializes a |
||
272 | //synchronization object variable managed by the scheduler, and |
||
273 | //returns a handle to it in the variable pointed to by synch_handle. |
||
274 | |||
275 | int |
||
276 | fsf_signal_synchobject(fsf_synch_object_handle_t *synch_handle); |
||
277 | |||
278 | //Description: If one or more servers are waiting upon the specified |
||
279 | //synchronization object one of them is awakened; if not, the event is |
||
280 | //queued at the synchronization object. |
||
281 | |||
282 | int |
||
283 | fsf_destroy_synchobject(fsf_synch_object_handle_t *synch_handle); |
||
284 | |||
285 | //This operation destroys the synchronization object (created by a |
||
286 | //previous call to fsf_create_synchobject) that is referenced by the |
||
287 | //synch_handle variable. After calling this operation, the |
||
288 | //synch_handle variable can not be used until it is initialized again |
||
289 | //by a call to fsf_create_synchobject. |
||
290 | |||
291 | |||
292 | /////////////////////////////////////////////////////////////// |
||
293 | // CONTRACT NEGOCIATION OPERATIONS |
||
294 | /////////////////////////////////////////////////////////////// |
||
295 | |||
296 | // Server Id type, that identifies a server created to manage a |
||
297 | // given contract |
||
298 | |||
299 | typedef int fsf_server_id_t; |
||
300 | |||
301 | // The following type references a function that may become |
||
302 | // a thread's code |
||
303 | |||
304 | typedef void * (*fsf_thread_code_t) (void *); |
||
305 | |||
306 | // Negotiate contract functions: The following functions are used to |
||
307 | // create servers for a contract parameters specification and also to |
||
308 | // assign one or more threads to a server (Note: the current |
||
309 | // implementation only supports one thread per server; this limitation |
||
310 | // will be removed in the next phase of the project) |
||
311 | |||
312 | // The first time that any of these operations is called, it creates |
||
313 | // all the internal management structures that are necessary for the |
||
314 | // FIRST Scheduling Framework to operate properly. |
||
315 | |||
316 | int |
||
317 | fsf_negotiate_contract |
||
318 | (const fsf_contract_parameters_t *contract, |
||
319 | fsf_server_id_t *server); |
||
320 | |||
321 | //Description: The operation negotiates a contract for a new |
||
322 | //server. If the on-line admission test is enabled it determines |
||
323 | //whether the contract can be admitted or not based on the current |
||
324 | //contracts established in the system. Then it creates the server and |
||
325 | //recalculates all necessary parameters for the contracts already |
||
326 | //present in the system. This is a potentially blocking operation; it |
||
327 | //returns when the system has either rejected the contract, or |
||
328 | //admitted it and made it effective. It returns zero and places the |
||
329 | //server identification number in the location pointed to by the |
||
330 | //server input parameter if accepted, or an error if rejected. No |
||
331 | //thread is bound to the newly created server, which will be idle |
||
332 | //until a thread is bound to it. This operation can only be executed |
||
333 | //by threads that are already bound to an active server and therefore |
||
334 | //are being scheduled by the fsf scheduler. |
||
335 | |||
336 | int |
||
241 | giacomo | 337 | fsf_create_thread |
338 | (fsf_server_id_t server, |
||
339 | pthread_t *thread, |
||
340 | pthread_attr_t *attr, |
||
341 | fsf_thread_code_t thread_code, |
||
342 | void *arg, |
||
343 | void *local_scheduler_arg); |
||
221 | giacomo | 344 | |
241 | giacomo | 345 | //Description: This operation creates a new thread inside a specific |
346 | //server. The local_scheduler_arg parameter is used to pass specific |
||
347 | //parameters to local scheduler. These parameters are application |
||
348 | //depented. |
||
221 | giacomo | 349 | |
350 | int |
||
351 | fsf_get_server |
||
352 | (fsf_server_id_t *server, |
||
353 | pthread_t thread); |
||
354 | |||
355 | //Description: This operation returns the server associated with a |
||
356 | //thread. It returns an error if the thread does not exist, it is not |
||
357 | //under the control of the scheduling framework, or is not bound. |
||
358 | |||
359 | int |
||
360 | fsf_cancel_contract (fsf_server_id_t *server); |
||
361 | |||
362 | //Description: The operation eliminates the specified server and |
||
363 | //recalculates all necessary parameters for the contracts remaining in |
||
364 | //the system. This is a potentially blocking operation; it returns when |
||
365 | //the system has made the changes effective. |
||
366 | |||
367 | int |
||
368 | fsf_renegotiate_contract |
||
369 | (const fsf_contract_parameters_t *new_contract, |
||
370 | fsf_server_id_t server); |
||
371 | |||
372 | //Description: The operation renegotiates a contract for an existing |
||
373 | //server. If the on-line admission test is enabled it determines |
||
374 | //whether the contract can be admitted or not based on the current |
||
375 | //contracts established in the system. If it cannot be admitted, the |
||
376 | //old contract remains in effect and an error is returned. If it can |
||
377 | //be admitted, it recalculates all necessary parameters for the |
||
378 | //contracts already present in the system anr returns zero. This is a |
||
379 | //potentially blocking operation; it returns when the system has |
||
380 | //either rejected the new contract, or admitted it and made it |
||
381 | //effective. |
||
382 | |||
383 | int |
||
384 | fsf_request_contract_renegotiation |
||
385 | (const fsf_contract_parameters_t *new_contract, |
||
386 | fsf_server_id_t server, |
||
387 | int sig_notify, |
||
388 | union sigval sig_value); |
||
389 | |||
390 | //Description: The operation enqueues a renegotiate operation for an |
||
391 | //existing server, and returns immediately. The renegotiate operation |
||
392 | //is performed asynchronously, as soon as it is practical; meanwhile |
||
393 | //the system operation will continue normally. When the renegotiation |
||
394 | //is made, if the on-line admission test is enabled it determines |
||
395 | //whether the contract can be admitted or not based on the current |
||
396 | //contracts established in the system. If it cannot be admitted, the |
||
397 | //old contract remains in effect. If it can be admitted, it |
||
398 | //recalculates all necessary parameters for the contracts already |
||
399 | //present in the system. When the operation is completed, notification |
||
400 | //is made to the caller, if requested, via a signal. The status of the |
||
401 | //operation (in progress, admitted, rejected) can be checked with the |
||
402 | //get_renegotiation_status operation. The argument sig_notify can be |
||
403 | //NULL_SIGNAL (no notification), or any posix signal; and in this case |
||
404 | //sig_value is to be sent with the signal. |
||
405 | |||
406 | typedef enum {FSF_IN_PROGRESS, |
||
407 | FSF_REJECTED, |
||
408 | FSF_ADMITTED} fsf_renegotiation_status_t; |
||
409 | |||
410 | int |
||
411 | fsf_get_renegotiation_status |
||
412 | (fsf_server_id_t server, |
||
413 | fsf_renegotiation_status_t *renegotiation_status); |
||
414 | |||
415 | //Description: The operation reports on the status of the last |
||
416 | //renegotiation operation enqueued for the specified server. It is |
||
417 | //callable even after notification of the completion of such operation, |
||
418 | //if requested. |
||
419 | |||
420 | int |
||
421 | fsf_request_change_quality_and_importance |
||
422 | (fsf_server_id_t server, |
||
423 | int new_importance, |
||
424 | int new_quality); |
||
425 | |||
426 | //Description: The operation enqueues a request to change the quality and |
||
427 | //importance parameters of the specified server, and returns immediately. |
||
428 | //The change operation is performed as soon as it is practical; |
||
429 | //meanwhile the system operation will continue normally. |
||
430 | |||
431 | |||
432 | //////////////////////////////////////////////////////////// |
||
433 | // SCHEDULING BOUNDED WORKLOADS |
||
434 | //////////////////////////////////////////////////////////// |
||
435 | |||
436 | int |
||
437 | fsf_schedule_next_timed_job |
||
438 | (const struct timespec *at_absolute_time, |
||
439 | struct timespec *next_budget, |
||
440 | struct timespec *next_period, |
||
441 | bool *was_deadline_missed, |
||
442 | bool *was_budget_overran); |
||
443 | |||
444 | //Description: This operation is invoked by threads associated with |
||
445 | //bounded workload servers to indicate that a job has been completed |
||
446 | //(and that the scheduler may reassign the unused capacity of the |
||
447 | //current job to other servers), and also when the first job require |
||
448 | //to be scheduled. The system will activate the job at the specified |
||
449 | //absolute time, and will then use the scheduling rules to determine |
||
450 | //when the job can run, at which time the call returns. Upon return, |
||
451 | //the system reports the current period and budget for the current |
||
452 | //job, whether the deadline of the previous job was missed or not, |
||
453 | //and whether the budget of the previous job was overrun or not. |
||
454 | |||
455 | |||
456 | int |
||
457 | fsf_schedule_next_event_triggered_job |
||
458 | (fsf_synch_object_handle_t *synch_handle, |
||
459 | struct timespec *next_budget, |
||
460 | struct timespec *next_period, |
||
461 | bool *was_deadline_missed, |
||
462 | bool *was_budget_overran); |
||
463 | |||
464 | //Description: This operation is invoked by threads associated with |
||
465 | //bounded workload servers to indicate that a job has been completed |
||
466 | //(and that the scheduler may reassign the unused capacity of the |
||
467 | //current job to other servers), and also when the first job require |
||
468 | //to be scheduled. If the specified synchronization object has events |
||
469 | //queued, one of them is dequeued; otherwise the server will wait upon |
||
470 | //the specified synchronization object until it is signalled. Then, the |
||
471 | //system will use the scheduling rules to determine when the job can run |
||
472 | //and the call will return at that time. Upon return, the system reports |
||
473 | //the current period and budget for the current job, whether the deadline |
||
474 | //of the previous job was missed or not, and whether the budget of the |
||
475 | //previous job was overrun or not. |
||
476 | |||
477 | |||
478 | ////////////////////////////////////////////////////////////// |
||
479 | // OBTAINING INFORMATION FROM THE SCHEDULER |
||
480 | ////////////////////////////////////////////////////////////// |
||
481 | |||
482 | int |
||
483 | fsf_get_available_capacity (fsf_server_id_t server, float *capacity); |
||
484 | |||
485 | //Description: This operation returns the current spare capacity (in |
||
486 | //percentage of processor or network utilization), currently assigned |
||
487 | //to the importance level of the specified server. |
||
488 | |||
489 | int |
||
490 | fsf_get_total_quality (fsf_server_id_t server, int *total_quality); |
||
491 | |||
492 | //Description: This operation returns the sum of the quality parameters |
||
493 | //for all servers in the system of importance level equal to that of |
||
494 | //the specified server. |
||
495 | |||
496 | int |
||
497 | fsf_is_admission_test_enabled(); |
||
498 | |||
499 | //Description: Returns true if the system is configured with the |
||
500 | //on-line admission test enabled, or false otherwise. |
||
501 | |||
502 | |||
503 | #endif // _FSF_CONTRACT_H_ |