1 //----------------------------------------------------------------------
2 // Copyright (C) 2006 - 2007 by the FRESCOR consortium:
4 // Universidad de Cantabria, SPAIN
5 // University of York, UK
6 // Scuola Superiore Sant'Anna, ITALY
7 // Kaiserslautern University, GERMANY
8 // Univ. Politecnica Valencia, SPAIN
9 // Czech Technical University in Prague, CZECH REPUBLIC
11 // Thales Communication S.A. FRANCE
12 // Visual Tools S.A. SPAIN
13 // Rapita Systems Ltd UK
16 // See http://www.frescor.org
18 // The 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
24 // based on previous work (FSF) done in the FIRST project
26 // Copyright (C) 2005 Mälardalen University, SWEDEN
27 // Scuola Superiore S.Anna, ITALY
28 // Universidad de Cantabria, SPAIN
29 // University of York, UK
31 // This file is part of FOSA (Frsh Operating System Abstraction)
33 // FOSA is free software; you can redistribute it and/or modify it
34 // under terms of the GNU General Public License as published by the
35 // Free Software Foundation; either version 2, or (at your option) any
36 // later version. FOSA is distributed in the hope that it will be
37 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
38 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39 // General Public License for more details. You should have received a
40 // copy of the GNU General Public License along with FOSA; see file
41 // COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
42 // Cambridge, MA 02139, USA.
44 // As a special exception, including FOSA header files in a file,
45 // instantiating FOSA generics or templates, or linking other files
46 // with FOSA objects to produce an executable application, does not
47 // by itself cause the resulting executable application to be covered
48 // by the GNU General Public License. This exception does not
49 // however invalidate any other reasons why the executable file might be
50 // covered by the GNU Public License.
51 // -----------------------------------------------------------------------
52 //fosa_app_def_sched.h
53 //==============================================
54 // ******** ****** ******** **********
55 // **///// /** ** **////// /** /**
56 // ** /** ** /** /** /**
57 // ******* /** ** /********* /**********
58 // **//// /** ** ////////** /**//////**
59 // ** /** ** /** /** /**
60 // ** /** ** ******** /** /**
61 // // /******/ //////// // //
63 // FOSA(Frescor Operating System Adaptation layer)
64 //================================================
65 // 26-Jun-07 SANGORRIN: comment scheduler mutex because signal_set can only be
66 // set from the scheduler itself (don't delete because it might be useful in
69 // 25-Jun-07 SANGORRIN: when posix_appsched_execute_actions had an error code
70 // was wrong. Now we clear actions before (and added destroy operation!), then
71 // execute scheduler op and then go back to main loop (when error it continued
72 // executing the rest of actions)
74 // 10-Jul-07 SANGORRIN: in the new_thread callback we need to accept the thread
75 // before suspend or activate it.
76 // -----------------------------------------------------------------------
78 #include "fosa_app_def_sched.h"
79 #include "fosa_configuration_parameters.h"
80 #include "fosa_threads_and_signals.h"
81 #include "frsh_error.h"
82 #include "frsh_fosa.h"
89 #include <sys/marte_sched_events_codes.h>
91 #include <misc/error_checks.h>
93 // Full error checking option
94 // --------------------------
95 // Uncomment the following definition if full error checking is desired
96 // Beware that this option will introduce overhead in each context switch
98 #define FULL_ERROR_CHECKING
100 /********************************
101 * Application-defined scheduling
102 ********************************/
105 * We make the following ASSUMPTIONS:
107 * - The ADS always executes in the user memory space, so we don't
108 * need to manage the memory space translation.
110 * - Only one application scheduler exists, so we don't need a
116 * Data structures for the scheduler thread
119 // data structure that is passed to the scheduler thread
120 struct scheduler_thread_data {
121 fosa_ads_scheduler_ops_t scheduler_ops; // entry points
122 size_t scheduler_data_size; // size of scheduler data
123 void * scheduler_data; // pointer to scheduler data
124 void * init_args; // pointer to init args
125 size_t init_args_size; // size of init args
126 sigset_t sch_signal_set; // set of signals used by the
128 // pthread_mutex_t sch_mutex; // mutex used to share info with
130 pthread_key_t clock_key; // key to thread-specific data where
131 // a clock id is stored
132 pthread_key_t msg_key; // key to thread-specific data with
133 // a pointer to the messages for
134 // explicit invoke operations
137 // data structure used in the explicit call with data operation
138 struct explicit_call_info {
146 static struct scheduler_thread_data schedthreaddata;
147 static pthread_t scheduler_thread_id;
150 * Code of application-defined thread. The current version of MaRTE OS
151 * requires a thread to perform the scheduler actions.
152 * In the future it is expected that this thread will not be necessary.
154 void * scheduler_thread_code(void *arg) {
155 fosa_ads_actions_t sched_actions;
156 struct posix_appsched_event event;
157 struct scheduler_thread_data *sch_thread_data=
158 (struct scheduler_thread_data *) arg;
159 void * scheduler_data = sch_thread_data->scheduler_data;
160 posix_appsched_eventset_t event_set;
161 struct timespec current_time;
162 struct explicit_call_info *call_info;
166 // set the clock to be used by the scheduler
167 CHK(posix_appschedattr_setclock(FOSA_CLOCK_REALTIME));
169 // set the timeouts to be used in the scheduler to be absolute
170 CHK(posix_appschedattr_setflags (POSIX_APPSCHED_ABSTIMEOUT));
172 // set the mask of events to mask all events except for those
173 // corresponding to non-null entry points
174 CHK(posix_appsched_fillset(&event_set));
176 if (sch_thread_data->scheduler_ops.new_thread!=NULL) {
177 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_NEW));
180 if (sch_thread_data->scheduler_ops.thread_terminate!=NULL) {
181 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_TERMINATE));
184 if (sch_thread_data->scheduler_ops.thread_ready!=NULL) {
185 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_READY));
188 if (sch_thread_data->scheduler_ops.thread_block!=NULL) {
189 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_BLOCK));
191 // change_sched_param_thread
192 if (sch_thread_data->scheduler_ops.change_sched_param_thread!=NULL) {
193 CHK(posix_appsched_delset(&event_set, POSIX_APPSCHED_CHANGE_SCHED_PARAM));
195 // explicit_call_with_data
196 if (sch_thread_data->scheduler_ops.explicit_call_with_data!=NULL) {
197 CHK(posix_appsched_delset(&event_set, POSIX_APPSCHED_EXPLICIT_CALL));
199 // notification_for_thread
200 if (sch_thread_data->scheduler_ops.notification_for_thread!=NULL) {
201 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_TASK_NOTIFICATION));
204 if (sch_thread_data->scheduler_ops.timeout!=NULL) {
205 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_TIMEOUT));
208 if (sch_thread_data->scheduler_ops.signal!=NULL) {
209 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_SIGNAL));
211 // set the event mask
212 CHK(posix_appschedattr_seteventmask(&event_set));
214 // invoke the init entry point
215 sch_thread_data->scheduler_ops.init(scheduler_data,
216 sch_thread_data->init_args);
218 // clear the scheduling actions data structure
219 CHK(posix_appsched_actions_init(&(sched_actions.actions)));
220 sched_actions.timeout_ptr=NULL;
221 sched_actions.rejected=false;
222 sched_actions.activated=false;
223 sched_actions.suspended=false;
225 // lock the scheduler mutex
226 // CHK(pthread_mutex_lock(&(sch_thread_data->sch_mutex)));
228 // main scheduler loop
231 // NOTE: Put here code shared with app to be protected with the mutex
233 // unlock the scheduler mutex before waiting
234 // CHK(pthread_mutex_unlock(&(sch_thread_data->sch_mutex)));
236 // execute pending scheduling actions and wait for next event
237 err=posix_appsched_execute_actions
238 (&(sched_actions.actions),&(sch_thread_data->sch_signal_set),
239 sched_actions.timeout_ptr,¤t_time,&event);
241 // clear the scheduling actions data structure
242 CHK(posix_appsched_actions_destroy (&(sched_actions.actions)));
243 CHK(posix_appsched_actions_init(&(sched_actions.actions)));
244 sched_actions.timeout_ptr=NULL;
245 sched_actions.rejected=false;
246 sched_actions.activated=false;
247 sched_actions.suspended=false;
249 // lock the scheduler mutex to perform scheduler operations
250 // in mutual exclusion
251 // CHK(pthread_mutex_lock(&(sch_thread_data->sch_mutex)));
254 // determine which kind of event has arrived, and invoke appropriate
256 switch (event.event_code) {
257 case POSIX_APPSCHED_NEW:
258 sch_thread_data->scheduler_ops.new_thread
263 if (!sched_actions.rejected) {
264 // create a memory area for the explicit messages
265 call_info=(struct explicit_call_info *)
266 malloc(sizeof(struct explicit_call_info));
267 if (call_info==NULL) {
268 CHK(posix_appsched_actions_addreject
269 (&(sched_actions.actions),event.thread));
271 // clear actions, we need to accept the thread first
272 CHK(posix_appsched_actions_destroy (&(sched_actions.actions)));
273 CHK(posix_appsched_actions_init(&(sched_actions.actions)));
275 CHK(posix_appsched_actions_addaccept
276 (&(sched_actions.actions),event.thread));
277 // store the memory area in thread-specific data
278 CHK(pthread_setspecific_for
279 (schedthreaddata.msg_key,event.thread,call_info));
280 // and activate or suspend the thread
281 if (sched_actions.suspended) {
282 CHK(posix_appsched_actions_addsuspend
283 (&(sched_actions.actions),event.thread));
285 CHK(posix_appsched_actions_addactivate
286 (&(sched_actions.actions),event.thread));
291 case POSIX_APPSCHED_TERMINATE:
292 sch_thread_data->scheduler_ops.thread_terminate
298 case POSIX_APPSCHED_READY:
299 sch_thread_data->scheduler_ops.thread_ready
304 // activate the thread unless suspended or already activated
305 if (!sched_actions.suspended && !sched_actions.activated) {
306 CHK(posix_appsched_actions_addactivate
307 (&(sched_actions.actions),event.thread));
310 case POSIX_APPSCHED_BLOCK:
311 sch_thread_data->scheduler_ops.thread_block
317 case POSIX_APPSCHED_CHANGE_SCHED_PARAM:
318 sch_thread_data->scheduler_ops.change_sched_param_thread
324 //case POSIX_APPSCHED_EXPLICIT_CALL_WITH_DATA:
325 //sch_thread_data->scheduler_ops.explicit_call_with_data
328 // event.event_info.info,event.info_size,
329 // &reply, &reply_size,
332 case POSIX_APPSCHED_EXPLICIT_CALL:
333 CHK(pthread_getspecific_from
334 (schedthreaddata.msg_key,event.thread,(void **)(&call_info)));
335 sch_thread_data->scheduler_ops.explicit_call_with_data
339 call_info->info_size,
340 call_info->reply_ptr,
341 &(call_info->reply_size),
344 // activate the thread unless suspended or already activated
345 if (!sched_actions.suspended && !sched_actions.activated) {
346 CHK(posix_appsched_actions_addactivate
347 (&(sched_actions.actions),event.thread));
350 case POSIX_APPSCHED_TASK_NOTIFICATION:
351 clk=(clockid_t) pthread_getspecific(sch_thread_data->clock_key);
352 sch_thread_data->scheduler_ops.notification_for_thread
358 // t.b.d. check if state of thread is suspended by default
360 case POSIX_APPSCHED_TIMEOUT:
361 sch_thread_data->scheduler_ops.timeout
366 case POSIX_APPSCHED_SIGNAL:
367 sch_thread_data->scheduler_ops.signal
369 event.event_info.siginfo.si_signo,
370 *((frsh_signal_info_t *)(&(event.event_info.siginfo.si_value))),
371 // the above casting construct is used to overcome the compiler
372 // restriction that does not allow casts between unions
377 ASSERT_INFO(true,"Unexpected scheduling event received in scheduler");
378 } // end switch on event code
379 } else if (err==EINVAL) {
380 sch_thread_data->scheduler_ops.appsched_error
381 (scheduler_data, event.thread,
382 FOSA_ADS_THREAD_NOT_ATTACHED, &sched_actions);
383 } else if (err==ESRCH) {
384 sch_thread_data->scheduler_ops.appsched_error
385 (scheduler_data, event.thread,
386 FOSA_ADS_INVALID_ACTION, &sched_actions);
388 } // end of main scheduler loop
393 * fosa_ads_scheduler_create()
395 * Create the application defined scheduler
397 * The application defined scheduler is created with the primitive
398 * operations specified in the object pointed to by scheduler_ops.
400 * The clock used to read the time immediately before the invocation
401 * of each primitive operation, to be reported to the scheduler via
402 * the current_time parameter of each primitive operation is the
403 * FOSA_CLOCK_REALTIME clock.
405 * The scheduler_data_size parameter is used to request that a memory
406 * area of this size must be created and reserved for the scheduler to
407 * store its state. A pointer to this area is passed to the scheduler
408 * operations in the sched_data parameter.
410 * Parameter init_arg points to an area that contains configuration
411 * information for the scheduler. The function creates a memory area
412 * of init_arg_size bytes and copies into it the area pointed by
413 * arg. A pointer to this new created area will be passed to the
414 * primitive operation init() in its arg parameter.
416 * Returns 0 if successful; otherwise it returns an error code:
417 * EINVAL: The value of scheduler_ops was invalid
418 * EAGAIN: The system lacks enough resources to create the scheduler
420 * Alternatively, in case of error the implementation is allowed to
421 * notify it to the system console and then terminate the FRSH
422 * implementation and dependant applications
424 * The fosa_ads_scheduler_create function must be called before any
425 * other function in this header file
427 int fosa_ads_scheduler_create
428 (const fosa_ads_scheduler_ops_t * scheduler_ops,
429 size_t scheduler_data_size,
431 size_t init_args_size)
434 // pthread_mutexattr_t mattr;
436 struct sched_param param;
438 #ifdef FULL_ERROR_CHECKING
439 // check for NULL scheduler operations
440 if (scheduler_ops==NULL) {
443 #endif // end if FULL_ERROR_CHECKING
445 // copy arguments in scheduler data
446 schedthreaddata.scheduler_ops=*scheduler_ops;
447 schedthreaddata.scheduler_data_size=scheduler_data_size;
448 schedthreaddata.init_args_size=init_args_size;
450 // create scheduler memory area
451 schedthreaddata.scheduler_data=malloc(scheduler_data_size);
452 if (schedthreaddata.scheduler_data==NULL) {
456 // create init args memory area and copy the init args
457 schedthreaddata.init_args=malloc(init_args_size);
458 if (schedthreaddata.init_args==NULL) {
461 memcpy(schedthreaddata.init_args,init_args,init_args_size);
463 // initialize the set of signals used by the scheduler to none
464 CHKE(sigemptyset(&(schedthreaddata.sch_signal_set)));
466 // calculate the priority
467 param.sched_priority=sched_get_priority_max(SCHED_FIFO)-
468 FOSA_ADS_SCHEDULER_PRIO_DIFF;
470 // initialize the mutex used to share data with the scheduler
471 // CHK(pthread_mutexattr_init(&mattr));
472 // we use the priority protect protocol
473 // CHK(pthread_mutexattr_setprotocol(&mattr,PTHREAD_PRIO_PROTECT));
474 // set priority ceiling
475 // CHK(pthread_mutexattr_setprioceiling(&mattr,param.sched_priority));
477 // CHK(pthread_mutex_init(&(schedthreaddata.sch_mutex),&mattr));
478 // CHK(pthread_mutexattr_destroy(&mattr));
480 // create the thread-specific data key for the clock id
481 CHK(pthread_key_create(&schedthreaddata.clock_key,NULL));
483 // create the thread-specific data key for the message pointers
484 CHK(pthread_key_create(&schedthreaddata.msg_key,NULL));
486 // set the attributes for the scheduler thread
487 err=pthread_attr_init(&attr);
491 CHK(pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED));
492 CHK(pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED));
493 CHK(pthread_attr_setschedpolicy(&attr,SCHED_FIFO));
494 CHK(pthread_attr_setschedparam(&attr,¶m));
495 CHK(pthread_attr_setappschedulerstate(&attr,PTHREAD_APPSCHEDULER));
496 CHK(pthread_attr_setpreemptionlevel(&attr,FOSA_ADS_SCHEDULER_LEVEL));
498 // create the scheduler thread
499 return pthread_create(&scheduler_thread_id,&attr,
500 scheduler_thread_code, (void *) &schedthreaddata);
504 * fosa_thread_attr_set_appscheduled()
506 * Set the appscheduled attribute of a thread attributes object
508 * This function is used to set the appscheduled attribute in the
509 * object pointed to by attr. This attribute controls the kind of
510 * scheduling used for threads created with it. If true, the thread is
511 * scheduled by the application scheduler. If not, it is scheduled by
512 * the system under a fixed priority scheduler
514 * Returns 0 if successful; otherwise it returns an error code:
515 * EINVAL: The value of attr is invalid
517 * Alternatively, in case of error the implementation is allowed to
518 * notify it to the system console and then terminate the FRSH
519 * implementation and dependant applications
521 int fosa_thread_attr_set_appscheduled
522 (frsh_thread_attr_t *attr,
527 // set the application-defined scheduler thread
528 error_code=pthread_attr_setappscheduler(attr,scheduler_thread_id);
529 if (error_code!=0) return error_code;
532 return pthread_attr_setschedpolicy(attr,SCHED_APP);
534 return pthread_attr_setschedpolicy(attr,SCHED_FIFO);
539 * fosa_thread_attr_get_appscheduled()
541 * Get the appscheduled attribute of a thread attributes object
543 * This function is used to get the appscheduled attribute in the
544 * object pointed to by attr. This attribute controls the kind of
545 * scheduling used for threads created with it. If true, the thread is
546 * scheduled by the application scheduler. If not, it is scheduled by
547 * the system under a fixed priority scheduler.
549 * Returns 0 if successful; otherwise it returns an error code:
550 * EINVAL: The value of attr is invalid
552 * Alternatively, in case of error the implementation is allowed to
553 * notify it to the system console and then terminate the FRSH
554 * implementation and dependant applications
556 int fosa_thread_attr_get_appscheduled
557 (const frsh_thread_attr_t *attr,
560 int policy, ret_value;
562 ret_value=pthread_attr_getschedpolicy(attr,&policy);
564 if (policy==SCHED_APP) {
574 * fosa_thread_attr_set_appsched_params()
576 * Set the appsched_param attribute of a thread attributes object
578 * This function is used to set the appsched_param attribute in the
579 * object pointed to by attr. For those threads with appscheduled set
580 * to true, this attribute represents the application-specific
581 * scheduling parameters. If successful, the function shall set the
582 * size of the appsched_param attribute to the value specified by
583 * paramsize, and shall copy the scheduling parameters occupying
584 * paramsize bytes and pointed to by param into that attribute
586 * Returns 0 if successful; otherwise it returns an error code:
587 * EINVAL: The value of attr is invalid, or paramsize is less than
588 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
590 * Alternatively, in case of error the implementation is allowed to
591 * notify it to the system console and then terminate the FRSH
592 * implementation and dependant applications
594 int fosa_thread_attr_set_appsched_params
595 (frsh_thread_attr_t *attr,
599 return pthread_attr_setappschedparam(attr,param,paramsize);
603 * fosa_thread_attr_get_appsched_params()
605 * Get the appsched_param attribute of a thread attributes object
607 * This function is used to get the appsched_param attribute from the
608 * object pointed to by attr. For those threads with appscheduled set
609 * to true, this attribute represents the application-specific
610 * scheduling parameters. If successful, the function shall set the
611 * value pointed to by paramsize to the size of the appsched_param
612 * attribute, and shall copy the scheduling parameters occupying
613 * paramsize bytes into the variable pointed to by param. This
614 * variable should be capable of storing a number of bytes equal to
617 * Returns 0 if successful; otherwise it returns an error code:
618 * EINVAL: The value of attr is invalid
620 * Alternatively, in case of error the implementation is allowed to
621 * notify it to the system console and then terminate the FRSH
622 * implementation and dependant applications
624 int fosa_thread_attr_get_appsched_params
625 (const frsh_thread_attr_t *attr,
629 return pthread_attr_getappschedparam(attr,param,paramsize);
633 * fosa_ads_set_appscheduled()
635 * Dynamically set the appscheduled attribute of a thread
637 * This function is used to dynamically set the appscheduled attribute
638 * of the thread identified by thread. This attribute controls the
639 * kind of scheduling used for threads created with it. If true, the
640 * thread is scheduled by the application scheduler. If not, it is
641 * scheduled by the system under a fixed priority scheduler.
643 * Returns 0 if successful; otherwise it returns an error code:
644 * EINVAL: The value of thread is invalid
646 * EREJECT: the attachment of the thread to the frsh schehduler
647 * was rejected by the frsh scheduler possibly because of
648 * incorrect attributes, or because the requested minimum
649 * capacity cannot be guaranteed
651 * Alternatively, in case of error the implementation is allowed to
652 * notify it to the system console and then terminate the FRSH
653 * implementation and dependant applications
655 int fosa_ads_set_appscheduled
656 (frsh_thread_id_t thread,
660 int current_policy, new_policy;
661 struct sched_param param;
663 // switch to the appropriate scheduling policy
664 CHK(pthread_getschedparam(thread,¤t_policy,¶m));
665 if (((current_policy==SCHED_APP) && (!appscheduled)) ||
666 ((current_policy!=SCHED_APP) && appscheduled)) {
668 new_policy=SCHED_APP;
669 // set the application-defined scheduler thread
670 error_code=pthread_setappscheduler(thread,scheduler_thread_id);
671 if (error_code!=0) return error_code;
673 new_policy=SCHED_FIFO;
675 error_code=pthread_setschedparam(thread,new_policy,¶m);
681 * fosa_ads_getappscheduled()
683 * Dynamically get the appscheduled attribute of a thread
685 * This function is used to dynamically get the appscheduled attribute
686 * of the thread identified by thread. This attribute controls the
687 * kind of scheduling used for threads created with it. If true, the
688 * thread is scheduled by the application scheduler. If not, it is
689 * scheduled by the system under a fixed priority scheduler
691 * Returns 0 if successful; otherwise it returns an error code:
692 * EINVAL: The value of thread is invalid
694 * Alternatively, in case of error the implementation is allowed to
695 * notify it to the system console and then terminate the FRSH
696 * implementation and dependant applications
698 int fosa_ads_get_appscheduled
699 (frsh_thread_id_t thread,
702 int error_code, policy;
703 struct sched_param param;
705 error_code=pthread_getschedparam(thread,&policy,¶m);
709 *appscheduled = (policy==SCHED_APP);
716 * fosa_ads_setappschedparam()
718 * Dynamically set the appsched_param attribute of a thread
720 * This function is used to dynamically set the appsched_param
721 * attribute of the thread identified by thread. For those threads
722 * with appscheduled set to true, this attribute represents the
723 * application-specific scheduling parameters. If successful, the
724 * function shall set the size of the appsched_param attribute to the
725 * value specified by paramsize, and shall copy the scheduling
726 * parameters occupying paramsize bytes and pointed to by param into
729 * Returns 0 if successful; otherwise it returns an error code:
730 * EINVAL: The value of thread is invalid, or paramsize is less than
731 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
733 * Alternatively, in case of error the implementation is allowed to
734 * notify it to the system console and then terminate the FRSH
735 * implementation and dependant applications
737 int fosa_ads_set_appsched_params
738 (frsh_thread_id_t thread,
742 return pthread_setappschedparam(thread,param,paramsize);
746 * fosa_ads_get_appsched_params()
748 * Dynamically get the appsched_param attribute of a thread
750 * This function is used to dynamically get the appsched_param
751 * attribute of the thread identified by thread. For those threads
752 * with appscheduled set to true, this attribute represents the
753 * application-specific scheduling parameters. If successful, the
754 * function shall set the variable pointed to by paramsize to the size
755 * of the appsched_param attribute, and shall copy the scheduling
756 * parameters occupying paramsize bytes into the variable pointed to
757 * by param. This variable should be capable of storing a number of
758 * bytes equal to paramsize.
760 * Returns 0 if successful; otherwise it returns an error code:
761 * EINVAL: The value of thread is invalid, or paramsize is less than
762 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
764 * Alternatively, in case of error the implementation is allowed to
765 * notify it to the system console and then terminate the FRSH
766 * implementation and dependant applications.
768 int fosa_ads_get_appsched_params
769 (frsh_thread_id_t thread,
773 return pthread_getappschedparam(thread,param,paramsize);
777 /*********************************
780 * A scheduling actions object is used to specify a series of actions
781 * to be performed by the system at the end of a scheduler primitive
782 * operation. The order of the actions added to the object shall be
785 *********************************/
788 * fosa_adsactions_add_reject()
790 * Add a reject-thread action
792 * This function adds a thread-reject action to the object referenced
793 * by sched_actions, that will serve to notify that the thread
794 * identified by thread has not been accepted by the scheduler to be
795 * scheduled by it, possibly because the thread contained invalid
796 * application scheduling attributes, or because there are not enough
797 * resources for the new thread. At the end of the new_thread()
798 * scheduler primitive operation, the parent of the rejected thread
799 * waiting on a fosa_thread_create() or the rejected thread itself
800 * waiting on a fosa_ads_set_appscheduled() function shall complete the
801 * function with an error code of EREJECT. If no reject-thread action
802 * is added during the new_thread() scheduler primitive operation, the
803 * thread is accepted to be scheduled by the scheduler and the
804 * associated fosa_thread_create() or the fosa_ads_set_appscheduled()
805 * function shall be completed without error. For the function to
806 * succeed, it has to be called from the new_thread() primitive
807 * operation and for the thread that is requesting attachment to the
810 * Returns 0 if successful; otherwise it returns an error code:
811 * ENOMEM: There is insufficient memory to add this action
812 * FOSA_EPOLICY: The thread specified by thread is not the one requesting
813 * attachment to the scheduler, or the function is not being
814 * called from the new_thread primitive operation
815 * EINVAL: The value specified by sched_actions is invalid
817 * Alternatively, in case of error the implementation is allowed to
818 * notify it to the system console and then terminate the FRSH
819 * implementation and dependant applications
821 int fosa_adsactions_add_reject(
822 fosa_ads_actions_t *sched_actions,
823 frsh_thread_id_t thread)
825 #ifdef FULL_ERROR_CHECKING
827 if (!pthread_equal(pthread_self(),scheduler_thread_id)) {
830 #endif // end if FULL_ERROR_CHECKING
831 sched_actions->rejected=true;
832 return posix_appsched_actions_addreject(&(sched_actions->actions),thread);
836 * fosa_adsactions_add_activate()
838 * Add a thread-activate action
840 * This function adds a thread-activate action to the object
841 * referenced by sched_actions. In case the thread had been previously
842 * suspended via posix_appsched_actions_addsuspend(), it will be
843 * activated at the end of the primitive operation.
845 * In those implementations that do not support urgency scheduling,
846 * the urgencu value is ignored. These implementations cannot support
847 * the frsh hierarchical scheduling module.
849 * In those implementations supporting urgency-scheduling, the action
850 * will cause the change of the urgency of the thread to the value
851 * specified in the urgency argument. Besides, if the thread was
852 * already active at the time the thread-activate action is executed,
853 * the change or urgency will imply a reordering of the thread in its
854 * priority queue, so that for threads of the same priority, those
855 * with more urgency will be scheduled before those of less urgency.
857 * Returns 0 if successful; otherwise it returns an error code:
858 * ENOMEM: There is insufficient memory to add this action
859 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
860 * attribute set to false,
861 * EINVAL: The value specified by sched_actions is invalid
863 * Alternatively, in case of error the implementation is allowed to
864 * notify it to the system console and then terminate the FRSH
865 * implementation and dependant applications
867 int fosa_adsactions_add_activate(
868 fosa_ads_actions_t *sched_actions,
869 frsh_thread_id_t thread,
870 fosa_ads_urgency_t urgency)
872 #ifdef FULL_ERROR_CHECKING
874 struct sched_param param;
877 CHK(pthread_getschedparam(thread,&policy,¶m));
878 if (policy!=SCHED_APP) {
881 #endif // end if FULL_ERROR_CHECKING
883 sched_actions->activated=true;
884 return posix_appsched_actions_addactivate(&(sched_actions->actions),thread);
888 * fosa_adsactions_add_suspend()
890 * Add a thread-suspend action
892 * This function adds a thread-suspend action to the object referenced
893 * by sched_actions, that will cause the thread identified by thread
894 * to be suspended waiting for a thread-activate action at the end of
895 * the scheduler operation. If the thread was already waiting for a
896 * thread-activate action the thread-suspend action has no effect. It
897 * is an error trying to suspend a thread that is blocked by the
900 * Returns 0 if successful; otherwise it returns an error code:
901 * ENOMEM: There is insufficient memory to add this action
902 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
903 * attribute set to false,
904 * EINVAL: The value specified by sched_actions is invalid
906 * Alternatively, in case of error the implementation is allowed to
907 * notify it to the system console and then terminate the FRSH
908 * implementation and dependant applications
910 int fosa_adsactions_add_suspend(
911 fosa_ads_actions_t *sched_actions,
912 frsh_thread_id_t thread)
914 #ifdef FULL_ERROR_CHECKING
916 struct sched_param param;
919 CHK(pthread_getschedparam(thread,&policy,¶m));
920 if (policy!=SCHED_APP) {
923 #endif // end if FULL_ERROR_CHECKING
924 sched_actions->suspended=true;
925 return posix_appsched_actions_addsuspend(&(sched_actions->actions),thread);
929 * fosa_adsactions_add_timeout()
931 * Add a timeout action
933 * This function adds a timeout action to the object referenced by
934 * sched_actions, that will cause the timeout() scheduler operation to
935 * be invoked if no other scheduler operation is invoked before
936 * timeout expires. The timeout shall expire when the clock specified by
937 * clock_id reaches the absolute time specified by the at_time
940 * Returns 0 if successful; otherwise it returns an error code:
941 * ENOMEM: There is insufficient memory to add this action
942 * EINVAL: The value specified by sched_actions is invalid
944 * Alternatively, in case of error the implementation is allowed to
945 * notify it to the system console and then terminate the FRSH
946 * implementation and dependant applications
948 int fosa_adsactions_add_timeout(
949 fosa_ads_actions_t *sched_actions,
950 fosa_clock_id_t clock_id,
951 const struct timespec *at_time)
953 sched_actions->timeout=*at_time;
954 sched_actions->timeout_ptr=&(sched_actions->timeout);
959 * fosa_adsactions_add_thread_notification()
961 * Add a timed-thread-notification action
963 * This function adds a thread-notification action associated with the
964 * thread specified in the thread argument that will cause the
965 * notification_for_thread() scheduler operation to be invoked at the
966 * time specified by at_time. This operation shall be invoked when the
967 * clock specified by clock_id reaches the absolute time specified by
968 * the at_time argument. In particular, a cpu-time clock may be used
969 * for parameter clock_id.Only one thread-notification can be active
970 * for each thread and clock. Calling the function shall remove the
971 * former thread-notification, if any, that had been programmed for
972 * the same thread and clock. A value of NULL for parameter at_time is
973 * used to cancel a previous thread-notification, if any, for the
974 * thread specified by thread and the clock specified by clock_id.
976 * Returns 0 if successful; otherwise it returns an error code:
977 * ENOMEM: There is insufficient memory to add this action
978 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
979 * attribute set to false,
980 * EINVAL: The value specified by sched_actions is invalid
982 * Alternatively, in case of error the implementation is allowed to
983 * notify it to the system console and then terminate the FRSH
984 * implementation and dependant applications
986 int fosa_adsactions_add_thread_notification(
987 fosa_ads_actions_t *sched_actions,
988 frsh_thread_id_t thread,
989 fosa_clock_id_t clock_id,
990 const struct timespec *at_time)
992 #ifdef FULL_ERROR_CHECKING
994 struct sched_param param;
997 CHK(pthread_getschedparam(thread,&policy,¶m));
998 if (policy!=SCHED_APP) {
1001 #endif // end if FULL_ERROR_CHECKING
1003 // the implementation uses a timer that generates a signal
1004 // with the thread id encoded in the signal info
1005 // the clock id is stored in thread-specific data
1007 // store the clock id in thread-specific data
1008 CHK(pthread_setspecific(schedthreaddata.clock_key,(void *) clock_id));
1010 // t.b.d. this function is currently not used,
1011 // therefore we don't implement it yet
1017 * fosa_ads_set_handled_signal_set()
1019 * Specifiy the set of signals that will be handled by the application
1022 * This function is used to dynamically set the set of signals that
1023 * are handled by the application scheduler. When a signal included
1024 * in this set is generated, the signal() primitive operation of the
1025 * application scheduler shall be executed. When a signal in tis set
1026 * is generated, it shall always imply the execution of the signal()
1027 * primitive operation, regardless of whether that signal could be
1028 * accepted by some other thread. Once the signal() primitive
1029 * operation is executed the signal is consumed, so no signal handlers
1030 * shall be executed and no threads using a sigwait operation shall
1031 * return for that particular signal instance. For this function to
1032 * succeed, it has to be called from a primitive operation of a
1035 * Returns 0 if successful; otherwise it returns an error code:
1036 * FOSA_EPOLICY: The function has not been called from a scheduler
1037 * primitive operation
1038 * EINVAL: The value specified by set is invalid
1040 * Alternatively, in case of error the implementation is allowed to
1041 * notify it to the system console and then terminate the FRSH
1042 * implementation and dependant applications
1044 int fosa_ads_set_handled_signal_set(frsh_signal_t set[], int size)
1048 #ifdef FULL_ERROR_CHECKING
1050 if (!pthread_equal(pthread_self(),scheduler_thread_id)) {
1051 return FOSA_EPOLICY;
1053 #endif // end if FULL_ERROR_CHECKING
1054 // empty the signal set
1055 CHKE(sigemptyset(&(schedthreaddata.sch_signal_set)));
1056 // loop for all signals in set, to add them to the set of signals used
1058 for(i=0;i<size;i++) {
1059 CHKE(sigaddset(&(schedthreaddata.sch_signal_set),set[i]));
1066 * fosa_signal_queue_scheduler()
1068 * Queue a signal destinated to the scheduler
1070 * This is a special case of fosa_signal_queue() in which the
1071 * destinator is the scheduler itself. It is needed by the service
1072 * thread to notify the results to the scheduler.
1074 * The problem with this case is that, depending on the implementation,
1075 * this call would be translated to a true signal or to a scheduler
1076 * notification message.
1078 * Besides for the scheduler we don't have always a destinator
1079 * thread_id needed in frsh_signal_queue for OSE.
1081 * So the fosa implementation will solve this issue internally.
1083 * Returns 0 if successful; otherwise it returns an error code:
1084 * FOSA_EINVAL: the signal specified by signal is not
1085 * between FOSA_SIGNAL_MIN and FOSA_SIGNAL_MAX
1087 * FOSA_EAGAIN: no resources are available to queue the signal; the
1088 * maximum number of queued signals has been reached, or a
1089 * systemwide resource limit has been exceeded
1091 * Alternatively, in case of error the implementation is allowed to
1092 * notify it to the system console and then terminate the FRSH
1093 * implementation and dependant applications
1095 int fosa_signal_queue_scheduler(frsh_signal_t signal, frsh_signal_info_t info)
1097 // In MaRTE OS this function is completely equivalent to
1098 // fosa_signal_queue, because there is no notion of receiver.
1099 frsh_thread_id_t receiver = 0; // Dummy value, not used by MaRTE OS
1100 return fosa_signal_queue(signal, info, receiver);
1104 * fosa_ads_invoke_withdata()
1106 * Explicitly invoke the scheduler, with data
1108 * This function can be used by any thread in the process to invoke
1109 * the ads scheduler or to share data with it.
1111 * If successful, the function shall cause the execution of the
1112 * primitive operation explicit_call_with_data() of the ads scheduler
1113 * with its thread parameter equal to the thread ID of the calling
1114 * thread, and its msg_size parameter equal to msg_size. In addition,
1115 * if msg_size is larger than zero, the function shall make available
1116 * to the scheduler a memory area whose contents are identical to the
1117 * memory area pointed to by msg in the msg parameter of the
1118 * explicit_call_with_data() primitive operation (note that copying
1119 * the information is not needed).
1121 * The function shall not return until the system has finished
1122 * execution of the explicit_call_with_data() primitive operation. If
1123 * the reply argument is non NULL, the memory area pointed to by the
1124 * reply parameter of explicit_call_with_data() primitive operation is
1125 * copied into the memory area pointed to by reply, and its size is
1126 * copied into the variable pointed to by reply_size. The size of the
1127 * reply information is limited to the value FOSA_ADS_SCHEDINFO_MAX.
1129 * The function shall fail if the size specified by msg_size is larger
1130 * than FOSA_ADS_SCHEDINFO_MAX. The function shall fail if primitive
1131 * operation explicit_call_with_data() is set to NULL for the ads
1134 * Returns 0 if successful; otherwise it returns an error code:
1135 * FOSA_EPOLICY: The function been called from inside a scheduler
1136 * primitive operation
1137 * EINVAL: The value of msg_size is less than zero or larger than
1138 * FOSA_ADS_SCHEDINFO_MAX
1139 * FOSA_EMASKED: The operation cannot be executed because the primitive
1140 * operation explicit_call_with_data() is set to NULL
1142 * Alternatively, in case of error the implementation is allowed to
1143 * notify it to the system console and then terminate the FRSH
1144 * implementation and dependant applications
1146 int fosa_ads_invoke_withdata
1147 (const void *msg, size_t msg_size, void *reply, size_t *reply_size)
1149 // The corresponding function in MaRTE OS is not yet implemented
1150 // We implement this function by creating a memory area for each thread
1151 // and using the invoke with no data function
1152 struct explicit_call_info * call_info;
1155 #ifdef FULL_ERROR_CHECKING
1157 if (pthread_equal(pthread_self(),scheduler_thread_id)) {
1158 return FOSA_EPOLICY;
1160 if (msg_size>FOSA_ADS_SCHEDINFO_MAX) {
1163 if (schedthreaddata.scheduler_ops.explicit_call_with_data==NULL) {
1164 return FOSA_EMASKED;
1166 #endif // end if FULL_ERROR_CHECKING
1168 call_info = (struct explicit_call_info *)
1169 pthread_getspecific(schedthreaddata.msg_key);
1170 ASSERT_INFO(call_info!=NULL,
1171 "Error in access to specific data for explicit call");
1172 if (call_info==NULL) return EINVAL;
1173 call_info->info_size=msg_size;
1174 // the following type cast is to avoid warnings, but should be OK
1175 call_info->info_ptr=(void *)msg;
1176 call_info->reply_ptr=reply;
1177 error_code=posix_appsched_invoke_scheduler(0);
1178 if (reply != NULL) {
1179 *reply_size=call_info->reply_size;