1 // -----------------------------------------------------------------------
2 // Copyright (C) 2006 - 2008 FRESCOR consortium partners:
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
11 // Thales Communication S.A. FRANCE
12 // Visual Tools S.A. SPAIN
13 // Rapita Systems Ltd UK
16 // See http://www.frescor.org for a link to partners' websites
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
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 // FSF API web pages: http://marte.unican.es/fsf/docs
32 // http://shark.sssup.it/contrib/first/docs/
34 // This file is part of FOSA (Frsh Operating System Adaption)
36 // FOSA 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. FOSA 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 FOSA; see file
44 // COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
45 // Cambridge, MA 02139, USA.
47 // As a special exception, including FOSA header files in a file,
48 // instantiating FOSA generics or templates, or linking other files
49 // with FOSA 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 //fosa_app_def_sched.h
56 //==============================================
57 // ******** ****** ******** **********
58 // **///// /** ** **////// /** /**
59 // ** /** ** /** /** /**
60 // ******* /** ** /********* /**********
61 // **//// /** ** ////////** /**//////**
62 // ** /** ** /** /** /**
63 // ** /** ** ******** /** /**
64 // // /******/ //////// // //
66 // FOSA(Frescor Operating System Adaptation layer)
67 //================================================
68 // 26-Jun-07 SANGORRIN: comment scheduler mutex because signal_set can only be
69 // set from the scheduler itself (don't delete because it might be useful in
72 // 25-Jun-07 SANGORRIN: when posix_appsched_execute_actions had an error code
73 // was wrong. Now we clear actions before (and added destroy operation!), then
74 // execute scheduler op and then go back to main loop (when error it continued
75 // executing the rest of actions)
77 // 10-Jul-07 SANGORRIN: in the new_thread callback we need to accept the thread
78 // before suspend or activate it.
79 // -----------------------------------------------------------------------
88 #include <sys/marte_sched_events_codes.h>
90 #include <misc/error_checks.h>
92 // Full error checking option
93 // --------------------------
94 // Uncomment the following definition if full error checking is desired
95 // Beware that this option will introduce overhead in each context switch
97 #define FULL_ERROR_CHECKING
99 /********************************
100 * Application-defined scheduling
101 ********************************/
104 * We make the following ASSUMPTIONS:
106 * - The ADS always executes in the user memory space, so we don't
107 * need to manage the memory space translation.
109 * - Only one application scheduler exists, so we don't need a
115 * Data structures for the scheduler thread
118 // data structure that is passed to the scheduler thread
119 struct scheduler_thread_data {
120 fosa_ads_scheduler_ops_t scheduler_ops; // entry points
121 size_t scheduler_data_size; // size of scheduler data
122 void * scheduler_data; // pointer to scheduler data
123 void * init_args; // pointer to init args
124 size_t init_args_size; // size of init args
125 sigset_t sch_signal_set; // set of signals used by the
127 // pthread_mutex_t sch_mutex; // mutex used to share info with
129 pthread_key_t clock_key; // key to thread-specific data where
130 // a clock id is stored
131 pthread_key_t msg_key; // key to thread-specific data with
132 // a pointer to the messages for
133 // explicit invoke operations
136 // data structure used in the explicit call with data operation
137 struct explicit_call_info {
145 static struct scheduler_thread_data schedthreaddata;
146 static pthread_t scheduler_thread_id;
149 * Code of application-defined thread. The current version of MaRTE OS
150 * requires a thread to perform the scheduler actions.
151 * In the future it is expected that this thread will not be necessary.
153 void * scheduler_thread_code(void *arg) {
154 fosa_ads_actions_t sched_actions;
155 struct posix_appsched_event event;
156 struct scheduler_thread_data *sch_thread_data=
157 (struct scheduler_thread_data *) arg;
158 void * scheduler_data = sch_thread_data->scheduler_data;
159 posix_appsched_eventset_t event_set;
160 fosa_abs_time_t current_time;
161 struct timespec current_time_tspec;
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_tspec,&event);
241 current_time = fosa_timespec_to_abs_time(current_time_tspec);
243 // clear the scheduling actions data structure
244 CHK(posix_appsched_actions_destroy (&(sched_actions.actions)));
245 CHK(posix_appsched_actions_init(&(sched_actions.actions)));
246 sched_actions.timeout_ptr=NULL;
247 sched_actions.rejected=false;
248 sched_actions.activated=false;
249 sched_actions.suspended=false;
251 // lock the scheduler mutex to perform scheduler operations
252 // in mutual exclusion
253 // CHK(pthread_mutex_lock(&(sch_thread_data->sch_mutex)));
256 // determine which kind of event has arrived, and invoke appropriate
258 switch (event.event_code) {
259 case POSIX_APPSCHED_NEW:
260 sch_thread_data->scheduler_ops.new_thread
265 if (!sched_actions.rejected) {
266 // create a memory area for the explicit messages
267 call_info=(struct explicit_call_info *)
268 malloc(sizeof(struct explicit_call_info));
269 if (call_info==NULL) {
270 CHK(posix_appsched_actions_addreject
271 (&(sched_actions.actions),event.thread));
273 // clear actions, we need to accept the thread first
274 CHK(posix_appsched_actions_destroy (&(sched_actions.actions)));
275 CHK(posix_appsched_actions_init(&(sched_actions.actions)));
277 CHK(posix_appsched_actions_addaccept
278 (&(sched_actions.actions),event.thread));
279 // store the memory area in thread-specific data
280 CHK(pthread_setspecific_for
281 (schedthreaddata.msg_key,event.thread,call_info));
282 // and activate or suspend the thread
283 if (sched_actions.suspended) {
284 CHK(posix_appsched_actions_addsuspend
285 (&(sched_actions.actions),event.thread));
287 CHK(posix_appsched_actions_addactivate
288 (&(sched_actions.actions),event.thread));
293 case POSIX_APPSCHED_TERMINATE:
294 sch_thread_data->scheduler_ops.thread_terminate
300 case POSIX_APPSCHED_READY:
301 sch_thread_data->scheduler_ops.thread_ready
306 // activate the thread unless suspended or already activated
307 if (!sched_actions.suspended && !sched_actions.activated) {
308 CHK(posix_appsched_actions_addactivate
309 (&(sched_actions.actions),event.thread));
312 case POSIX_APPSCHED_BLOCK:
313 sch_thread_data->scheduler_ops.thread_block
319 case POSIX_APPSCHED_CHANGE_SCHED_PARAM:
320 sch_thread_data->scheduler_ops.change_sched_param_thread
326 //case POSIX_APPSCHED_EXPLICIT_CALL_WITH_DATA:
327 //sch_thread_data->scheduler_ops.explicit_call_with_data
330 // event.event_info.info,event.info_size,
331 // &reply, &reply_size,
334 case POSIX_APPSCHED_EXPLICIT_CALL:
335 CHK(pthread_getspecific_from
336 (schedthreaddata.msg_key,event.thread,(void **)(&call_info)));
337 sch_thread_data->scheduler_ops.explicit_call_with_data
341 call_info->info_size,
342 call_info->reply_ptr,
343 &(call_info->reply_size),
346 // activate the thread unless suspended or already activated
347 if (!sched_actions.suspended && !sched_actions.activated) {
348 CHK(posix_appsched_actions_addactivate
349 (&(sched_actions.actions),event.thread));
352 case POSIX_APPSCHED_TASK_NOTIFICATION:
353 clk=(clockid_t) pthread_getspecific(sch_thread_data->clock_key);
354 sch_thread_data->scheduler_ops.notification_for_thread
360 // t.b.d. check if state of thread is suspended by default
362 case POSIX_APPSCHED_TIMEOUT:
363 sch_thread_data->scheduler_ops.timeout
368 case POSIX_APPSCHED_SIGNAL:
369 sch_thread_data->scheduler_ops.signal
371 event.event_info.siginfo.si_signo,
372 *((fosa_signal_info_t *)(&(event.event_info.siginfo.si_value))),
373 // the above casting construct is used to overcome the compiler
374 // restriction that does not allow casts between unions
379 ASSERT_INFO(true,"Unexpected scheduling event received in scheduler");
380 } // end switch on event code
381 } else if (err==EINVAL) {
382 sch_thread_data->scheduler_ops.appsched_error
383 (scheduler_data, event.thread,
384 FOSA_ADS_THREAD_NOT_ATTACHED, &sched_actions);
385 } else if (err==ESRCH) {
386 sch_thread_data->scheduler_ops.appsched_error
387 (scheduler_data, event.thread,
388 FOSA_ADS_INVALID_ACTION, &sched_actions);
390 } // end of main scheduler loop
395 * fosa_ads_scheduler_create()
397 * Create the application defined scheduler
399 * The application defined scheduler is created with the primitive
400 * operations specified in the object pointed to by scheduler_ops.
402 * The clock used to read the time immediately before the invocation
403 * of each primitive operation, to be reported to the scheduler via
404 * the current_time parameter of each primitive operation is the
405 * FOSA_CLOCK_REALTIME clock.
407 * The scheduler_data_size parameter is used to request that a memory
408 * area of this size must be created and reserved for the scheduler to
409 * store its state. A pointer to this area is passed to the scheduler
410 * operations in the sched_data parameter.
412 * Parameter init_arg points to an area that contains configuration
413 * information for the scheduler. The function creates a memory area
414 * of init_arg_size bytes and copies into it the area pointed by
415 * arg. A pointer to this new created area will be passed to the
416 * primitive operation init() in its arg parameter.
418 * Returns 0 if successful; otherwise it returns an error code:
419 * EINVAL: The value of scheduler_ops was invalid
420 * EAGAIN: The system lacks enough resources to create the scheduler
422 * Alternatively, in case of error the implementation is allowed to
423 * notify it to the system console and then terminate the FRSH
424 * implementation and dependant applications
426 * The fosa_ads_scheduler_create function must be called before any
427 * other function in this header file
429 int fosa_ads_scheduler_create
430 (const fosa_ads_scheduler_ops_t * scheduler_ops,
431 size_t scheduler_data_size,
433 size_t init_args_size)
436 // pthread_mutexattr_t mattr;
438 struct sched_param param;
440 #ifdef FULL_ERROR_CHECKING
441 // check for NULL scheduler operations
442 if (scheduler_ops==NULL) {
445 #endif // end if FULL_ERROR_CHECKING
447 // copy arguments in scheduler data
448 schedthreaddata.scheduler_ops=*scheduler_ops;
449 schedthreaddata.scheduler_data_size=scheduler_data_size;
450 schedthreaddata.init_args_size=init_args_size;
452 // create scheduler memory area
453 schedthreaddata.scheduler_data=malloc(scheduler_data_size);
454 if (schedthreaddata.scheduler_data==NULL) {
458 // create init args memory area and copy the init args
459 schedthreaddata.init_args=malloc(init_args_size);
460 if (schedthreaddata.init_args==NULL) {
463 memcpy(schedthreaddata.init_args,init_args,init_args_size);
465 // initialize the set of signals used by the scheduler to none
466 CHKE(sigemptyset(&(schedthreaddata.sch_signal_set)));
468 // calculate the priority
469 param.sched_priority=sched_get_priority_max(SCHED_FIFO)-
470 FOSA_ADS_SCHEDULER_PRIO_DIFF;
472 // initialize the mutex used to share data with the scheduler
473 // CHK(pthread_mutexattr_init(&mattr));
474 // we use the priority protect protocol
475 // CHK(pthread_mutexattr_setprotocol(&mattr,PTHREAD_PRIO_PROTECT));
476 // set priority ceiling
477 // CHK(pthread_mutexattr_setprioceiling(&mattr,param.sched_priority));
479 // CHK(pthread_mutex_init(&(schedthreaddata.sch_mutex),&mattr));
480 // CHK(pthread_mutexattr_destroy(&mattr));
482 // create the thread-specific data key for the clock id
483 CHK(pthread_key_create(&schedthreaddata.clock_key,NULL));
485 // create the thread-specific data key for the message pointers
486 CHK(pthread_key_create(&schedthreaddata.msg_key,NULL));
488 // set the attributes for the scheduler thread
489 err=pthread_attr_init(&attr);
493 CHK(pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED));
494 CHK(pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED));
495 CHK(pthread_attr_setschedpolicy(&attr,SCHED_FIFO));
496 CHK(pthread_attr_setschedparam(&attr,¶m));
497 CHK(pthread_attr_setappschedulerstate(&attr,PTHREAD_APPSCHEDULER));
498 CHK(pthread_attr_setpreemptionlevel(&attr,FOSA_ADS_SCHEDULER_LEVEL));
500 // create the scheduler thread
501 return pthread_create(&scheduler_thread_id,&attr,
502 scheduler_thread_code, (void *) &schedthreaddata);
506 * fosa_thread_attr_set_appscheduled()
508 * Set the appscheduled attribute of a thread attributes object
510 * This function is used to set the appscheduled attribute in the
511 * object pointed to by attr. This attribute controls the kind of
512 * scheduling used for threads created with it. If true, the thread is
513 * scheduled by the application scheduler. If not, it is scheduled by
514 * the system under a fixed priority scheduler
516 * Returns 0 if successful; otherwise it returns an error code:
517 * EINVAL: The value of attr is invalid
519 * Alternatively, in case of error the implementation is allowed to
520 * notify it to the system console and then terminate the FRSH
521 * implementation and dependant applications
523 int fosa_thread_attr_set_appscheduled
524 (fosa_thread_attr_t *attr,
529 // set the application-defined scheduler thread
530 error_code=pthread_attr_setappscheduler(attr,scheduler_thread_id);
531 if (error_code!=0) return error_code;
534 return pthread_attr_setschedpolicy(attr,SCHED_APP);
536 return pthread_attr_setschedpolicy(attr,SCHED_FIFO);
541 * fosa_thread_attr_get_appscheduled()
543 * Get the appscheduled attribute of a thread attributes object
545 * This function is used to get the appscheduled attribute in the
546 * object pointed to by attr. This attribute controls the kind of
547 * scheduling used for threads created with it. If true, the thread is
548 * scheduled by the application scheduler. If not, it is scheduled by
549 * the system under a fixed priority scheduler.
551 * Returns 0 if successful; otherwise it returns an error code:
552 * EINVAL: The value of attr is invalid
554 * Alternatively, in case of error the implementation is allowed to
555 * notify it to the system console and then terminate the FRSH
556 * implementation and dependant applications
558 int fosa_thread_attr_get_appscheduled
559 (const fosa_thread_attr_t *attr,
562 int policy, ret_value;
564 ret_value=pthread_attr_getschedpolicy(attr,&policy);
566 if (policy==SCHED_APP) {
576 * fosa_thread_attr_set_appsched_params()
578 * Set the appsched_param attribute of a thread attributes object
580 * This function is used to set the appsched_param attribute in the
581 * object pointed to by attr. For those threads with appscheduled set
582 * to true, this attribute represents the application-specific
583 * scheduling parameters. If successful, the function shall set the
584 * size of the appsched_param attribute to the value specified by
585 * paramsize, and shall copy the scheduling parameters occupying
586 * paramsize bytes and pointed to by param into that attribute
588 * Returns 0 if successful; otherwise it returns an error code:
589 * EINVAL: The value of attr is invalid, or paramsize is less than
590 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
592 * Alternatively, in case of error the implementation is allowed to
593 * notify it to the system console and then terminate the FRSH
594 * implementation and dependant applications
596 int fosa_thread_attr_set_appsched_params
597 (fosa_thread_attr_t *attr,
601 return pthread_attr_setappschedparam(attr,param,paramsize);
605 * fosa_thread_attr_get_appsched_params()
607 * Get the appsched_param attribute of a thread attributes object
609 * This function is used to get the appsched_param attribute from the
610 * object pointed to by attr. For those threads with appscheduled set
611 * to true, this attribute represents the application-specific
612 * scheduling parameters. If successful, the function shall set the
613 * value pointed to by paramsize to the size of the appsched_param
614 * attribute, and shall copy the scheduling parameters occupying
615 * paramsize bytes into the variable pointed to by param. This
616 * variable should be capable of storing a number of bytes equal to
619 * Returns 0 if successful; otherwise it returns an error code:
620 * EINVAL: The value of attr is invalid
622 * Alternatively, in case of error the implementation is allowed to
623 * notify it to the system console and then terminate the FRSH
624 * implementation and dependant applications
626 int fosa_thread_attr_get_appsched_params
627 (const fosa_thread_attr_t *attr,
631 return pthread_attr_getappschedparam(attr,param,paramsize);
635 * fosa_ads_set_appscheduled()
637 * Dynamically set the appscheduled attribute of a thread
639 * This function is used to dynamically set the appscheduled attribute
640 * of the thread identified by thread. This attribute controls the
641 * kind of scheduling used for threads created with it. If true, the
642 * thread is scheduled by the application scheduler. If not, it is
643 * scheduled by the system under a fixed priority scheduler.
645 * Returns 0 if successful; otherwise it returns an error code:
646 * EINVAL: The value of thread is invalid
648 * EREJECT: the attachment of the thread to the frsh schehduler
649 * was rejected by the frsh scheduler possibly because of
650 * incorrect attributes, or because the requested minimum
651 * capacity cannot be guaranteed
653 * Alternatively, in case of error the implementation is allowed to
654 * notify it to the system console and then terminate the FRSH
655 * implementation and dependant applications
657 int fosa_ads_set_appscheduled
658 (fosa_thread_id_t thread,
662 int current_policy, new_policy;
663 struct sched_param param;
665 // switch to the appropriate scheduling policy
666 CHK(pthread_getschedparam(thread,¤t_policy,¶m));
667 if (((current_policy==SCHED_APP) && (!appscheduled)) ||
668 ((current_policy!=SCHED_APP) && appscheduled)) {
670 new_policy=SCHED_APP;
671 // set the application-defined scheduler thread
672 error_code=pthread_setappscheduler(thread,scheduler_thread_id);
673 if (error_code!=0) return error_code;
675 new_policy=SCHED_FIFO;
677 error_code=pthread_setschedparam(thread,new_policy,¶m);
683 * fosa_ads_getappscheduled()
685 * Dynamically get the appscheduled attribute of a thread
687 * This function is used to dynamically get the appscheduled attribute
688 * of the thread identified by thread. This attribute controls the
689 * kind of scheduling used for threads created with it. If true, the
690 * thread is scheduled by the application scheduler. If not, it is
691 * scheduled by the system under a fixed priority scheduler
693 * Returns 0 if successful; otherwise it returns an error code:
694 * EINVAL: The value of thread is invalid
696 * Alternatively, in case of error the implementation is allowed to
697 * notify it to the system console and then terminate the FRSH
698 * implementation and dependant applications
700 int fosa_ads_get_appscheduled
701 (fosa_thread_id_t thread,
704 int error_code, policy;
705 struct sched_param param;
707 error_code=pthread_getschedparam(thread,&policy,¶m);
711 *appscheduled = (policy==SCHED_APP);
718 * fosa_ads_setappschedparam()
720 * Dynamically set the appsched_param attribute of a thread
722 * This function is used to dynamically set the appsched_param
723 * attribute of the thread identified by thread. For those threads
724 * with appscheduled set to true, this attribute represents the
725 * application-specific scheduling parameters. If successful, the
726 * function shall set the size of the appsched_param attribute to the
727 * value specified by paramsize, and shall copy the scheduling
728 * parameters occupying paramsize bytes and pointed to by param into
731 * Returns 0 if successful; otherwise it returns an error code:
732 * EINVAL: The value of thread is invalid, or paramsize is less than
733 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
735 * Alternatively, in case of error the implementation is allowed to
736 * notify it to the system console and then terminate the FRSH
737 * implementation and dependant applications
739 int fosa_ads_set_appsched_params
740 (fosa_thread_id_t thread,
744 return pthread_setappschedparam(thread,param,paramsize);
748 * fosa_ads_get_appsched_params()
750 * Dynamically get the appsched_param attribute of a thread
752 * This function is used to dynamically get the appsched_param
753 * attribute of the thread identified by thread. For those threads
754 * with appscheduled set to true, this attribute represents the
755 * application-specific scheduling parameters. If successful, the
756 * function shall set the variable pointed to by paramsize to the size
757 * of the appsched_param attribute, and shall copy the scheduling
758 * parameters occupying paramsize bytes into the variable pointed to
759 * by param. This variable should be capable of storing a number of
760 * bytes equal to paramsize.
762 * Returns 0 if successful; otherwise it returns an error code:
763 * EINVAL: The value of thread is invalid, or paramsize is less than
764 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
766 * Alternatively, in case of error the implementation is allowed to
767 * notify it to the system console and then terminate the FRSH
768 * implementation and dependant applications.
770 int fosa_ads_get_appsched_params
771 (fosa_thread_id_t thread,
775 return pthread_getappschedparam(thread,param,paramsize);
779 /*********************************
782 * A scheduling actions object is used to specify a series of actions
783 * to be performed by the system at the end of a scheduler primitive
784 * operation. The order of the actions added to the object shall be
787 *********************************/
790 * fosa_adsactions_add_reject()
792 * Add a reject-thread action
794 * This function adds a thread-reject action to the object referenced
795 * by sched_actions, that will serve to notify that the thread
796 * identified by thread has not been accepted by the scheduler to be
797 * scheduled by it, possibly because the thread contained invalid
798 * application scheduling attributes, or because there are not enough
799 * resources for the new thread. At the end of the new_thread()
800 * scheduler primitive operation, the parent of the rejected thread
801 * waiting on a fosa_thread_create() or the rejected thread itself
802 * waiting on a fosa_ads_set_appscheduled() function shall complete the
803 * function with an error code of EREJECT. If no reject-thread action
804 * is added during the new_thread() scheduler primitive operation, the
805 * thread is accepted to be scheduled by the scheduler and the
806 * associated fosa_thread_create() or the fosa_ads_set_appscheduled()
807 * function shall be completed without error. For the function to
808 * succeed, it has to be called from the new_thread() primitive
809 * operation and for the thread that is requesting attachment to the
812 * Returns 0 if successful; otherwise it returns an error code:
813 * ENOMEM: There is insufficient memory to add this action
814 * FOSA_EPOLICY: The thread specified by thread is not the one requesting
815 * attachment to the scheduler, or the function is not being
816 * called from the new_thread primitive operation
817 * EINVAL: The value specified by sched_actions is invalid
819 * Alternatively, in case of error the implementation is allowed to
820 * notify it to the system console and then terminate the FRSH
821 * implementation and dependant applications
823 int fosa_adsactions_add_reject(
824 fosa_ads_actions_t *sched_actions,
825 fosa_thread_id_t thread)
827 #ifdef FULL_ERROR_CHECKING
829 if (!pthread_equal(pthread_self(),scheduler_thread_id)) {
832 #endif // end if FULL_ERROR_CHECKING
833 sched_actions->rejected=true;
834 return posix_appsched_actions_addreject(&(sched_actions->actions),thread);
838 * fosa_adsactions_add_activate()
840 * Add a thread-activate action
842 * This function adds a thread-activate action to the object
843 * referenced by sched_actions. In case the thread had been previously
844 * suspended via posix_appsched_actions_addsuspend(), it will be
845 * activated at the end of the primitive operation.
847 * In those implementations that do not support urgency scheduling,
848 * the urgencu value is ignored. These implementations cannot support
849 * the frsh hierarchical scheduling module.
851 * In those implementations supporting urgency-scheduling, the action
852 * will cause the change of the urgency of the thread to the value
853 * specified in the urgency argument. Besides, if the thread was
854 * already active at the time the thread-activate action is executed,
855 * the change or urgency will imply a reordering of the thread in its
856 * priority queue, so that for threads of the same priority, those
857 * with more urgency will be scheduled before those of less urgency.
859 * Returns 0 if successful; otherwise it returns an error code:
860 * ENOMEM: There is insufficient memory to add this action
861 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
862 * attribute set to false,
863 * EINVAL: The value specified by sched_actions is invalid
865 * Alternatively, in case of error the implementation is allowed to
866 * notify it to the system console and then terminate the FRSH
867 * implementation and dependant applications
869 int fosa_adsactions_add_activate(
870 fosa_ads_actions_t *sched_actions,
871 fosa_thread_id_t thread,
872 fosa_ads_urgency_t urgency)
874 #ifdef FULL_ERROR_CHECKING
876 struct sched_param param;
879 CHK(pthread_getschedparam(thread,&policy,¶m));
880 if (policy!=SCHED_APP) {
883 #endif // end if FULL_ERROR_CHECKING
885 sched_actions->activated=true;
886 return posix_appsched_actions_addactivate(&(sched_actions->actions),thread);
890 * fosa_adsactions_add_suspend()
892 * Add a thread-suspend action
894 * This function adds a thread-suspend action to the object referenced
895 * by sched_actions, that will cause the thread identified by thread
896 * to be suspended waiting for a thread-activate action at the end of
897 * the scheduler operation. If the thread was already waiting for a
898 * thread-activate action the thread-suspend action has no effect. It
899 * is an error trying to suspend a thread that is blocked by the
902 * Returns 0 if successful; otherwise it returns an error code:
903 * ENOMEM: There is insufficient memory to add this action
904 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
905 * attribute set to false,
906 * EINVAL: The value specified by sched_actions is invalid
908 * Alternatively, in case of error the implementation is allowed to
909 * notify it to the system console and then terminate the FRSH
910 * implementation and dependant applications
912 int fosa_adsactions_add_suspend(
913 fosa_ads_actions_t *sched_actions,
914 fosa_thread_id_t thread)
916 #ifdef FULL_ERROR_CHECKING
918 struct sched_param param;
921 CHK(pthread_getschedparam(thread,&policy,¶m));
922 if (policy!=SCHED_APP) {
925 #endif // end if FULL_ERROR_CHECKING
926 sched_actions->suspended=true;
927 return posix_appsched_actions_addsuspend(&(sched_actions->actions),thread);
931 * fosa_adsactions_add_timeout()
933 * Add a timeout action
935 * This function adds a timeout action to the object referenced by
936 * sched_actions, that will cause the timeout() scheduler operation to
937 * be invoked if no other scheduler operation is invoked before
938 * timeout expires. The timeout shall expire when the clock specified by
939 * clock_id reaches the absolute time specified by the at_time
942 * Returns 0 if successful; otherwise it returns an error code:
943 * ENOMEM: There is insufficient memory to add this action
944 * EINVAL: The value specified by sched_actions is invalid
946 * Alternatively, in case of error the implementation is allowed to
947 * notify it to the system console and then terminate the FRSH
948 * implementation and dependant applications
950 int fosa_adsactions_add_timeout(
951 fosa_ads_actions_t *sched_actions,
952 fosa_clock_id_t clock_id,
953 const fosa_abs_time_t *at_time)
955 sched_actions->timeout= fosa_abs_time_to_timespec(*at_time);
956 sched_actions->timeout_ptr=&(sched_actions->timeout);
961 * fosa_adsactions_add_thread_notification()
963 * Add a timed-thread-notification action
965 * This function adds a thread-notification action associated with the
966 * thread specified in the thread argument that will cause the
967 * notification_for_thread() scheduler operation to be invoked at the
968 * time specified by at_time. This operation shall be invoked when the
969 * clock specified by clock_id reaches the absolute time specified by
970 * the at_time argument. In particular, a cpu-time clock may be used
971 * for parameter clock_id.Only one thread-notification can be active
972 * for each thread and clock. Calling the function shall remove the
973 * former thread-notification, if any, that had been programmed for
974 * the same thread and clock. A value of NULL for parameter at_time is
975 * used to cancel a previous thread-notification, if any, for the
976 * thread specified by thread and the clock specified by clock_id.
978 * Returns 0 if successful; otherwise it returns an error code:
979 * ENOMEM: There is insufficient memory to add this action
980 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
981 * attribute set to false,
982 * EINVAL: The value specified by sched_actions is invalid
984 * Alternatively, in case of error the implementation is allowed to
985 * notify it to the system console and then terminate the FRSH
986 * implementation and dependant applications
988 int fosa_adsactions_add_thread_notification(
989 fosa_ads_actions_t *sched_actions,
990 fosa_thread_id_t thread,
991 fosa_clock_id_t clock_id,
992 const fosa_abs_time_t *at_time)
994 #ifdef FULL_ERROR_CHECKING
996 struct sched_param param;
999 CHK(pthread_getschedparam(thread,&policy,¶m));
1000 if (policy!=SCHED_APP) {
1001 return FOSA_EPOLICY;
1003 #endif // end if FULL_ERROR_CHECKING
1005 // the implementation uses a timer that generates a signal
1006 // with the thread id encoded in the signal info
1007 // the clock id is stored in thread-specific data
1009 // store the clock id in thread-specific data
1010 CHK(pthread_setspecific(schedthreaddata.clock_key,(void *) clock_id));
1012 // t.b.d. this function is currently not used,
1013 // therefore we don't implement it yet
1019 * fosa_ads_set_handled_signal_set()
1021 * Specifiy the set of signals that will be handled by the application
1024 * This function is used to dynamically set the set of signals that
1025 * are handled by the application scheduler. When a signal included
1026 * in this set is generated, the signal() primitive operation of the
1027 * application scheduler shall be executed. When a signal in tis set
1028 * is generated, it shall always imply the execution of the signal()
1029 * primitive operation, regardless of whether that signal could be
1030 * accepted by some other thread. Once the signal() primitive
1031 * operation is executed the signal is consumed, so no signal handlers
1032 * shall be executed and no threads using a sigwait operation shall
1033 * return for that particular signal instance. For this function to
1034 * succeed, it has to be called from a primitive operation of a
1037 * Returns 0 if successful; otherwise it returns an error code:
1038 * FOSA_EPOLICY: The function has not been called from a scheduler
1039 * primitive operation
1040 * EINVAL: The value specified by set is invalid
1042 * Alternatively, in case of error the implementation is allowed to
1043 * notify it to the system console and then terminate the FRSH
1044 * implementation and dependant applications
1046 int fosa_ads_set_handled_signal_set(fosa_signal_t set[], int size)
1050 #ifdef FULL_ERROR_CHECKING
1052 if (!pthread_equal(pthread_self(),scheduler_thread_id)) {
1053 return FOSA_EPOLICY;
1055 #endif // end if FULL_ERROR_CHECKING
1056 // empty the signal set
1057 CHKE(sigemptyset(&(schedthreaddata.sch_signal_set)));
1058 // loop for all signals in set, to add them to the set of signals used
1060 for(i=0;i<size;i++) {
1061 CHKE(sigaddset(&(schedthreaddata.sch_signal_set),set[i]));
1068 * fosa_signal_queue_scheduler()
1070 * Queue a signal destinated to the scheduler
1072 * This is a special case of fosa_signal_queue() in which the
1073 * destinator is the scheduler itself. It is needed by the service
1074 * thread to notify the results to the scheduler.
1076 * The problem with this case is that, depending on the implementation,
1077 * this call would be translated to a true signal or to a scheduler
1078 * notification message.
1080 * Besides for the scheduler we don't have always a destinator
1081 * thread_id needed in fosa_signal_queue for OSE.
1083 * So the fosa implementation will solve this issue internally.
1085 * Returns 0 if successful; otherwise it returns an error code:
1086 * FOSA_EINVAL: the signal specified by signal is not
1087 * between FOSA_SIGNAL_MIN and FOSA_SIGNAL_MAX
1089 * FOSA_EAGAIN: no resources are available to queue the signal; the
1090 * maximum number of queued signals has been reached, or a
1091 * systemwide resource limit has been exceeded
1093 * Alternatively, in case of error the implementation is allowed to
1094 * notify it to the system console and then terminate the FRSH
1095 * implementation and dependant applications
1097 int fosa_signal_queue_scheduler(fosa_signal_t signal, fosa_signal_info_t info)
1099 // In MaRTE OS this function is completely equivalent to
1100 // fosa_signal_queue, because there is no notion of receiver.
1101 fosa_thread_id_t receiver = 0; // Dummy value, not used by MaRTE OS
1102 return fosa_signal_queue(signal, info, receiver);
1106 * fosa_ads_invoke_withdata()
1108 * Explicitly invoke the scheduler, with data
1110 * This function can be used by any thread in the process to invoke
1111 * the ads scheduler or to share data with it.
1113 * If successful, the function shall cause the execution of the
1114 * primitive operation explicit_call_with_data() of the ads scheduler
1115 * with its thread parameter equal to the thread ID of the calling
1116 * thread, and its msg_size parameter equal to msg_size. In addition,
1117 * if msg_size is larger than zero, the function shall make available
1118 * to the scheduler a memory area whose contents are identical to the
1119 * memory area pointed to by msg in the msg parameter of the
1120 * explicit_call_with_data() primitive operation (note that copying
1121 * the information is not needed).
1123 * The function shall not return until the system has finished
1124 * execution of the explicit_call_with_data() primitive operation. If
1125 * the reply argument is non NULL, the memory area pointed to by the
1126 * reply parameter of explicit_call_with_data() primitive operation is
1127 * copied into the memory area pointed to by reply, and its size is
1128 * copied into the variable pointed to by reply_size. The size of the
1129 * reply information is limited to the value FOSA_ADS_SCHEDINFO_MAX.
1131 * The function shall fail if the size specified by msg_size is larger
1132 * than FOSA_ADS_SCHEDINFO_MAX. The function shall fail if primitive
1133 * operation explicit_call_with_data() is set to NULL for the ads
1136 * Returns 0 if successful; otherwise it returns an error code:
1137 * FOSA_EPOLICY: The function been called from inside a scheduler
1138 * primitive operation
1139 * EINVAL: The value of msg_size is less than zero or larger than
1140 * FOSA_ADS_SCHEDINFO_MAX
1141 * FOSA_EMASKED: The operation cannot be executed because the primitive
1142 * operation explicit_call_with_data() is set to NULL
1144 * Alternatively, in case of error the implementation is allowed to
1145 * notify it to the system console and then terminate the FRSH
1146 * implementation and dependant applications
1148 int fosa_ads_invoke_withdata
1149 (const void *msg, size_t msg_size, void *reply, size_t *reply_size)
1151 // The corresponding function in MaRTE OS is not yet implemented
1152 // We implement this function by creating a memory area for each thread
1153 // and using the invoke with no data function
1154 struct explicit_call_info * call_info;
1157 #ifdef FULL_ERROR_CHECKING
1159 if (pthread_equal(pthread_self(),scheduler_thread_id)) {
1160 return FOSA_EPOLICY;
1162 if (msg_size>FOSA_ADS_SCHEDINFO_MAX) {
1165 if (schedthreaddata.scheduler_ops.explicit_call_with_data==NULL) {
1166 return FOSA_EMASKED;
1168 #endif // end if FULL_ERROR_CHECKING
1170 call_info = (struct explicit_call_info *)
1171 pthread_getspecific(schedthreaddata.msg_key);
1172 ASSERT_INFO(call_info!=NULL,
1173 "Error in access to specific data for explicit call");
1174 if (call_info==NULL) return EINVAL;
1175 call_info->info_size=msg_size;
1176 // the following type cast is to avoid warnings, but should be OK
1177 call_info->info_ptr=(void *)msg;
1178 call_info->reply_ptr=reply;
1179 error_code=posix_appsched_invoke_scheduler(0);
1180 if (reply != NULL) {
1181 *reply_size=call_info->reply_size;