]> rtime.felk.cvut.cz Git - frescor/frsh-include.git/blob - frsh_core.h
Add frsh_get_local_cpu_id()
[frescor/frsh-include.git] / frsh_core.h
1 // -----------------------------------------------------------------------
2 //  Copyright (C) 2006 - 2009 FRESCOR consortium partners:
3 //
4 //    Universidad de Cantabria,              SPAIN
5 //    University of York,                    UK
6 //    Scuola Superiore Sant'Anna,            ITALY
7 //    Kaiserslautern University,             GERMANY
8 //    Univ. Politécnica  Valencia,           SPAIN
9 //    Czech Technical University in Prague,  CZECH REPUBLIC
10 //    ENEA                                   SWEDEN
11 //    Thales Communication S.A.              FRANCE
12 //    Visual Tools S.A.                      SPAIN
13 //    Rapita Systems Ltd                     UK
14 //    Evidence                               ITALY
15 //
16 //    See http://www.frescor.org for a link to partners' websites
17 //
18 //           FRESCOR project (FP6/2005/IST/5-034026) is funded
19 //        in part by the European Union Sixth Framework Programme
20 //        The European Union is not liable of any use that may be
21 //        made of this code.
22 //
23 //
24 //  based on previous work (FSF) done in the FIRST project
25 //
26 //   Copyright (C) 2005  Mälardalen University, SWEDEN
27 //                       Scuola Superiore S.Anna, ITALY
28 //                       Universidad de Cantabria, SPAIN
29 //                       University of York, UK
30 //
31 //   FSF API web pages: http://marte.unican.es/fsf/docs
32 //                      http://shark.sssup.it/contrib/first/docs/
33 //
34 //   This file is part of FRSH (FRescor ScHeduler)
35 //
36 //  FRSH is free software; you can redistribute it and/or modify it
37 //  under terms of the GNU General Public License as published by the
38 //  Free Software Foundation; either version 2, or (at your option) any
39 //  later version.  FRSH is distributed in the hope that it will be
40 //  useful, but WITHOUT ANY WARRANTY; without even the implied warranty
41 //  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
42 //  General Public License for more details. You should have received a
43 //  copy of the GNU General Public License along with FRSH; see file
44 //  COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
45 //  Cambridge, MA 02139, USA.
46 //
47 //  As a special exception, including FRSH header files in a file,
48 //  instantiating FRSH generics or templates, or linking other files
49 //  with FRSH objects to produce an executable application, does not
50 //  by itself cause the resulting executable application to be covered
51 //  by the GNU General Public License. This exception does not
52 //  however invalidate any other reasons why the executable file might be
53 //  covered by the GNU Public License.
54 // -----------------------------------------------------------------------
55
56 //==============================================
57 //  ******** *******    ********  **      **
58 //  **///// /**////**  **//////  /**     /**
59 //  **      /**   /** /**        /**     /**
60 //  ******* /*******  /********* /**********
61 //  **////  /**///**  ////////** /**//////**
62 //  **      /**  //**        /** /**     /**
63 //  **      /**   //** ********  /**     /**
64 //  //       //     // ////////   //      //
65 //
66 // FRSH(FRescor ScHeduler), pronounced "fresh"
67 //==============================================
68
69 #ifndef _FRSH_CORE_H_
70 #define _FRSH_CORE_H_
71
72
73 /**
74  * @file frsh_core.h
75  **/
76
77
78 #include <time.h>
79 #include <sys/types.h>
80
81 #include "frsh_core_types.h"
82 #include "frsh_spare_capacity.h"
83
84
85 FRSH_CPP_BEGIN_DECLS
86
87 /**
88  * @defgroup core Core module
89  *
90  * This module includes the basic functions and services that are
91  * provided by any FRSH implementation. This module includes basic type
92  * definitions, and functions to
93  *
94  * - create a contract and initialize it
95  * - set/get the basic parameters of a contract
96  * - negotiate a service contract, obtaining a vres id
97  * - create and bind threads to vres
98  * - create/destroy a synchronization object
99  * - manage bounded workloads
100  *
101  **/
102
103
104 //////////////////////////////////////////////////////////////////////
105 //           INITIALIZATION SERVICES
106 //////////////////////////////////////////////////////////////////////
107
108 /**
109  * @defgroup initialization Initialization services
110  * @ingroup core
111  *
112  * These functions need to be called before doing any FRSH operation
113  * (including contract initialization).
114  *
115  * @{
116  **/
117
118
119 /**
120  * frsh_init()
121  *
122  * We cannot call any frsh functions before frsh_init. After calling
123  * frsh_init, the main will be executing in the background. Then, it
124  * can do the negotiations and create new threads if needed.  The
125  * second time this function is called it fails.
126  *
127  * @return 0 if no error. \n
128  *  FRSH_ERR_SYSTEM_ALREADY_INITIALIZED : if the function has already
129  *                                        been called before\n
130  *  .
131  *  It may also return any of the errors that may be returned by the
132  *  underlying operating system primitives required to perform the
133  *  FRSH system start up
134  *
135  **/
136 int frsh_init();
137
138 /*@}*/
139
140
141 /////////////////////////////////////////////////////////////
142 //                       CONTRACT PARAMETERS
143 /////////////////////////////////////////////////////////////
144 /**
145  * @defgroup contract Contract Creation and Initialization.
146  * @ingroup core
147  *
148  * These functions are used to create and initialize a contract, and
149  * set its parameters.
150  *
151  * @{
152  **/
153
154
155 /**
156  * frsh_contract_init()
157  *
158  * The operation receives a pointer to a contract object
159  * and initializes it, setting it to the default values.
160  *
161  * The default values are:
162  *
163  * - resource_id               => 0
164  * - ressource_type            => FRSH_CRT_PROCESSOR
165  * - contract_label               => ""
166  * - budget_min                => {0,0};
167  * - period_max                => {0,0};
168  * - budget_max                => {0,0};
169  * - period_min                => {0,0};
170  * - workload                  => FRSH_WT_INDETERMINATE
171  * - d_equals_t                => true
172  * - contract_type             => FRSH_CT_REGULAR;
173  * - deadline                  => {0,0};
174  * - budget_overrun_signal => 0;  (signal number)
175  * - budget_overrun_siginfo  => {0, NULL};
176  * - deadline_miss_signal  => 0;  (signal number)
177  * - deadline_miss_siginfo   => {0, NULL};
178  *
179  * - granularity               => DEFAULT_GRANULARITY;
180  * - utilization_set;          => size = 0
181  * - quality                   => DEFAULT_QUALITY;    (range 0..100)
182  * - importance                => DEFAULT_IMPORTANCE; (range 1..5)
183  * - preemption_level          => 0; (range 1..2**32-1)
184  * - critical_sections;        => size = 0
185  *
186  * - sched_policy              => DEFAULT_SCHED_POLICY (FRSH_NONE)
187  *
188  * @param     contract the pointer to the contract variable.
189  *
190  * @return 0 if no error \n
191  *     FRSH_ERR_BAD_ARGUMENT :  contract is NULL
192  *
193  **/
194 int frsh_contract_init(frsh_contract_t *contract);
195
196
197 /**
198  * frsh_contract_destroy()
199  *
200  * The operation deallocates all memory which might be allocated for
201  * the contract.
202  *
203  * @param contract the pointer to the contract variable.
204  **/
205 void frsh_contract_destroy(frsh_contract_t *contract);
206
207
208 /**
209  * frsh_contract_set_basic_params()
210  *
211  * The operation updates the specified contract parameters object by
212  * setting its budget, period, workload and type to the specified
213  * input parameters. (Note: the workload is a basic parameter because
214  * bounded tasks are triggered by the scheduler (see the
215  * frsh_timed_wait() and frsh_synchobj_wait* operations), while
216  * indeterminate tasks are not; therefore, their programming model is
217  * quite different).
218  *
219  * @param contract     the pointer to the contract object
220  * @param[in] budget_min   the minimum budget for the contract
221  * @param[in] period_max   the maximum period for the contract
222  * @param[in] workload     the kind of workload (can be FRSH_WT_BOUNDED,
223  *                            FRSH_WT_INDETERMINATE or FRSH_OVERHEAD)
224  * @param[in] contract_type can be FRSH_CT_REGULAR,
225  *                                 FRSH_CT_BACKGROUND, FRSH_CT_DUMMY.
226  *
227  * @return 0 if no error \n
228  *    FRSH_ERR_BAD_ARGUMENT :  if any of the pointers is NULL
229  *    or if only one of the time values is 0, and also if the
230  *    workload or the contract type values are unknown in the
231  *    enumerations.
232  **/
233 int frsh_contract_set_basic_params
234   (frsh_contract_t *contract,
235    const frsh_rel_time_t      *budget_min,
236    const frsh_rel_time_t      *period_max,
237    const frsh_workload_t      workload,
238    const frsh_contract_type_t contract_type);
239
240 /**
241  * frsh_contract_get_basic_params()
242  *
243  * This operation obtains from the specified contract object its
244  * budget, period, and workload, and copies them to the places pointed
245  * to by the corresponding output parameters.
246  *
247  * @param[in] contract   the pointer to the contract object
248  * @param[out] budget_min pointer to preallocated space
249  * @param[out] period_max pointer to preallocated space
250  * @param[out] workload pointer to preallocated space
251  * @param[out] contract_type pointer to preallocated space
252  *
253  * @return   0 if no error \n
254  *       FRSH_ERR_BAD_ARGUMENT :  if one of the contract or
255  *                                    pointers is NULL.
256  *
257  **/
258 int frsh_contract_get_basic_params
259   (const frsh_contract_t *contract,
260    frsh_rel_time_t  *budget_min,
261    frsh_rel_time_t  *period_max,
262    frsh_workload_t   *workload,
263    frsh_contract_type_t *contract_type);
264
265 /**
266  * frsh_contract_set_resource_and_label()
267  *
268  * Specify resource_id and type, and the contract label. Otherwise
269  * default values will apply. If the contract label is too long it is truncated
270  *
271  * @return   0 if no error \n
272  *       FRSH_ERR_BAD_ARGUMENT :  if the contract pointer is NULL.
273  **/
274 int frsh_contract_set_resource_and_label
275   (frsh_contract_t *contract,
276    const frsh_resource_type_t resource_type,
277    const frsh_resource_id_t resource_id,
278    const char *contract_label);
279
280
281 /**
282  * frsh_contract_get_resource_and_label()
283  *
284  * Obtain the resource_id and type, and the contract label.
285  *
286  * @return   0 if no error \n
287  *       FRSH_ERR_BAD_ARGUMENT :  if the contract or the contract_label
288  *                                 pointer is NULL.
289  **/
290 int frsh_contract_get_resource_and_label
291   (const frsh_contract_t *contract,
292    frsh_resource_type_t *resource_type,
293    frsh_resource_id_t *resource_id,
294    char *contract_label);
295
296
297 /**
298  * frsh_contract_set_timing_reqs()
299  *
300  * The operation updates the specified contract object, specifying
301  * additional time-related requirements.
302  *
303  * @param  contract The pointer to the contract object
304  *
305  * @param [in] d_equals_t It is a boolean value, set to true (1) if
306  *                        we want to specify a deadline different from
307  *                        the period  for the contract.
308  * @param [in] deadline  If the previous parameter is set to true,
309  *                       this parameter is ignored (the contract value
310  *                       will be NULL_DEADLINE internally). Otherwise, it
311  *                       contains the desired deadline value.
312  *
313  * @return  0 if successful\n
314  *     FRSH_ERR_BAD_ARGUMENT :  if contract is NULL \b or \n
315  *      (d_equals_t is true and  deadline is not FRSH_NULL_DEADLINE) \b or \n
316  *      (budget_overrun_signal is not a valid signal)  \b or \n
317  *      (deadline_miss_signal is not a valid signal) \b or \n
318  *      (d_equals_t is false but (deadline is FRSH_NULL_DEADLINE or its value
319  *                                is grater than the contract's maximum period))
320  *
321  **/
322 int frsh_contract_set_timing_reqs
323   (frsh_contract_t *contract,
324    const bool                   d_equals_t,
325    const frsh_rel_time_t        *deadline);
326
327 /**
328  * frsh_contract_get_timing_reqs()
329  *
330  * The operation obtains the corresponding input parameters from the
331  * specified contract object. If d_equals_t is true, the deadline will
332  * be set to FRSH_NULL_DEADLINE.
333  *
334  * @return 0 if no error \n
335  *   FRSH_ERR_BAD_ARGUMENT :  if contract is NULL
336  *
337  **/
338 int frsh_contract_get_timing_reqs
339   (const frsh_contract_t *contract,
340    bool                    *d_equals_t,
341    frsh_rel_time_t         *deadline);
342
343
344 /*@}*/
345
346 //////////////////////////////////////////////////////////////////
347 //                 SYNCHRONIZATION OBJECTS
348 //////////////////////////////////////////////////////////////////
349 /**
350  * @defgroup synch  Synchronization objects
351  * @ingroup core
352  *
353  * Synchronisation objects provide an alternative to timers for
354  * bounded-workload vres to signal the end of their current job and
355  * return their remaining budget to FRSH.
356  *
357  * Instead of asking to be reactivated based on an absolute time, they
358  * queue themselves in a synchronisation object and will wait there
359  * until another vres (bounded-workload or indeterminate-workload)
360  * wakes them up with a signal call the earliest at the beginning of
361  * the next period.
362  *
363  * Indeterminate-workload vres cannot queue themselves here because
364  * they don't have any budget to return.  However they can signal on
365  * the objects to activate a waiting workload vres.
366  *
367  * For classical signal/wait synchronisation paradigms the application
368  * must use whatever mechanism the underlying OS provides.
369  *
370  * In the future we may add a broadcast operation that would signal a
371  * group of synchronization objects. We have not included a broadcast
372  * service in this version because it can be easily created by the
373  * user by signalling individual synchronization objects inside a
374  * loop.
375  *
376  * Notice that for synchronization objects there is no naming service
377  * like in shared objects because tasks that use synchronization are
378  * not developed independently, as they are closely coupled.
379  *
380  * @{
381  **/
382
383
384 /**
385  * frsh_synchobj_create()
386  *
387  * This operation creates and initializes a synchronization object
388  * variable managed by the scheduler, and returns a handle to it in
389  * the variable pointed to by synch_handle.
390  *
391  * @param[out]  synch_handle pointer to the variable that will contain
392  *                  the handle to the newly created synchronization object
393  *
394  * @return      0 if the operation is succesful
395  *              FRSH_ERR_TOO_MANY_SYNCH_OBJS if the number of synchronization
396  *              objects in the system has already exceeded the maximum
397  *
398  *   FRSH_ERR_TOO_MANY_SYNCH_OBJS : if the number of synchronization
399  *      objects in the system has already exceeded the maximum\n
400  *   .
401  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not
402  *      scheduled under FRSH\n
403  *   .
404  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not running
405  *
406  **/
407 int frsh_synchobj_create
408     (frsh_synchobj_handle_t *synch_handle);
409
410
411 /**
412  * frsh_synchobj_destroy()
413  *
414  * This operation destroys the synchronization object (created by a
415  * previous call to frsh_synchobj_create) that is referenced by the
416  * synch_handle variable. After calling this operation, the
417  * synch_handle variable can not be used until it is initialized again
418  * by a call to frsh_synchobj_create.
419  *
420  * @param synch_handle the handle to the synchronization object
421  *            to be destroyed
422  *
423  * @return 0 if no error \n
424  *   FRSH_ERR_BAD_ARGUMENT :  if synch_handle is 0\n
425  *   FRSH_ERR_INVALID_SYNCH_OBJ_HANDLE if the handle is not valid\n
426  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not
427  *                            scheduled under FRSH \n
428  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
429  *                            running
430  *
431  * @sa frsh_synchobj_create
432  **/
433 int frsh_synchobj_destroy
434     (const frsh_synchobj_handle_t synchobj_handle);
435
436 /**
437  * frsh_synchobj_wait()
438  *
439  * This operation is invoked by threads associated with bounded
440  * workload vres to indicate that a job has been completed (and
441  * that the scheduler may reassign the unused capacity of the current
442  * job to other vres).
443  *
444  * As a difference with frsh_timed_wait(), here the vres
445  * specifies to be awakened by the arrival of a signal operation
446  * instead of at a precise point of time.
447  *
448  * This function can also be called to schedule the first job of a
449  * recently created vres and make it start when a signal operation
450  * has been sent from another thread.
451  *
452  * The vres' budget will be made zero for the remainder of the vres'
453  * period, and FRSH will not replenish it until an event has been
454  * notified to the synchronisation object by another vres.
455  *
456  * It can happen that the synchronisation object has notification
457  * events queued from the past, in this case one of the events is
458  * dequeued immediately and the vres won't have to wait for another
459  * one.
460  *
461  * At the time of reception of a notification event (wether in the
462  * future or in the past), all pending budget replenishments (if any)
463  * are made effective. Once the vres has a positive budget and the
464  * scheduler schedules the calling thread again, the call returns and
465  * the vres continues executing.
466  *
467  * If the synchronisation object is destroyed while the vres was
468  * waiting on it, the vres will be awaken and the function will
469  * return with a code FRSH_ERR_INVALID_SYNCH_OBJ_HANDLE
470  *
471  * Except for those parameters equal to NULL pointers, the system
472  * reports the current period and budget for the current job, it informs
473  * if the deadline of the previous job was missed or not, and whether the
474  * budget of the previous job was overrun or not.
475  *
476  * In a system with hierarchical scheduling, since this call makes the
477  * budget of the current period zero, the other threads in the same
478  * vres are not run. As mentioned above, only when the call finishes
479  * the budget may be replenished.
480  *
481  * @param synch_handle   Synchronisation object upon which the vres
482  *                       will be waiting.
483  * @param next_budget[out]  Upon return of this function, the variable
484  *                          pointed by this function will be equal to
485  *                                      the current vres budget. If this parameter is
486  *                                      set to NULL, no action is taken
487  * @param next_period[out]  The vres period upon return (ignored if NULL).
488  * @param was_deadline_missed Upon return whether the deadline was
489  *                           missed in the previous period.
490  * @param was_budget_overran
491  *
492  *
493  * @return 0 if success \n
494  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
495  *               running \n
496  *   FRSH_ERR_INTERNAL_ERROR : erroneous binding or malfunction of the FRSH
497  *     main scheduler \n
498  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not scheduled
499  *     under FRSH \n
500  *   FRSH_ERR_NOT_BOUND : if the calling thread does not have a valid
501  *            vres bound to it \n
502  *   FRSH_ERR_BAD_ARGUMENT : if synch_handle is 0 \n
503  *   FRSH_ERR_INVALID_SYNCH_OBJ_HANDLE if the synch_handle is not
504  *          valid or was destroyed while the vres was waiting on it. \n
505  *   FRSH_ERR_VRES_WORKLOAD_NOT_COMPATIBLE: if the kind of workload of the vres
506  *     is not FRSH_BOUNDED
507  *
508  **/
509 int frsh_synchobj_wait
510   (const frsh_synchobj_handle_t  synch_handle,
511    frsh_rel_time_t               *next_budget,
512    frsh_rel_time_t               *next_period,
513    bool                          *was_deadline_missed,
514    bool                          *was_budget_overran);
515
516
517 /**
518  * frsh_synchobj_wait_with_timeout()
519  *
520  * This call is the same as frsh_synchobj_wait() but with an extra
521  * absolute timeout. The timed_out argument, indicates whether the
522  * function returned because of the expiration of the timeout or not.
523  *
524  * @return 0 if no error \n
525  *   FRSH_ERR_INVALID_SYNCH_OBJ_HANDLE if the synch_handle is not
526  *        valid \n
527  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
528  *        running \n
529  *   FRSH_ERR_INTERNAL_ERROR : erroneous binding or malfunction of the FRSH
530  *     main scheduler \n
531  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not scheduled
532  *     under FRSH \n
533  *   FRSH_ERR_NOT_BOUND : if the calling thread does not have a valid
534  *     vres bound to it \n
535  *   FRSH_ERR_BAD_ARGUMENT :  if the synch_handle given is not valid or the
536  *     abs_timeout argument is NULL or its value is in the past\n
537  *   FRSH_ERR_VRES_WORKLOAD_NOT_COMPATIBLE: if the kind of workload of the vres
538  *     is not FRSH_BOUNDED
539  *
540  **/
541 int frsh_synchobj_wait_with_timeout
542   (const frsh_synchobj_handle_t  synch_handle,
543    const frsh_abs_time_t         *abs_timeout,
544    bool                          *timed_out,
545    frsh_rel_time_t               *next_budget,
546    frsh_rel_time_t               *next_period,
547    bool                          *was_deadline_missed,
548    bool                          *was_budget_overran);
549
550 /**
551  * frsh_synchobj_signal()
552  *
553  * This function sends a notification event to the synchronization object
554  * specified as parameter. If there is at least one vres waiting on
555  * the synchronization object, it is awaken. If more than one vres
556  * are waiting, just one of them is awaken. However, which one is
557  * awaken is implementation dependent. If no vres is waiting on the
558  * synchronization object, the notification event is queued.
559  *
560  * @param [in] synch_handle the handle of the synchronization object to
561  *                 notify.
562  *
563  * @return 0 if no error \n
564  *    FRSH_ERR_BAD_ARGUMENT :  if synch_handle is 0 \n
565  *    FRSH_ERR_INVALID_SYNCH_OBJ_HANDLE if the handle is not valid \n
566  *    FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not
567  *            scheduled under FRSH \n
568  *    FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
569  *            running \n
570  *    FRSH_ERR_TOO_MANY_EVENTS_IN_SYNCH_OBJ : if the number of events stored
571  *            in the synchronization object reaches the maximum defined in the
572  *            configuration parameter header file
573  *
574  * @sa frsh_synchobj_wait, frsh_synchobj_wait_with_timeout
575  **/
576 int frsh_synchobj_signal
577     (const frsh_synchobj_handle_t synch_handle);
578
579 /**
580  * frsh_timed_wait()
581  *
582  * This operation is invoked by threads associated with bounded
583  * workload vres to indicate that a job has been completed (and
584  * that the scheduler may reassign the unused capacity of the current
585  * job to other vres). It is also invoked when the first job of
586  * such threads has to be scheduled.
587  *
588  * As an effect, the system will make the current vres's budget zero
589  * for the remainder of the vres's period, and will not replenish
590  * the budget until the specified absolute time.  At that time, all
591  * pending budget replenishments (if any) are made effective. Once the
592  * vres has a positive budget and the scheduler schedules the
593  * calling thread again, the call returns and at that time, except for
594  * those parameters equal to NULL pointers, the system reports the
595  * current period and budget for the current job, whether the deadline
596  * of the previous job was missed or not, and whether the budget of
597  * the previous job was overrun or not.
598  *
599  * In a system with hierarchical scheduling, since this call makes the
600  * budget zero, the other threads in the same vres are not run. As
601  * mentioned abobe, only when the call finishes the budget may be
602  * replenished.
603  *
604  * @param [in] abs_time     absolute time at which the budget will be
605  *                          replenished
606  *
607  * @param [out] next_budget upon return of this function, the variable
608  *                          pointed by this function will be equal to
609  *                          the current vres budget. If this parameter is
610  *                          set to NULL, no action is taken.
611  *
612  * @param [out] next_period upon return of this function, the variable
613  *                          pointed by this function will be equal to
614  *                          the current vres period. If this parameter is
615  *                          set to NULL, no action is taken.
616  *
617  * @param [out] was_deadline_missed upon return of this function, the
618  *                          variable pointed by this function will be
619  *                          equal to true if the previous vres deadline
620  *                          was missed, to false otherwise. If this
621  *                          parameter is set to NULL, no action is
622  *                          taken.
623  *
624  * @param [out] was_budget_overrun upon return of this function, the
625  *                          variable pointed by this function will be
626  *                          equal to true if the previous vres budget was
627  *                          overrun, to false otherwise. If this
628  *                          parameter is set to NULL, no action is
629  *                          taken.
630  *
631  * @return  0 if the operation is successful \n
632  *   FRSH_ERR_TIME_SPEC_IN_THE_PAST if the absolute time specification
633  *            is in the past. \n
634  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong
635  *             or not running \n
636  *   FRSH_ERR_INTERNAL_ERROR : erroneous binding or malfunction of the FRSH
637  *                                    main scheduler \n
638  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling
639  *                      thread is not scheduled under FRSH \n
640  *   FRSH_ERR_NOT_BOUND : if the calling thread does not have a valid
641  *     vres bound to it \n
642  *   FRSH_ERR_BAD_ARGUMENT :  if abs_time is NULL \n
643  *   FRSH_ERR_VRES_WORKLOAD_NOT_COMPATIBLE: if the kind of workload of the vres
644  *     is not FRSH_BOUNDED
645  *
646  *
647  * @sa frsh_synchobj_wait, frsh_synchobj_wait_with_timeout
648  **/
649 int frsh_timed_wait
650   (const frsh_abs_time_t *abs_time,
651    frsh_rel_time_t       *next_budget,
652    frsh_rel_time_t       *next_period,
653    bool                  *was_deadline_missed,
654    bool                  *was_budget_overran);
655
656
657
658 /**
659  * frsh_vresperiod_wait()
660  *
661  * Suspend the calling thread until the start of the specified virtual
662  * resource period of a vres_id, for a synchronized workload.
663  *
664  * Virtual resource periods are numbered. The number of the current
665  * period can be obtained through the frsh_vres_get_period_number()
666  * operation.
667  **/
668 int frsh_vresperiod_wait(unsigned long period_num,
669                          frsh_rel_time_t       *next_budget,
670                          frsh_rel_time_t       *next_period,
671                          bool                  *was_deadline_missed,
672                          bool                  *was_budget_overran);
673
674
675 /**
676  * frsh_vres_get_period()
677  *
678  * Return the current period number, for a virtual resource of
679  * synchronized workload.
680  **/
681 int frsh_vres_get_period_number
682    (const frsh_vres_id_t vres,
683     long *period_num);
684
685
686
687
688 /*@}*/
689
690 ///////////////////////////////////////////////////////////////////
691 //                 CONTRACT NEGOCIATION OPERATIONS
692 ///////////////////////////////////////////////////////////////////
693
694 /**
695  * @defgroup negotiate Negotiate contract functions
696  * @ingroup core
697  *
698  * The following functions are used to negotiate contracts and thus
699  * creating vres which are the execution image of a contract.
700  * Besides, these functions allow to assign and unassign threads to
701  * vres.
702  *
703  * In the case of more than one thread per vres please refer to the
704  * hierarchical module.
705  *
706  * @{
707  **/
708
709
710
711 /**
712  * frsh_contract_negotiate()
713  *
714  * The operation negotiates a contract and if accepted it will return
715  * a vres_id.  It will also check that the given contract_label is unique
716  * within the node.
717  *
718  * If the on-line admission test is enabled, it determines whether the
719  * contract can be admitted or not based on the current contracts
720  * established in the system. Then it creates the vres and
721  * recalculates all necessary parameters for the contracts already
722  * present in the system.
723  *
724  * This is a potentially blocking operation, it returns when the
725  * system has either rejected the contract, or admitted it and made it
726  * effective. No thread is bound to the newly created vres, which
727  * will be idle until a thread is bound to it via frsh_thread_bind()
728  * or frsh_thread_create_and_bind().
729  *
730  * This operation can only be executed by threads that are already
731  * bound to an active vres and therefore are being scheduled by the
732  * frsh scheduler.
733  *
734  * @return 0 if successful \n
735  *   FRSH_ERR_CONTRACT_REJECTED:  The contract is not accepted.\n
736  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
737  *                running \n
738  *   FRSH_ERR_INTERNAL_ERROR : erroneous binding or malfunction of the FRSH
739  *     main scheduler \n
740  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not scheduled
741  *     under FRSH scheduler \n
742  *   FRSH_ERR_BAD_ARGUMENT :  if the contract or vres arguments are NULL \n
743  *   FRSH_ERR_TOO_MANY_VRES : if there is no space for more vres
744  *     (the maximum number of them is already reached) \n
745  *   FRSH_ERR_CONTRACT_LABEL_ALREADY_EXISTS : contract_label is not unique.
746  *
747  **/
748 int frsh_contract_negotiate
749   (const frsh_contract_t *contract,
750    frsh_vres_id_t        *vres);
751
752 /**
753  * frsh_thread_create_and_bind()
754  *
755  * This operation creates a thread and binds it to an existing vres.
756  *
757  * This is the preferred way to add threads to the application because
758  * we make sure that the thread won't become unbound.
759  *
760  * The vres must not have any thread binded to it.  If you want to
761  * bind more than one thread to the vres you must use the
762  * hierarchical module.
763  *
764  * The frsh_thread_attr_t parameter is overwritten as necessary to
765  * introduce the adequate scheduling policy and priority,  according
766  * to the preemption level given in the contract and the
767  * frsh_priority_map() function defined by the user.
768  *
769  * @param[in] vres_id       vres with which the thread will be bound.
770  * @param[out] thread         frsh_thread_id returned by the system.
771  * @param attr         pthread_attr taken and maybe corrected
772  *                                by the system.  Ignored if NULL
773  * @param[in] thread_code     Thread function (void func(void *) )
774  *                                that will constitute the main of the
775  *                                thread.
776  * @param[in] arg             Argument for data to be passed at the
777  *                            thread. Set to NUL if you don't want
778  *                            to do anything like this.
779  *
780  * @return  0 if successful \n
781  *   FRSH_ERR_BAD_ARGUMENT : if the contract or vres arguments are
782  *               NULL \n
783  *   FRSH_ERR_CONTRACT_REJECTED : if the contract is rejected. \n
784  *   .
785  *   It may also return all the errors that may be returned by the
786  *     fosa_thread_create() function call
787  *
788  **/
789 int frsh_thread_create_and_bind
790   (const frsh_vres_id_t vres,
791    frsh_thread_id_t     *thread,
792    frsh_thread_attr_t   *attr,
793    frsh_thread_code_t   thread_code,
794    void                 *arg);
795
796
797 /**
798  * frsh_thread_create_in_background()
799  *
800  * This function creates a "background contract" that does not need to
801  * be negotiated, creates a threads and binds to the new vres.
802  *
803  * This method is suggested as a way to initate components and
804  * plugins.  The event that triggers the component activation should
805  * arrive to an application thread that could use this function to
806  * create a thread used in its initialisation.
807  *
808  * The attribute parameter is overwritten as necessary to introduce
809  * the adequate scheduling policy and priority.
810  *
811  * @param[in]  thread_code   Function to be executed by the new
812  *                           thread.
813  * @param[in]  thread_arg    General pointer that will be passed to
814  *                           the new thread as initialisation data.
815  * @param attr               Pthread attribute with thread params
816  * @param[in]  contract_label   Contract label for the new vres.
817  * @param[out] thread_id     Id of the new thread.
818  * @param[out] vres_id       vres_id of the new vres.
819  *
820  * @return 0 if successful \n
821  *   FRSH_ERR_BAD_ARGUMENT : Any problems with the argument \n
822  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is
823  *               not scheduled under FRSH \n
824  *   FRSH_ERR_CONTRACT_LABEL_ALREADY_EXISTS : contract_label is not unique \n
825  *   FRSH_ERR_TOO_MANY_VRES : if there is no space for more vres
826  *     (the maximum number of them is already reached)
827  *
828  **/
829 int frsh_thread_create_in_background
830     (frsh_thread_code_t thread_code,
831      const void *thread_arg,
832      const char *contract_label,
833      frsh_thread_attr_t *attr,
834      frsh_thread_id_t *thread_id,
835      frsh_vres_id_t *vres_id);
836
837
838
839 /**
840  * frsh_thread_join_in_background()
841  *
842  * This function is aimed for external threads to join FRSH in the
843  * least disturbing possible mode.
844  *
845  * Upon calling this function by a thread which has been created
846  * natively in the OS, it joins the framework and gets inmediately
847  * bound to an on-the-fly generated background contract.
848  *
849  * In order to gain a higher priority then it can renegotiate a
850  * contract for its vres with the needed parameters.
851  *
852  * @param[in] resource_id:   Resource (CPU) in which the vres will
853  *                           be associated.
854  *
855  * @param[in] resource_type: Resource type (should be CPU) for the
856  *                           contract.
857  *
858  * @param[in] label:         Label to be added to the contract.
859  *
860  * @param[out] vres_id:      Resulting vres_id from the on-the-fly
861  *                           generated background contract.
862  *
863  * @return  0 if successful\n
864  *          FRSH_ERR_NOT_CONTRACTED_VRES if the thread is already
865  *          bound to a vres.
866  **/
867 int frsh_thread_join_in_background(frsh_resource_id_t resource_id,
868                                    frsh_resource_type_t resource_type,
869                                    const char *label,
870                                    frsh_vres_id_t *vres_id);
871
872
873
874 /**
875  * frsh_thread_bind()
876  *
877  * This operation associates a thread with a vres, which means that
878  * it starts consuming the vres's budget  and is executed according
879  * to the contract established for that vres. If the thread is
880  * already bound to another vres, it is effectively unbound from it
881  * and bound to the specified one.
882  *
883  * It fails if the vres's policy is different than FRSH_NONE, or if
884  * there is already a thread bound to this vres.  In order to bind
885  * more than one vres to the same thread you must use the
886  * hierarchical module.
887  *
888  * Implementation dependent issue: In order to allow the usage of
889  * application defined schedulers, the given thread must not have the
890  * scheduling policy SCHED_APP and at the same time be attached to an
891  * application scheduler different than the frsh scheduler.
892  *
893  * @return 0 if successful \n
894  *   FRSH_ERR_INTERNAL_ERROR : erroneous binding or malfunction of the FRSH
895  *     main scheduler \n
896  *   FRSH_ERR_UNKNOWN_APPSCHEDULED_THREAD : if the thread is attached to
897  *     an application defined scheduler different than the frsh
898  *     scheduler \n
899  *   FRSH_ERR_BAD_ARGUMENT : if the vres value does not complain with the
900  *     expected format or valid range or the given thread does not
901  *     exist \n
902  *   FRSH_ERR_NOT_CONTRACTED_VRES : if the referenced vres is not
903  *      valid \n
904  *   FRSH_ERR_VRES_WORKLOAD_NOT_COMPATIBLE: if the kind of workload
905  *     of the vres is FRSH_OVERHEAD \n
906  *   FRSH_ERR_ALREADY_BOUND : if the given vres has a thread already
907  *     bound
908  *
909  **/
910 int frsh_thread_bind
911   (const frsh_vres_id_t   vres,
912    const frsh_thread_id_t thread);
913
914
915 /**
916  * frsh_thread_unbind()
917  *
918  * This operation unbinds a thread from a vres.  Since threads with
919  * no vres associated are not allowed to execute, they remain in a
920  * dormant state until they are either eliminated or bound again.
921  *
922  * If the thread is inside a critical section the effects of this call
923  * are deferred until the critical section is ended
924  *
925  * Implementation dependent issue: in the implementation with an
926  * application scheduler, the thread is still attached to the frsh
927  * scheduler, but suspended.
928  *
929  * @return 0 if successful \n
930  *   FRSH_ERR_INTERNAL_ERROR : erroneous binding or malfunction of the FRSH
931  *     main scheduler \n
932  *   FRSH_ERR_BAD_ARGUMENT : if the given thread does not exist \n
933  *   FRSH_ERR_NOT_SCHEDULED_THREAD : if the given thread is not scheduled
934  *     under FRSH \n
935  *   FRSH_ERR_UNKNOWN_APPSCHEDULED_THREAD : if the thread is attached to
936  *     an application defined scheduler different than the frsh
937  *     scheduler \n
938  *   FRSH_ERR_NOT_BOUND : if the given thread does not have a valid
939  *     vres bound to it
940  **/
941 int frsh_thread_unbind(const frsh_thread_id_t thread);
942
943 /**
944  * frsh_vres_set_notification()
945  *
946  * This function setups notification signals for CPU vres. It is
947  * necessary to call this function before bounding the thread to the
948  * vres.
949  * 
950  * @param [in] budget_overrun_signal contains the number of the signal
951  *                that must be raised if the budget of the vres is
952  *                overrun by the thread.
953  *                If the value of this parameter is FRSH_NULL_SIGNAL, no signal will
954  *                be raised.
955  * @param [in] budget_overrun_siginfo contains the value that will be
956  *               passed to the signal "catcher" when the signal is raised.
957  *               This parameters is not used if the budget_overrun_signal
958  *               parameter is set to FRSH_NULL_SIGNAL.
959  * @param [in] deadline_miss_signal contains the number of the
960  *               signal that must be raised if the deadline of the
961  *               vres is missed. If the value of this parameter is
962  *               FRSH_NULL_SIGNAL, no signal is raised.
963  * @param [in] deadline_miss_siginfo contains the value that will be
964  *                passed to the signal "catcher" when the signal is
965  *                raised.  This parameter is not used if the
966  *                deadline_signal parameter is set to NULL_SIGNAL
967  **/
968 int frsh_vres_set_notification(
969         frsh_vres_id_t vres,
970         const frsh_signal_t          budget_overrun_signal,
971         const frsh_signal_info_t     budget_overrun_siginfo,
972         const frsh_signal_t          deadline_miss_signal,
973         const frsh_signal_info_t     deadline_miss_siginfo);
974
975 /**
976  * frsh_thread_get_vres_id()
977  *
978  * This operation stores the Id of the vres associated with the
979  * specified thread in the variable pointed to by vres. It returns
980  * an error if the thread does not exist, it is not under the control
981  * of the scheduling framework, or is not bound.
982  *
983  * @return 0 if no error \n
984  *   FRSH_ERR_NOT_SCHEDULED_THREAD : if the given thread is not scheduled
985  *     under FRSH \n
986  *   FRSH_ERR_NOT_BOUND : if the given thread does not have a valid
987  *     vres bound to it \n
988  *   FRSH_ERR_BAD_ARGUMENT : if the given thread does not exist or the
989  *     vres argument is NULL
990  *
991  **/
992 int frsh_thread_get_vres_id(const frsh_thread_id_t       thread,
993                     frsh_vres_id_t *vres_id);
994
995 /**
996  * frsh_vres_get_priority()
997  *
998  * This operation stores the priority currently associated
999  * with the specified vres in the variable pointed to by
1000  * priority. It returns an error if the vres_id is not recognised.
1001  *
1002  * @return 0 if no error \n
1003  *   FRSH_ERR_BAD_ARGUMENT :  if the contract argument is NULL or the value
1004  *     of the vres argument is not in range \n
1005  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not
1006  *     scheduled under FRSH \n
1007  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
1008  *        running \n
1009  *   FRSH_ERR_NOT_CONTRACTED_VRES: if the vres of the calling thread
1010  *     has been cancelled or it is not valid
1011  *
1012  **/
1013 int frsh_vres_get_priority
1014      (frsh_vres_id_t            vres_id,
1015       int *priority);
1016
1017 /**
1018  * frsh_vres_get_contract()
1019  *
1020  * This operation stores the contract parameters currently associated
1021  * with the specified vres in the variable pointed to by
1022  * contract. It returns an error if the vres_id is not recognised.
1023  *
1024  * @return 0 if no error \n
1025  *   FRSH_ERR_BAD_ARGUMENT :  if the contract argument is NULL or the value
1026  *     of the vres argument is not in range \n
1027  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not
1028  *     scheduled under FRSH \n
1029  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
1030  *        running \n
1031  *   FRSH_ERR_NOT_CONTRACTED_VRES: if the vres of the calling thread
1032  *     has been cancelled or it is not valid
1033  *
1034  **/
1035 int frsh_vres_get_contract
1036   (const frsh_vres_id_t vres,
1037     frsh_contract_t *contract);
1038
1039 /**
1040  * frsh_resource_get_vres_from_label()
1041  *
1042  * This operation retrieves the vres_id whose contract_label
1043  * corresponds to the parameter in the resource_id and resource_type
1044  * specified.
1045  *
1046  * The contract label must refer to a contract negotiated
1047  * in the same processing node in which the call is being
1048  * made. Otherwise an error is returned.
1049  *
1050  * @return 0 if no error \n
1051  *   FRSH_ERR_BAD_ARGUMENT :  if the contract argument is NULL or the
1052  *     contract_label is NULL \n
1053  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not
1054  *     scheduled under FRSH \n
1055  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
1056  *     running \n
1057  *   FRSH_ERR_CONTRACT_LABEL_UNKNOWN: if the contract_label is not known
1058  **/
1059 int frsh_resource_get_vres_from_label
1060   (const char *contract_label,
1061    const frsh_resource_type_t resource_type,
1062    const frsh_resource_id_t resource_id,
1063    frsh_vres_id_t *vres);
1064
1065
1066
1067 /**
1068  * frsh_contract_cancel()
1069  *
1070  * The operation eliminates the specified vres
1071  * and recalculates all necessary parameters for the contracts
1072  * remaining in the system. This is a potentially blocking operation;
1073  * it returns when the system has made the changes effective.
1074  *
1075  * Note that the thread is not eliminated.  We leave the application
1076  * the option to either freeze it for a later use or bind it to
1077  * another vres.
1078  *
1079  * @return 0 if successful \n
1080  *   FRSH_ERR_BAD_ARGUMENT :  if the value of vres is not in range \n
1081  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not
1082  *     scheduled under FRSH \n
1083  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
1084  *     running \n
1085  *   FRSH_ERR_NOT_CONTRACTED_VRES : if the vres of the calling thread
1086  *     has been cancelled or it is not valid
1087  *
1088  **/
1089 int frsh_contract_cancel (const frsh_vres_id_t vres);
1090
1091
1092 /**
1093  * frsh_contract_renegotiate_sync()
1094  *
1095  * The operation renegotiates a contract for an existing vres. If
1096  * the on-line admission test is enabled it determines whether the
1097  * contract can be admitted or not based on the current contracts
1098  * established in the system. If it cannot be admitted, the old
1099  * contract remains in effect and an error is returned. If it can be
1100  * admitted, it recalculates all necessary parameters for the
1101  * contracts already present in the system and returns zero. This is a
1102  * potentially blocking operation; it returns when the system has
1103  * either rejected the new contract, or admitted it and made it
1104  * effective.
1105  *
1106  *  @return 0 if successful \n
1107  *   FRSH_ERR_BAD_ARGUMENT :  if the new_contract argument is NULL or the
1108  *     value of the vres argument is not in range \n
1109  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not
1110  *     scheduled under FRSH \n
1111  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
1112  *     running \n
1113  *   FRSH_ERR_NOT_CONTRACTED_VRES : if the vres of the calling thread
1114  *     has been cancelled or it is not valid \n
1115  *   FRSH_ERR_CONTRACT_REJECTED : if the renegotiation fails
1116  *
1117  **/
1118 int frsh_contract_renegotiate_sync
1119   (const frsh_contract_t *new_contract,
1120    const frsh_vres_id_t vres);
1121
1122
1123 /**
1124  * frsh_contract_renegotiate_async()
1125  *
1126  * The operation enqueues a renegotiate operation for an existing
1127  * vres, and returns immediately. The renegotiate operation is
1128  * performed asynchronously, as soon as it is practical; meanwhile the
1129  * system operation will continue normally. When the renegotiation is
1130  * made, if the on-line admission test is enabled it determines
1131  * whether the contract can be admitted or not based on the current
1132  * contracts established in the system. If it cannot be admitted, the
1133  * old contract remains in effect. If it can be admitted, it
1134  * recalculates all necessary parameters for the contracts already
1135  * present in the system.
1136  *
1137  * When the operation is completed, notification is made to the
1138  * caller, if requested, via a signal. The status of the operation (in
1139  * progress, admitted, rejected) can be checked with the
1140  * frsh_vres_get_renegotiation_status() operation.  The argument
1141  * sig_notify can be FRSH_NULL_SIGNAL (no notification), or any FRSH
1142  * signal value and in this case signal_info is to be sent with the signal.
1143  *
1144  * @param[in] new_contract   New contract parameters for the new
1145  *                           situation if approved.
1146  * @param[in] vres           vres_id on which to do the renegotiation.
1147  * @param[in] signal_to_notify  Signal number to use to notify vres of
1148  *                           the negotiation result.  If
1149  *                           FRSH_NULL_SIGNAL,  no signal will be raised.
1150  * @param[in] signal_info:   Associated info that will come with the
1151  *                           signal.  This parameter will be ignored
1152  *                           if signal_to_notify == FRSH_NULL_SIGNAL.
1153  *
1154  * @return 0 if no error \n
1155  *   FRSH_ERR_BAD_ARGUMENT :  if the new_contract argument is NULL, the
1156  *     value of the vres argument is not in range or sig_notify is
1157  *     neither NULL nor a valid POSIX signal \n
1158  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not
1159  *     scheduled under FRSH \n
1160  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
1161  *     running \n
1162  *   FRSH_ERR_NOT_CONTRACTED_VRES : if the vres of the calling thread
1163  *     has been cancelled or it is not valid
1164  *
1165  **/
1166 int frsh_contract_renegotiate_async
1167   (const frsh_contract_t *new_contract,
1168    const frsh_vres_id_t vres,
1169    const frsh_signal_t                     signal_to_notify,
1170    const frsh_signal_info_t                signal_info);
1171
1172
1173 /**
1174  * frsh_vres_get_renegotiation_status()
1175  *
1176  * The operation reports on the status of the last renegotiation
1177  * operation enqueued for the specified vres. It is callable even
1178  * after notification of the completion of such operation, if
1179  * requested.
1180  *
1181  * If the vres is not and has not been involved in any of the
1182  * frsh_contract_renegotiate_async() or frsh_group_change_mode_async()
1183  * operations, the status returned is FRSH_RS_NOT_REQUESTED
1184  *
1185  * @return 0 if no error \n
1186  *   FRSH_ERR_BAD_ARGUMENT :  if the renegotiation_status argument is
1187  *     NULL or the value of the vres argument is not in range \n
1188  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not
1189  *     scheduled under FRSH \n
1190  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
1191  *     running \n
1192  *   FRSH_ERR_NOT_CONTRACTED_VRES : if the vres of the calling thread
1193  *     has been cancelled or it is not valid
1194  *
1195  **/
1196 int frsh_vres_get_renegotiation_status
1197   (const frsh_vres_id_t vres,
1198    frsh_renegotiation_status_t *renegotiation_status);
1199
1200 /*@}*/
1201
1202 ////////////////////////////////////////////////////////////////////////
1203 //           CHANGE OF MODE: GROUPS OF CONTRACTS
1204 ////////////////////////////////////////////////////////////////////////
1205 /**
1206  * @defgroup groupofcontracts Group of contracts
1207  * @ingroup core
1208  *
1209  * The following functions are used to negotiate atomically more than
1210  * one contract.  This allows to build complex applications by
1211  * splitting them in individual contracts that are negotiated
1212  * simultaneously and atomically.
1213  *
1214  * @{
1215  **/
1216
1217 /**
1218  * frsh_group_change_mode_sync()
1219  *
1220  * This function performs a set of negotiation operations which can
1221  * include: adding new contracts (neg), modifying existing vres (reneg)
1222  * or cancelling existing vres (cancel).
1223  *
1224  * If one of the group operations has a NULL value, unless it causes an
1225  * inconsistency the system will suppose that no operation of that
1226  * type (neg, reneg or cancel) should be done.
1227  *
1228  * The virtual resources resulting from negotiations of new contracts are
1229  * returned in the parameter 'new_vres' which must be provided by the user.
1230  *
1231  * If the on-line admission test is enabled, FRSH analizes the
1232  * schedulability of the context that would  result in the new
1233  * contract situation with removed, changed and added contracts.
1234  *
1235  * A successful return code will mean that all contracts have been
1236  * accepted  and all required operations (creation, cancellation or
1237  * update of vres) have been carried out to reach the new running
1238  * context.
1239  *
1240  * If any of the contracts is not accepted a corresponding error shall be
1241  * returned and no changes will be made to the previously running context.
1242  *
1243  * This call is a synchronous, potentially blocking operation.  It
1244  * returns when the system has rejected the contracts or accepted
1245  * and made them effective.
1246  *
1247  * @param[in] contracts_to_neg    List of new contracts to negotiate
1248  * @param[in] contracts_to_reneg  List of contracts to renegotiate
1249  * @param[in] vres_to_reneg       List of vres to renegotiate
1250  * @param[in] vres_to_cancel      List of vres to cancel
1251  * @param[out] new_vres           List of vres of new contracts.
1252  *
1253  * @return 0 if no error \n
1254  *    FRSH_ERR_BAD_ARGUMENT Invalid pointer or group identifier. \n
1255  *    FRSH_ERR_CONTRACT_LABEL_ALREADY_EXISTS contract_label not unique. \n
1256  *    FRSH_ERR_NOT_CONTRACTED_VRES: One of the provided vres_ids
1257  *       is not recognised. \n
1258  *    FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD The calling thread
1259  *       is not scheduled under FRSH. \n
1260  *    FRSH_ERR_INVALID_SCHEDULER_REPLY: The scheduler is wrong or
1261  *       not running. \n
1262  *    FRSH_ERR_INTERNAL_ERROR:  Erroneous binding or malfunction of
1263  *       FRSH main scheduler. \n
1264  *    FRSH_ERR_REJECTED_CONTRACT:  The negotiation of one of the
1265  *       proposed contracts has failed.
1266  **/
1267 int frsh_group_change_mode_sync
1268                             (const frsh_contracts_group_t *contracts_to_neg,
1269                              const frsh_contracts_group_t *contracts_to_reneg,
1270                              const frsh_vres_group_t      *vres_to_reneg,
1271                              const frsh_vres_group_t      *vres_to_cancel,
1272                              frsh_vres_group_t            *new_vres);
1273
1274 /**
1275  * frsh_group_change_mode_async()
1276  *
1277  * This is an asynchronous (non-blocking) version of the previous function,
1278  * frsh_group_change_mode_sync() and thus, it returns inmediately.
1279  *
1280  * The status of the change of mode and the identifiers for new virtual
1281  * resources must be requested with the function 'frsh_group_get_status'
1282  * by using the return parameter 'group'.
1283  *
1284  * As in the asynchronous renegotiations, when the operation is completed,
1285  * the user is notified with a signal so he can check the final result with
1286  * 'frsh_group_get_status'. In case that FRSH_NULL_SIGNAL is used, no
1287  * signal will be sent to the user.
1288  *
1289  * @param[in] contracts_to_neg    List of new contracts to negotiate
1290  * @param[in] contracts_to_reneg  List of contracts to renegotiate
1291  * @param[in] vres_to_reneg       List of vres to renegotiate
1292  * @param[in] vres_to_cancel      List of vres to cancel
1293  * @param[in] signal              Signal number to notify completion of
1294  *                                the change of mode. If FRSH_NULL_SIGNAL,
1295  *                                no signal will be raised.
1296  * @param[in] signal_info         Data associated to the signal
1297  * @param[out] group              The group identifier to get the status
1298  *
1299  * @return 0 if no error \n
1300  *    FRSH_ERR_BAD_ARGUMENT Invalid pointer, signal or group identifier. \n
1301  *    FRSH_ERR_CONTRACT_LABEL_ALREADY_EXISTS contract_label not unique. \n
1302  *    FRSH_ERR_NOT_CONTRACTED_VRES: One of the provided vres_ids
1303  *       is not recognised. \n
1304  *    FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD The calling thread
1305  *       is not scheduled under FRSH. \n
1306  *    FRSH_ERR_INVALID_SCHEDULER_REPLY: The scheduler is wrong or
1307  *       not running. \n
1308  *    FRSH_ERR_INTERNAL_ERROR:  Erroneous binding or malfunction of
1309  *       FRSH main scheduler.
1310  **/
1311 int frsh_group_change_mode_async
1312                             (const frsh_contracts_group_t *contracts_to_neg,
1313                              const frsh_contracts_group_t *contracts_to_reneg,
1314                              const frsh_vres_group_t      *vres_to_reneg,
1315                              const frsh_vres_group_t      *vres_to_cancel,
1316                              const frsh_signal_t          signal,
1317                              const frsh_signal_info_t     signal_info,
1318                              frsh_group_id_t              *group);
1319
1320 /**
1321  * frsh_group_get_status()
1322  *
1323  * This function is similar to 'frsh_vres_get_renegotiation_status' but it
1324  * is intented for group negotiations (changes of mode).
1325  *
1326  * The operation reports on the status of the last negotiation
1327  * operation enqueued for the specified group identifier.
1328  *
1329  * The status value can be one of the following values:
1330  *
1331  *    - FRSH_RS_IN_PROGRESS: the change of mode is in progress
1332  *    - FRSH_RS_REJECTED: the change of mode was not accepted
1333  *    - FRSH_RS_ADMITTED: the change of mode was accepted
1334  *    - FRSH_RS_NOT_REQUESTED: no change of mode has been requested yet
1335  *
1336  * When status returns 'FRSH_RS_ADMITTED', the array 'new_vres' contains
1337  * the values for the new virtual resources (if there was any).
1338  *
1339  * This function frees the group identifier when status returns something
1340  * different than FRSH_RS_IN_PROGRESS so further calls to this function may
1341  * return inconsistent values.
1342  *
1343  * @param[in]  group     The group identifier
1344  * @param[out] status    The status of the change of mode
1345  * @param[out] new_vres  List of vres for the negotiation of new contracts.
1346  *
1347  * @return 0 if no error \n
1348  *    FRSH_ERR_BAD_ARGUMENT Invalid pointer, signal or group identifier. \n
1349  *    FRSH_ERR_CONTRACT_LABEL_ALREADY_EXISTS contract_label not unique. \n
1350  *    FRSH_ERR_NOT_CONTRACTED_VRES: One of the provided vres_ids
1351  *       is not recognised. \n
1352  *    FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD The calling thread
1353  *       is not scheduled under FRSH. \n
1354  *    FRSH_ERR_INVALID_SCHEDULER_REPLY: The scheduler is wrong or
1355  *       not running. \n
1356  *    FRSH_ERR_INTERNAL_ERROR:  Erroneous binding or malfunction of
1357  *       FRSH main scheduler.
1358  **/
1359 int frsh_group_get_status(const frsh_group_id_t       group,
1360                           frsh_renegotiation_status_t *status,
1361                           frsh_vres_group_t           *new_vres);
1362
1363
1364 /*@}*/
1365
1366
1367 ////////////////////////////////////////////////////
1368 //           OBTAINING INFORMATION FROM THE SCHEDULER
1369 ////////////////////////////////////////////////////
1370
1371 /**
1372  * @defgroup getschedinfo Obtaining information from the scheduler
1373  *
1374  * @ingroup core
1375  *
1376  * The following functions are used to obtain available budget and
1377  * resource usage in the system.  They can be used to adapt the
1378  * execution of threads according to the load of the system.
1379  *
1380  * @{
1381  **/
1382
1383
1384 /**
1385  * frsh_config_is_admission_test_enabled()
1386  *
1387  * Returns true if the system is
1388  * configured with the on-line admission test enabled, or false
1389  * otherwise.  This situation can only be changed at compile time.
1390  **/
1391 bool frsh_config_is_admission_test_enabled();
1392
1393 /**
1394  * frsh_vres_get_usage()
1395  *
1396  * This function stores the current execution time spent by the
1397  * threads bound to the specified vres in the variable pointed to by
1398  * cpu_time.
1399  *
1400  * @return 0 if successful \n
1401  *   FRSH_ERR_BAD_ARGUMENT : if the value of the vres argument is not in range or
1402  *     cpu_time is NULL \n
1403  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not
1404  *     scheduled under FRSH \n
1405  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
1406  *     running \n
1407  *   FRSH_ERR_NOT_CONTRACTED_VRESR : if the vres of the calling thread
1408  *     has been cancelled or it is not valid
1409  *
1410  **/
1411 int frsh_vres_get_usage
1412    (const frsh_vres_id_t vres,
1413     frsh_rel_time_t *spent);
1414
1415
1416 /**
1417  * frsh_vres_get_job_usage()
1418  *
1419  * Get the execution time of the current job of the specified virtual
1420  * resource for a bounded or synchronized workload.
1421  **/
1422 int frsh_vres_get_job_usage
1423     (const frsh_vres_id_t vres,
1424      frsh_rel_time_t *spent);
1425
1426
1427 /**
1428  * frsh_vres_get_remaining_budget()
1429  *
1430  * This function stores in the variable pointed to by budget the
1431  * remaining execution-time budget associated with the specified
1432  * vres.
1433  *
1434  *  @return 0 if successful \n
1435  *   FRSH_ERR_BAD_ARGUMENT : if the value of the vres argument is not in range or
1436  *     budget is NULL \n
1437  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not
1438  *     scheduled under FRSH \n
1439  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
1440  *     running \n
1441  *   FRSH_ERR_NOT_CONTRACTED_VRES : if the vres of the calling thread
1442  *     has been cancelled or it is not valid
1443  *
1444  **/
1445 int frsh_vres_get_remaining_budget
1446    (const frsh_vres_id_t vres,
1447     frsh_rel_time_t *budget);
1448
1449
1450 /**
1451  * frsh_vres_get_budget_and_period()
1452  *
1453  * This function stores in the variables
1454  * pointed to by budget and period, the execution-time budget and the
1455  * period respectively associated with the specified vres. If any of
1456  * these pointers is NULL, the corresponding information is not stored.
1457  *
1458  * @return 0 if successful \n
1459  *   FRSH_ERR_BAD_ARGUMENT : if the value of the vres argument is not in range,
1460  *     or budget and period are both NULL \n
1461  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not
1462  *     scheduled under FRSH \n
1463  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
1464  *     running \n
1465  *   FRSH_ERR_NOT_CONTRACTED_VRES : if the vres of the calling thread
1466  *     has been cancelled or it is not valid
1467  *
1468  **/
1469 int frsh_vres_get_budget_and_period
1470    (const frsh_vres_id_t vres,
1471     frsh_rel_time_t *budget,
1472     frsh_rel_time_t *period);
1473
1474 /*@}*/
1475
1476 /////////////////////////////////////////////////////////////////////
1477 //           SERVICE THREAD TUNING
1478 /////////////////////////////////////////////////////////////////////
1479 /**
1480  * @defgroup servthtuning Service thread tuning
1481  *
1482  * @ingroup core
1483  *
1484  * The following functions are used to obtain available budget and
1485  * resource usage in the system.  They can be used to adapt the
1486  * execution of threads to the load of the system.
1487  *
1488  * @{
1489  **/
1490
1491 /**
1492  * frsh_service_thread_set_data()
1493  *
1494  * This function allows the application to change the period and
1495  * budget of the service thread that makes the
1496  * negotiations. Increasing the utilization of this thread makes the
1497  * negotiations faster, but introduces additional load in the system
1498  * that may decrease the bandwidth available for the vres. For this
1499  * call, the system will make a schedulability analysis to determine
1500  * if the new situation is acceptable or not. This is reported back in
1501  * the variable pointed to by accepted. If the new service thread data
1502  * is accepted, the system will reassign budgets and periods to the
1503  * vres according to the new bandwidth available, in the same way
1504  * as it does for a regular contract negotiation.
1505  *
1506  * When its budget is exhausted, the service thread may run in the
1507  * background
1508  *
1509  * The service thread starts with a default budget and period that are
1510  * configurable
1511  *
1512  * Implementation dependency: in the fixed priority implementtaion of
1513  * frsh, the default priority is lower than the priority of any vres,
1514  * but higher than the background. According to the
1515  * implementation-dependent module the priority is adjustable by means
1516  * of a function that changes its preemption level
1517  *
1518  * @return 0 if successful \n
1519  *   FRSH_ERR_BAD_ARGUMENT : if any of the pointer arguments is NULL or
1520  *     the budget value is greater than the period value \n
1521  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not
1522  *     scheduled under FRSH \n
1523  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
1524  *     running \n
1525  *   FRSH_ERR_NOT_CONTRACTED_VRES : if the vres of the calling thread
1526  *     has been cancelled or it is not valid
1527  *
1528  **/
1529 int frsh_service_thread_set_data (const frsh_rel_time_t *budget,
1530                                   const frsh_rel_time_t *period,
1531                                   bool                  *accepted);
1532
1533 /**
1534  * frsh_service_thread_get_data()
1535  *
1536  * this function returns in the variables pointed by budget and
1537  * period, respectively, the current budget and period of the service
1538  * thread.
1539  *
1540  * @return 0 if successful \n
1541  *   FRSH_ERR_BAD_ARGUMENT : if any of the pointer arguments is NULL \n
1542  *   FRSH_ERR_NOT_SCHEDULED_CALLING_THREAD : if the calling thread is not
1543  *     scheduled under FRSH \n
1544  *   FRSH_ERR_INVALID_SCHEDULER_REPLY : the scheduler is wrong or not
1545  *     running \n
1546  *   FRSH_ERR_NOT_CONTRACTED_VRES : if the vres of the calling thread
1547  *     has been cancelled or it is not valid
1548  *
1549  **/
1550 int frsh_service_thread_get_data
1551    (frsh_rel_time_t *budget,
1552     frsh_rel_time_t *period);
1553
1554
1555 /*@}*/
1556
1557
1558 ////////////////////////////////////////////////////////////////////////
1559 //           BACKGROUND MANAGEMENT
1560 ////////////////////////////////////////////////////////////////////////
1561
1562 //A round-robin background scheduling policy is available for those
1563 //threads that do not have real-time requirements. Because some of
1564 //these threads may require sharing information with other threads run
1565 //by regular vres.  Special background contracts may be created for
1566 //specifying the synchronization requirements.
1567
1568 //The way of specifying a background contract is by setting
1569 //contract_type to FRSH_CT_BACKGROUND. Negotiation may fail if the contract uses
1570 //shared_objects. If the contract has no shared_objects the returned
1571 //vres id represents the background and may be used to bind more
1572 //than one thread. If the contract has shared objects a vres is
1573 //created to keep track of them, but the associated threads are
1574 //executed in the background, together with the other background
1575 //threads
1576
1577
1578 ////////////////////////////////////////////////////////////////////////
1579 //           OTHER
1580 ////////////////////////////////////////////////////////////////////////
1581
1582 /**
1583  * Returns resource id of local CPU.
1584  *
1585  * The ID is determined from environment variable FRSH_CPU_ID or, if
1586  * that is not defined, the compile time default (defined in
1587  * config.target/omk).
1588  */
1589 frsh_resource_id_t frsh_get_local_cpu_id(void);
1590
1591 FRSH_CPP_END_DECLS
1592
1593 #endif // _FRSH_CORE_H_