Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
864 | trimarchi | 1 | //fsf_core.h |
2 | //================================================================= |
||
3 | // FFFFFFIII RRRRR SSTTTTTTT |
||
4 | // FF IIR RR SS |
||
5 | // FF IR SS |
||
6 | // FFFFFF RRRR SSSSST |
||
7 | // FF FI RRR SS |
||
8 | // FF II RRR SS |
||
9 | // FF IIIIIR RS |
||
10 | // |
||
11 | // Basic FSF(FIRST Scheduling Framework) contract management |
||
12 | //================================================================ |
||
13 | |||
14 | #include "fsf_configuration_parameters.h" |
||
15 | #include "fsf_opaque_types.h" |
||
16 | #include "fsf_basic_types.h" |
||
17 | |||
18 | #ifndef _FSF_CORE_H_ |
||
19 | #define _FSF_CORE_H_ |
||
20 | |||
21 | ///////////////////////////////////////////////////////////////// |
||
22 | // BASIC TYPES AND CONSTANTS in fsf_basic_types.h |
||
23 | ///////////////////////////////////////////////////////////////// |
||
24 | |||
25 | //typedef enum {FSF_BOUNDED, FSF_INDETERMINATE} |
||
26 | // fsf_workload_t; |
||
27 | |||
28 | //// Constants for assigning default values |
||
29 | // |
||
30 | //#define FSF_DEFAULT_WORKLOAD FSF_INDETERMINATE |
||
31 | //#define FSF_DEFAULT_D_EQUALS_T false |
||
32 | //#define FSF_DEFAULT_DEADLINE {0,0} //struct timespec |
||
33 | // |
||
34 | // |
||
35 | //// Constants for omitting the assignment of values |
||
36 | //// to specific arguments in calls to |
||
37 | //// initialization functions |
||
38 | // |
||
39 | //#define FSF_NULL_DEADLINE (struct timespec *)NULL |
||
40 | //#define FSF_NULL_SIGNAL 0 |
||
41 | // |
||
42 | // |
||
43 | //// Error codes |
||
44 | //#define FSF_ERR_TOO_MANY_TASKS 2003001 |
||
45 | //#define FSF_ERR_BAD_ARGUMENT 2003002 |
||
46 | //#define FSF_ERR_INVALID_SYNCH_OBJ_HANDLE 2003003 |
||
47 | //#define FSF_ERR_NO_RENEGOTIATION_REQUESTED 2003004 |
||
48 | //#define FSF_ERR_CONTRACT_REJECTED 2003005 |
||
49 | //#define FSF_ERR_NOT_SCHEDULED_CALLING_THREAD 2003006 |
||
50 | //#define FSF_ERR_UNBOUND_THREAD 2003007 |
||
51 | //#define FSF_ERR_UNKNOWN_APPSCHEDULED_THREAD 2003008 |
||
52 | //#define FSF_ERR_NOT_CONTRACTED_SERVER 2003009 |
||
53 | //#define FSF_ERR_NOT_SCHEDULED_THREAD 2003010 |
||
54 | //#define FSF_ERR_TOO_MANY_SERVICE_JOBS 2003011 |
||
55 | //#define FSF_ERR_TOO_MANY_SYNCH_OBJS 2003012 |
||
56 | //#define FSF_ERR_TOO_MANY_SERVERS_IN_SYNCH_OBJ 2003013 |
||
57 | //#define FSF_ERR_TOO_MANY_EVENTS_IN_SYNCH_OBJ 2003014 |
||
58 | //#define FSF_ERR_INTERNAL_ERROR 2003015 |
||
59 | //#define FSF_ERR_TOO_MANY_SERVERS 2003016 |
||
60 | //#define FSF_ERR_INVALID_SCHEDULER_REPLY 2003017 |
||
61 | //#define FSF_ERR_TOO_MANY_PENDING_REPLENISHMENTS 2003018 |
||
62 | //#define FSF_WRN_MODULE_NOT_SUPPORTED 2004001 |
||
63 | // |
||
64 | |||
65 | /// This function converts an error code to an error message that is |
||
66 | /// stored in the buffer starting at the location pointed to by |
||
67 | /// message. The size of this buffer is specified by the size |
||
68 | /// argument. If the error message is longer than size-1, it is |
||
69 | /// truncated to that length. Regardless of whether the message is |
||
70 | /// truncated or not, a final zero character that marks the end of the |
||
71 | /// string is stored in the buffer. |
||
72 | /// The function fails if the error code passed does not correspond |
||
73 | /// to any of the fsf error codes. |
||
74 | |||
75 | int fsf_strerror (int error, char *message, size_t size); |
||
76 | |||
77 | ///////////////////////////////////////////////////////////// |
||
78 | // CONTRACT PARAMETERS |
||
79 | ///////////////////////////////////////////////////////////// |
||
80 | |||
81 | // Contract parameters type; it is an opaque type |
||
82 | |||
83 | typedef FSF_CONTRACT_PARAMETERS_T_OPAQUE fsf_contract_parameters_t; |
||
84 | |||
85 | /// fsf_initialize_contract: The operation receives a pointer to a |
||
86 | /// contract parameters object and initializes it, setting it to the |
||
87 | /// default values. |
||
88 | // budget_min => {0,0}; |
||
89 | // period_max => {0,0}; |
||
90 | // budget_max => {0,0}; |
||
91 | // period_min => {0,0}; |
||
92 | // workload => DEFAULT_WORKLOAD; |
||
93 | |||
94 | // d_equals_t => DEFAULT_D_EQUALS_T; (false or true) |
||
95 | // deadline => DEFAULT_DEADLINE; |
||
96 | // budget_overrun_sig_notify => 0; (signal number) |
||
97 | // budget_overrun_sig_value => {0, NULL}; |
||
98 | // deadline_miss_sig_notify => 0; (signal number) |
||
99 | // deadline_miss_sig_value => {0, NULL}; |
||
100 | // |
||
101 | // granularity => DEFAULT_GRANULARITY; |
||
102 | // utilization_set; => size = 0 |
||
103 | // quality => DEFAULT_QUALITY; (range 0..100) |
||
104 | // importance => DEFAULT_IMPORTANCE; (range 1..5) |
||
105 | // |
||
106 | // preemption_level => 0; (range 1..2**32-1) |
||
107 | // critical_sections; => size = 0 |
||
108 | // sched_policy => DEFAULT_SCHED_POLICY |
||
109 | // (FSF_NONE) |
||
110 | |||
111 | int fsf_initialize_contract (fsf_contract_parameters_t *contract); |
||
112 | |||
113 | |||
114 | /// fsf_set_contract_basic_parameters: The operation updates the |
||
115 | /// specified contract parameters object by setting its budget, |
||
116 | /// period, and workload to the specified input parameters. (Note: the |
||
117 | /// workload is a basic parameter because bounded tasks are triggered |
||
118 | /// by the scheduler (see the fsf_schedule_timed_job() operation), |
||
119 | /// while indeterminate tasks are not; therefore, their programming |
||
120 | /// model is quite different). |
||
121 | |||
122 | int |
||
123 | fsf_set_contract_basic_parameters |
||
124 | (fsf_contract_parameters_t *contract, |
||
125 | const struct timespec *budget_min, |
||
126 | const struct timespec *period_max, |
||
127 | fsf_workload_t workload); |
||
128 | |||
129 | |||
130 | //fsf_get_contract_basic_parameters: This operation obtains from the |
||
131 | //specified contract parameters object its budget, period, and |
||
132 | //workload, and copies them to the places pointed to by the |
||
133 | //corresponding input parameters. |
||
134 | |||
135 | int |
||
136 | fsf_get_contract_basic_parameters |
||
137 | (const fsf_contract_parameters_t *contract, |
||
138 | struct timespec *budget_min, |
||
139 | struct timespec *period_max, |
||
140 | fsf_workload_t *workload); |
||
141 | |||
142 | |||
143 | //fsf_set_contract_timing_requirements: The operation updates the |
||
144 | //specified contract parameters object. d_equals_t is used as a |
||
145 | //boolean, deadline must be NULL_DEADLINE if d_equals_t is true, |
||
146 | //budget_overrun_sig_notify or deadline_miss_sig_notify may be |
||
147 | //NULL_SIGNAL (no notification) or any posix |
||
148 | //signal. budget_overrun_sig_value and deadline_miss_sig_value are the |
||
149 | //values to be delivered with the signal. |
||
150 | |||
151 | int |
||
152 | 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 | |||
162 | //fsf_get_contract_timing_requirements: The operation obtains the |
||
163 | //corresponding input parameters from the specified contract |
||
164 | //parameters object. If d_equals_t is true, the deadline will not be |
||
165 | //updated. |
||
166 | |||
167 | int |
||
168 | fsf_get_contract_timing_requirements |
||
169 | (const fsf_contract_parameters_t *contract, |
||
170 | bool *d_equals_t, |
||
171 | struct timespec *deadline, |
||
172 | int *budget_overrun_sig_notify, |
||
173 | union sigval *budget_overrun_sig_value, |
||
174 | int *deadline_miss_sig_notify, |
||
175 | union sigval *deadline_miss_sig_value); |
||
176 | |||
177 | |||
178 | |||
179 | ////////////////////////////////////////////////////////////////// |
||
180 | // SYNCHRONIZATION OBJECTS |
||
181 | ////////////////////////////////////////////////////////////////// |
||
182 | |||
183 | |||
184 | //An abstract synchronization object is defined by the application. |
||
185 | //This object can be used by an application to wait for an event to |
||
186 | //arrive by invoking the fsf_schedule_triggered_job() operation. |
||
187 | //It can also be used to signal the event either causing a waiting |
||
188 | //server to wake up, or the event to be queued if no server is waiting |
||
189 | //for it. It is defined by the following opaque type and has the |
||
190 | //following operations: |
||
191 | |||
192 | typedef FSF_SYNCH_OBJ_HANDLE_T_OPAQUE fsf_synch_obj_handle_t; |
||
193 | |||
194 | |||
195 | //fsf_create_synch_obj: This operation creates and initializes a |
||
196 | //synchronization object variable managed by the scheduler, and |
||
197 | //returns a handle to it in the variable pointed to by synch_handle. |
||
198 | |||
199 | int |
||
200 | fsf_create_synch_obj |
||
201 | (fsf_synch_obj_handle_t *synch_handle); |
||
202 | |||
203 | |||
204 | //fsf_signal_synch_obj: If one or more servers are waiting upon the |
||
205 | //specified synchronization object one of them is awakened; if not, |
||
206 | //the event is queued at the synchronization object. |
||
207 | |||
208 | int |
||
209 | fsf_signal_synch_obj |
||
210 | (fsf_synch_obj_handle_t synch_handle); |
||
211 | |||
212 | |||
213 | //fsf_destroy_synch_obj: This operation destroys the synchronization |
||
214 | //object (created by a previous call to fsf_create_synch_obj) that is |
||
215 | //referenced by the synch_handle variable. After calling this |
||
216 | //operation, the synch_handle variable can not be used until it is |
||
217 | //initialized again by a call to fsf_create_synch_obj. |
||
218 | |||
219 | int |
||
220 | fsf_destroy_synch_obj |
||
221 | (fsf_synch_obj_handle_t synch_handle); |
||
222 | |||
223 | // In the future we may add a broadcast operation that would signal a |
||
224 | // group of synchronization objects. We have not included a broadcast |
||
225 | // service in this version because it can be easily created by the |
||
226 | // user by signalling individual synchronization objects inside a |
||
227 | // loop. |
||
228 | |||
229 | // Notice that for synchronization objects there is no naming service |
||
230 | // like in shared objects because tasks that use synchronization are |
||
231 | // not developed independently, as they are closely coupled. |
||
232 | |||
233 | |||
234 | |||
235 | /////////////////////////////////////////////////////////////////// |
||
236 | // CONTRACT NEGOCIATION OPERATIONS |
||
237 | /////////////////////////////////////////////////////////////////// |
||
238 | |||
239 | // Server Id type, that identifies a server created to manage a given |
||
240 | // contract |
||
241 | |||
242 | typedef int fsf_server_id_t; // => 0 |
||
243 | |||
244 | // The following type references a function that may become a thread's |
||
245 | // code |
||
246 | |||
247 | typedef void * (*fsf_thread_code_t) (void *); |
||
248 | |||
249 | |||
250 | // Negotiate contract functions: The following functions are used to |
||
251 | // create servers for a contract parameters specification and also to |
||
252 | // assign one or more threads to a server (Note: the current |
||
253 | // implementation only supports one thread per server; this limitation |
||
254 | // will be removed in the next phase of the project) |
||
255 | |||
256 | |||
257 | //fsf_negotiate_contract: The operation negotiates a contract for a |
||
258 | //new server. If the on-line admission test is enabled it determines |
||
259 | //whether the contract can be admitted or not based on the current |
||
260 | //contracts established in the system. Then it creates the server and |
||
261 | //recalculates all necessary parameters for the contracts already |
||
262 | //present in the system. This is a potentially blocking operation; it |
||
263 | //returns when the system has either rejected the contract, or |
||
264 | //admitted it and made it effective. It returns zero and places the |
||
265 | //server identification number in the location pointed to by the |
||
266 | //server input parameter if accepted, or an error if rejected. No |
||
267 | //thread is bound to the newly created server, which will be idle |
||
268 | //until a thread is bound to it. This operation can only be executed |
||
269 | //by threads that are already bound to an active server and therefore |
||
270 | //are being scheduled by the fsf scheduler. |
||
271 | |||
272 | int |
||
273 | fsf_negotiate_contract |
||
274 | (const fsf_contract_parameters_t *contract, |
||
275 | fsf_server_id_t *server); |
||
276 | |||
277 | |||
278 | //fsf_negotiate_contract_for_new_thread: This operation negotiates a |
||
279 | //contract for a new server, creates a thread and binds it to the |
||
280 | //server. If the contract is accepted, the operation creates a thread |
||
281 | //with the arguments thread, attr, thread_code and arg as they are |
||
282 | //defined for the pthread_create() POSIX function call, and attaches |
||
283 | //it to the fsf scheduler. Then, it binds the created thread to the |
||
284 | //new server. It returns zero and puts the server identification |
||
285 | //number in the location pointed to by the server input parameter. The |
||
286 | //attr parameter is overwritten as necessary to introduce the adequate |
||
287 | //scheduling policy and priority, according to the preemption level |
||
288 | //given in the contract and the fsf_priority_map() function defined by |
||
289 | //the user. If the contract is rejected, the thread is not created and |
||
290 | //the corresponding error is returned. |
||
291 | |||
292 | //The server is created with the FSF_NONE scheduling policy, which |
||
293 | //means no hierarchical scheduling, and only one thread per server, |
||
294 | //except for the case of background tasks (see below) |
||
295 | |||
296 | int |
||
297 | fsf_negotiate_contract_for_new_thread |
||
298 | (const fsf_contract_parameters_t *contract, |
||
299 | fsf_server_id_t *server, |
||
300 | pthread_t *thread, |
||
301 | pthread_attr_t *attr, |
||
302 | fsf_thread_code_t thread_code, |
||
303 | void *arg); |
||
304 | |||
305 | |||
306 | //fsf_negotiate_contract_for_myself: This operation negotiates a |
||
307 | //contract for a new server, and binds the calling thread to it. If |
||
308 | //the contract is accepted it returns zero and copies the server |
||
309 | //identification number in the location pointed to by the server input |
||
310 | //parameter. If it is rejected, an error is returned. |
||
311 | |||
312 | //The server is created with the FSF_NONE scheduling policy, which |
||
313 | //means no hierarchical scheduling, and only one thread per server, |
||
314 | //except for the case of background tasks (see below) |
||
315 | |||
316 | //Implementation dependent issue: In order to allow the usage of |
||
317 | //application defined schedulers, the calling thread must not have the |
||
318 | //SCHED_APP scheduling policy and at the same time be attached to an |
||
319 | //application scheduler different than the fsf scheduler; in such |
||
320 | //case, an error is returned. After a successful call the calling |
||
321 | //thread will have the SCHED_APP scheduling policy and will be |
||
322 | //attached to the fsf scheduler. |
||
323 | |||
324 | int |
||
325 | fsf_negotiate_contract_for_myself |
||
326 | (const fsf_contract_parameters_t *contract, |
||
327 | fsf_server_id_t *server); |
||
328 | |||
329 | |||
330 | //fsf_bind_thread_to_server: This operation associates a thread with a |
||
331 | //server, which means that it starts consuming the server's budget and |
||
332 | //is executed according to the contract established for that |
||
333 | //server. If the thread is already bound to another server, it is |
||
334 | //effectively unbound from it and bound to the specified one. |
||
335 | |||
336 | //It fails if the server's policy is different than FSF_NONE, or if |
||
337 | //there is already a thread bound to this server |
||
338 | |||
339 | //Implementation dependent issue: In order to allow the usage of |
||
340 | //application defined schedulers, the given thread must not have the |
||
341 | //scheduling policy SCHED_APP and at the same time be attached to an |
||
342 | //application scheduler different than the fsf scheduler. |
||
343 | |||
344 | int |
||
345 | fsf_bind_thread_to_server |
||
346 | (fsf_server_id_t server, |
||
347 | pthread_t thread); |
||
348 | |||
349 | |||
350 | //fsf_unbind_thread_from_server: This operation unbinds a thread from |
||
351 | //a server. Since threads with no server associated are not allow to |
||
352 | //execute, they remain in a dormant state until they are either |
||
353 | //eliminated or bound again. |
||
354 | |||
355 | // If the thread is inside a critical section the effects of this call |
||
356 | // are deferred until the critical section is ended |
||
357 | |||
358 | //Implementation dependent issue: in the implementation with an |
||
359 | //application scheduler, the thread is still attached to the fsf |
||
360 | //scheduler, but suspended. |
||
361 | |||
362 | int |
||
363 | fsf_unbind_thread_from_server (pthread_t thread); |
||
364 | |||
365 | |||
366 | //fsf_get_server: This operation stores the Id of the server |
||
367 | //associated with the specified thread in the variable pointed to by |
||
368 | //server. It returns an error if the thread does not exist, it is not |
||
369 | //under the control of the scheduling framework, or is not bound. |
||
370 | |||
371 | int |
||
372 | fsf_get_server |
||
373 | (pthread_t thread, |
||
374 | fsf_server_id_t *server); |
||
375 | |||
376 | |||
377 | //fsf_get_contract: This operation stores the contract parameters |
||
378 | //currently associated with the specified server in the variable |
||
379 | //pointed to by contract. It returns an error if the server id is |
||
380 | //incorrect. |
||
381 | |||
382 | int |
||
383 | fsf_get_contract |
||
384 | (fsf_server_id_t server, |
||
385 | fsf_contract_parameters_t *contract); |
||
386 | |||
387 | |||
388 | //fsf_cancel_contract: The operation eliminates the specified server |
||
389 | //and recalculates all necessary parameters for the contracts |
||
390 | //remaining in the system. This is a potentially blocking operation; |
||
391 | //it returns when the system has made the changes effective. |
||
392 | |||
393 | int |
||
394 | fsf_cancel_contract (fsf_server_id_t server); |
||
395 | |||
396 | |||
397 | //fsf_renegotiate_contract: The operation renegotiates a contract for |
||
398 | //an existing server. If the on-line admission test is enabled it |
||
399 | //determines whether the contract can be admitted or not based on the |
||
400 | //current contracts established in the system. If it cannot be |
||
401 | //admitted, the old contract remains in effect and an error is |
||
402 | //returned. If it can be admitted, it recalculates all necessary |
||
403 | //parameters for the contracts already present in the system anr |
||
404 | //returns zero. This is a potentially blocking operation; it returns |
||
405 | //when the system has either rejected the new contract, or admitted it |
||
406 | //and made it effective. |
||
407 | |||
408 | int |
||
409 | fsf_renegotiate_contract |
||
410 | (const fsf_contract_parameters_t *new_contract, |
||
411 | fsf_server_id_t server); |
||
412 | |||
413 | |||
414 | //fsf_request_contract_renegotiation: The operation enqueues a |
||
415 | //renegotiate operation for an existing server, and returns |
||
416 | //immediately. The renegotiate operation is performed asynchronously, |
||
417 | //as soon as it is practical; meanwhile the system operation will |
||
418 | //continue normally. When the renegotiation is made, if the on-line |
||
419 | //admission test is enabled it determines whether the contract can be |
||
420 | //admitted or not based on the current contracts established in the |
||
421 | //system. If it cannot be admitted, the old contract remains in |
||
422 | //effect. If it can be admitted, it recalculates all necessary |
||
423 | //parameters for the contracts already present in the system. When the |
||
424 | //operation is completed, notification is made to the caller, if |
||
425 | //requested, via a signal. The status of the operation (in progress, |
||
426 | //admitted, rejected) can be checked with the get_renegotiation_status |
||
427 | //operation. The argument sig_notify can be NULL_SIGNAL (no |
||
428 | //notification), or any posix signal; and in this case sig_value is to |
||
429 | //be sent with the signal. |
||
430 | |||
431 | int |
||
432 | fsf_request_contract_renegotiation |
||
433 | (const fsf_contract_parameters_t *new_contract, |
||
434 | fsf_server_id_t server, |
||
435 | int sig_notify, |
||
436 | union sigval sig_value); |
||
437 | |||
438 | |||
439 | //fsf_get_renegotiation_status: The operation reports on the status of |
||
440 | //the last renegotiation operation enqueued for the specified |
||
441 | //server. It is callable even after notification of the completion of |
||
442 | //such operation, if requested. |
||
443 | |||
444 | typedef enum {FSF_IN_PROGRESS, |
||
445 | FSF_REJECTED, |
||
446 | FSF_ADMITTED} |
||
447 | fsf_renegotiation_status_t; |
||
448 | |||
449 | int |
||
450 | fsf_get_renegotiation_status |
||
451 | (fsf_server_id_t server, |
||
452 | fsf_renegotiation_status_t *renegotiation_status); |
||
453 | |||
454 | |||
455 | |||
456 | //////////////////////////////////////////////////// |
||
457 | // SCHEDULING BOUNDED WORKLOADS |
||
458 | //////////////////////////////////////////////////// |
||
459 | |||
460 | //fsf_schedule_timed_job: This operation is invoked by threads |
||
461 | //associated with bounded workload servers to indicate that a job has |
||
462 | //been completed (and that the scheduler may reassign the unused |
||
463 | //capacity of the current job to other servers). It is also invoked |
||
464 | //when the first job of such threads has to be scheduled. The system |
||
465 | //will make the server's budget zero for the remainder of the server's |
||
466 | //period, and will not replenish the budget until the specified |
||
467 | //absolute time. At that time, all pending budget replenishments (if |
||
468 | //any) are made effective. Once the server has a positive budget and |
||
469 | //the scheduler schedules the calling thread again, the call returns |
||
470 | //and at that time, except for those parameters equal to NULL |
||
471 | //pointers, the system reports the current period and budget for the |
||
472 | //current job, whether the deadline of the previous job was missed or |
||
473 | //not, and whether the budget of the previous job was overrun or not. |
||
474 | |||
475 | //In a system with hierarchical scheduling, since this call makes the |
||
476 | //budget zero, the other threads in the same server are not run. As |
||
477 | //mentioned abobe, only when the call finishes the budget may be |
||
478 | //replenished. |
||
479 | |||
480 | int |
||
481 | fsf_schedule_timed_job |
||
482 | (const struct timespec *abs_time, |
||
483 | struct timespec *next_budget, |
||
484 | struct timespec *next_period, |
||
485 | bool *was_deadline_missed, |
||
486 | bool *was_budget_overran); |
||
487 | |||
488 | |||
489 | //fsf_schedule_triggered_job: This operation is invoked by threads |
||
490 | //associated with bounded workload servers to indicate that a job has |
||
491 | //been completed (and that the scheduler may reassign the unused |
||
492 | //capacity of the current job to other servers). It is also invoked |
||
493 | //when the first job of such threads has to be scheduled. If the |
||
494 | //specified synchronization object has events queued, one of them is |
||
495 | //dequeued; otherwise the server will wait upon the specified |
||
496 | //synchronization object, the server's budget will be made zero for |
||
497 | //the remainder of the server's period, and the implementation will |
||
498 | //not replenish the budget until the specified synchronization object |
||
499 | //is signalled. At that time, all pending budget replenishments (if |
||
500 | //any) are made effective. Once the server has a positive budget and |
||
501 | //the scheduler schedules the calling thread again, the call returns |
||
502 | //and at that time, except for those parameters equal to NULL |
||
503 | //pointers, the system reports the current period and budget for the |
||
504 | //current job, whether the deadline of the previous job was missed or |
||
505 | //not, and whether the budget of the previous job was overrun or not. |
||
506 | |||
507 | //In a system with hierarchical scheduling, since this call makes the |
||
508 | //budget zero, the other threads in the same server are not run. As |
||
509 | //mentioned above, only when the call finishes the budget may be |
||
510 | //replenished. |
||
511 | |||
512 | int |
||
513 | fsf_schedule_triggered_job |
||
514 | (fsf_synch_obj_handle_t synch_handle, |
||
515 | struct timespec *next_budget, |
||
516 | struct timespec *next_period, |
||
517 | bool *was_deadline_missed, |
||
518 | bool *was_budget_overran); |
||
519 | |||
520 | |||
521 | // fsf_timed_schedule_triggered_job. This call is the same as |
||
522 | // fsf_schedule_triggered_job, but with an absolute timeout. The |
||
523 | // timed_out argument, indicates whether the function returned because |
||
524 | // of a timeout or not |
||
525 | |||
526 | int |
||
527 | fsf_timed_schedule_triggered_job |
||
528 | (fsf_synch_obj_handle_t synch_handle, |
||
529 | const struct timespec *abs_timeout, |
||
530 | bool *timed_out, |
||
531 | struct timespec *next_budget, |
||
532 | struct timespec *next_period, |
||
533 | bool *was_deadline_missed, |
||
534 | bool *was_budget_overran); |
||
535 | |||
536 | |||
537 | //////////////////////////////////////////////////// |
||
538 | // OBTAINING INFORMATION FROM THE SCHEDULER |
||
539 | //////////////////////////////////////////////////// |
||
540 | |||
541 | //fsf_is_admission_test_enabled: Returns true if the system is |
||
542 | //configured with the on-line admission test enabled, or false |
||
543 | //otherwise. |
||
544 | |||
545 | bool |
||
546 | fsf_is_admission_test_enabled(); |
||
547 | |||
548 | |||
549 | //fsf_get_cpu_time: This function stores the current execution time |
||
550 | //spent by the threads bound to the specified server in the variable |
||
551 | //pointed to by cpu_time. |
||
552 | |||
553 | int |
||
554 | fsf_get_cpu_time |
||
555 | (fsf_server_id_t server, |
||
556 | struct timespec *cpu_time); |
||
557 | |||
558 | |||
559 | //fsf_get_remaining_budget: This function stores in the variable |
||
560 | //pointed to by budget the remaining execution-time budget associated |
||
561 | //with the specified server |
||
562 | |||
563 | int |
||
564 | fsf_get_remaining_budget |
||
565 | (fsf_server_id_t server, |
||
566 | struct timespec *budget); |
||
567 | |||
568 | |||
569 | //fsf_get_budget_and_period: This function stores in the variables |
||
570 | //pointed to by budget and period, the execution-time budget and the |
||
571 | //period respectively associated with the specified server. If any of |
||
572 | //these pointers is NULL, the corresponding information is not stored. |
||
573 | |||
574 | int |
||
575 | fsf_get_budget_and_period |
||
576 | (fsf_server_id_t server, |
||
577 | struct timespec *budget, |
||
578 | struct timespec *period); |
||
579 | |||
580 | |||
581 | |||
582 | ///////////////////////////////////////////////////////////////////// |
||
583 | // SERVICE THREAD TUNING |
||
584 | ///////////////////////////////////////////////////////////////////// |
||
585 | |||
586 | //fsf_set_service_thread_data: This function allows the application to |
||
587 | //change the period and budget of the service thread that makes the |
||
588 | //negotiations. Increasing the utilization of this thread makes the |
||
589 | //negotiations faster, but introduces additional load in the system |
||
590 | //that may decrease the bandwidth available for the servers. For this |
||
591 | //call, the system will make a schedulability analysis to determine if |
||
592 | //the new situation is acceptable or not. This is reported back in the |
||
593 | //variable pointed to by accepted. If the new service thread data is |
||
594 | //accepted, the system will reassign budgets and periods to the |
||
595 | //servers according to the new bandwidth available, in the same way as |
||
596 | //it does for a regular contract negotiation. |
||
597 | |||
598 | //When its budget is exhausted, the service thread may run in the |
||
599 | //background |
||
600 | |||
601 | //The service thread starts with a default budget and period that are |
||
602 | //configurable |
||
603 | |||
604 | //Implementation dependency: in the fixed priority implementtaion of |
||
605 | //fsf, the default priority is lower than the priority of any server, |
||
606 | //but higher than the background. According to the |
||
607 | //implementation-dependent module the priority is adjustable by means |
||
608 | //of a function that changes its preemption level |
||
609 | |||
610 | int |
||
611 | fsf_set_service_thread_data |
||
612 | (const struct timespec *budget, |
||
613 | const struct timespec *period, |
||
614 | bool *accepted); |
||
615 | |||
616 | |||
617 | //fsf_get_service_thread_data: this function returns in the variables |
||
618 | //pointed by budget and period, respectively, the current budget and |
||
619 | //period of the service thread. |
||
620 | |||
621 | int |
||
622 | fsf_get_service_thread_data |
||
623 | (struct timespec *budget, |
||
624 | struct timespec *period); |
||
625 | |||
626 | |||
627 | //////////////////////////////////////////////////////////////////////// |
||
628 | // BACKGROUND MANAGEMENT |
||
629 | //////////////////////////////////////////////////////////////////////// |
||
630 | |||
631 | //A round-robin background scheduling policy is available for those |
||
632 | //threads that do not have real-time requirements. Because some of |
||
633 | //these threads may require sharing information with other threads run |
||
634 | //by regular servers, special background contracts may be created for |
||
635 | //specifying the synchronization requirements. |
||
636 | |||
637 | //The way of specifying a background contract is by setting budget_min |
||
638 | //= period_max = 0. Negotiation may fail if the contract uses |
||
639 | //shared_objects. If the contract has no shared_objects the returned |
||
640 | //server id represents the background and may be used to bind more |
||
641 | //than one thread. If the contract has shared objects a server is |
||
642 | //created to keep track of them, but the associated threads are |
||
643 | //executed in the background, together with the other background |
||
644 | //threads |
||
645 | |||
646 | |||
647 | //////////////////////////////////////////////////////////////////////// |
||
648 | // CHANGE OF MODE: GROUPS OF CONTRACTS |
||
649 | //////////////////////////////////////////////////////////////////////// |
||
650 | |||
651 | //Data types |
||
652 | |||
653 | //list of contracts to negotiate |
||
654 | typedef struct { |
||
655 | int size; |
||
656 | fsf_contract_parameters_t* contracts[FSF_MAX_N_SERVERS]; |
||
657 | } fsf_contracts_group_t; |
||
658 | |||
659 | //list of servers to cancel |
||
660 | typedef struct { |
||
661 | int size; |
||
662 | fsf_server_id_t servers[FSF_MAX_N_SERVERS]; |
||
663 | } fsf_servers_group_t; |
||
664 | |||
665 | |||
666 | //fsf_negotiate_group: This operation analizes the schedulability of |
||
667 | //the context that results from negitiating the contracts specified in |
||
668 | //the contracts_up list and cacelling the contracts referenced by the |
||
669 | //servers_down list. If the overall negotiation is successful, a new |
||
670 | //server will be created for each of the elements of the contracts_up |
||
671 | //group, the servers in servers_down will be cancelled, the list of |
||
672 | //new server ids will be returned in the variable pointed to by |
||
673 | //servers_up, and the variable pointed to by accepted will be made |
||
674 | //true. Otherwise, this variable will be made false, and no other |
||
675 | //effect will take place. The function returns the corresponding error |
||
676 | //code if any of the contracts is not correct or any of the server ids |
||
677 | //is not valid. |
||
678 | |||
679 | int |
||
680 | fsf_negotiate_group |
||
681 | (const fsf_contracts_group_t *contracts_up, |
||
682 | const fsf_servers_group_t *severs_down, |
||
683 | fsf_servers_group_t *severs_up, |
||
684 | bool *accepted); |
||
685 | |||
686 | |||
687 | ////////////////////////////////////////////////////////////////////// |
||
688 | // INITIALIZATION SERVICES |
||
689 | ////////////////////////////////////////////////////////////////////// |
||
690 | |||
691 | // We cannot call any fsf functions before fsf_init. After calling |
||
692 | // fsf_init, the main will be executing in the background. Then, it |
||
693 | // can do the negotiations, create the threads and, if needed, |
||
694 | // activate them via some user-specified synchronization mechanism. It |
||
695 | // may also create a contract for itself. The second time this |
||
696 | // function is called it fails. |
||
697 | |||
698 | int fsf_init(); |
||
699 | |||
700 | |||
701 | #endif // _FSF_CORE_H_ |