1 // -----------------------------------------------------------------------
2 // Copyright (C) 2006 - 2007 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. 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 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
23 // This file is part of the FRSH implementation
25 // FRSH is free software; you can redistribute it and/or modify
26 // it under the terms of the GNU General Public License as published by
27 // the Free Software Foundation; either version 2, or (at your option)
30 // FRSH is distributed in the hope that it will be useful, but
31 // WITHOUT ANY WARRANTY; without even the implied warranty of
32 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 // General Public License for more details.
35 // You should have received a copy of the GNU General Public License
36 // distributed with FRSH; see file COPYING. If not, write to the
37 // Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
40 // -----------------------------------------------------------------------
41 //fosa_app_def_sched.h
42 //==============================================
43 // ******** ****** ******** **********
44 // **///// /** ** **////// /** /**
45 // ** /** ** /** /** /**
46 // ******* /** ** /********* /**********
47 // **//// /** ** ////////** /**//////**
48 // ** /** ** /** /** /**
49 // ** /** ** ******** /** /**
50 // // /******/ //////// // //
52 // FOSA(Frescor Operating System Adaptation layer)
53 //================================================
55 #include "fosa_app_def_sched.h"
56 #include "fosa_configuration_parameters.h"
57 #include "frsh_error.h"
58 #include "frsh_fosa.h"
64 #include <sys/marte_sched_events_codes.h>
66 #include <misc/error_checks.h>
68 // Full error checking option
69 // --------------------------
70 // Uncomment the following definition if full error checking is desired
71 // Beware that this option will introduce overhead in each context switch
73 #define FULL_ERROR_CHECKING
75 /********************************
76 * Application-defined scheduling
77 ********************************/
80 * We make the following ASSUMPTIONS:
82 * - The ADS always executes in the user memory space, so we don't
83 * need to manage the memory space translation.
85 * - Only one application scheduler exists, so we don't need a
91 * Data structures for the scheduler thread
94 // data structure that is passed to the scheduler thread
95 struct scheduler_thread_data {
96 fosa_ads_scheduler_ops_t scheduler_ops; // entry points
97 size_t scheduler_data_size; // size of scheduler data
98 void * scheduler_data; // pointer to scheduler data
99 void * init_args; // pointer to init args
100 size_t init_args_size; // size of init args
101 sigset_t sch_signal_set; // set of signals used by the
103 pthread_mutex_t sch_mutex; // mutex used to share info with
105 pthread_key_t clock_key; // key to thread-specific data where
106 // a clock id is stored
107 pthread_key_t msg_key; // key to thread-specific data with
108 // a pointer to the messages for
109 // explicit invoke operations
112 // data structure used in the explicit call with data operation
113 struct explicit_call_info {
121 static struct scheduler_thread_data schedthreaddata;
122 static pthread_t scheduler_thread_id;
125 * Code of application-defined thread. The current version of MaRTE OS
126 * requires a thread to perform the scheduler actions.
127 * In the future it is expected that this thread will not be necessary.
129 void * scheduler_thread_code(void *arg) {
130 fosa_ads_actions_t sched_actions;
131 struct posix_appsched_event event;
132 struct scheduler_thread_data *sch_thread_data=
133 (struct scheduler_thread_data *) arg;
134 void * scheduler_data = sch_thread_data->scheduler_data;
135 posix_appsched_eventset_t event_set;
136 struct timespec current_time;
137 sigset_t copy_of_signalset;
138 struct explicit_call_info *call_info;
142 // set the clock to be used by the scheduler
143 CHK(posix_appschedattr_setclock(FOSA_CLOCK_REALTIME));
145 // set the timeouts to be used in the scheduler to be absolute
146 posix_appschedattr_setflags (POSIX_APPSCHED_ABSTIMEOUT);
148 // set the mask of events to mask all events except for those
149 // corresponding to non-null entry points
150 CHK(posix_appsched_fillset(&event_set));
152 if (sch_thread_data->scheduler_ops.new_thread!=NULL) {
153 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_NEW));
156 if (sch_thread_data->scheduler_ops.thread_terminate!=NULL) {
157 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_TERMINATE));
160 if (sch_thread_data->scheduler_ops.thread_ready!=NULL) {
161 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_READY));
164 if (sch_thread_data->scheduler_ops.thread_block!=NULL) {
165 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_BLOCK));
167 // change_sched_param_thread
168 if (sch_thread_data->scheduler_ops.change_sched_param_thread!=NULL) {
169 CHK(posix_appsched_delset(&event_set,
170 POSIX_APPSCHED_CHANGE_SCHED_PARAM));
172 // explicit_call_with_data
173 if (sch_thread_data->scheduler_ops.explicit_call_with_data!=NULL) {
174 CHK(posix_appsched_delset(&event_set,
175 POSIX_APPSCHED_EXPLICIT_CALL_WITH_DATA));
177 // notification_for_thread
178 if (sch_thread_data->scheduler_ops.notification_for_thread!=NULL) {
179 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_TASK_NOTIFICATION));
182 if (sch_thread_data->scheduler_ops.timeout!=NULL) {
183 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_TIMEOUT));
186 if (sch_thread_data->scheduler_ops.signal!=NULL) {
187 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_SIGNAL));
189 // set the event mask
190 CHK(posix_appschedattr_seteventmask(&event_set));
192 // invoke the init entry point
193 sch_thread_data->scheduler_ops.init(scheduler_data,
194 sch_thread_data->init_args);
196 // clear the scheduling actions data structure
197 CHK(posix_appsched_actions_init(&(sched_actions.actions)));
198 sched_actions.timeout_ptr=NULL;
199 sched_actions.rejected=false;
200 sched_actions.activated=false;
201 sched_actions.suspended=false;
203 // lock the scheduler mutex
204 CHK(pthread_mutex_lock(&(sch_thread_data->sch_mutex)));
206 // main scheduler loop
209 // copy the set of signals to be handled with mutex locked
210 copy_of_signalset=sch_thread_data->sch_signal_set;
212 // unlock the scheduler mutex before waiting
213 CHK(pthread_mutex_lock(&(sch_thread_data->sch_mutex)));
215 // execute pending scheduling actions and wait for next event
216 err=posix_appsched_execute_actions
217 (&(sched_actions.actions),©_of_signalset,
218 sched_actions.timeout_ptr,¤t_time,&event);
220 sch_thread_data->scheduler_ops.appsched_error
223 FOSA_ADS_THREAD_NOT_ATTACHED,
225 } else if (err==ESRCH) {
226 sch_thread_data->scheduler_ops.appsched_error
229 FOSA_ADS_INVALID_ACTION,
233 // clear the scheduling actions data structure
234 CHK(posix_appsched_actions_init(&(sched_actions.actions)));
235 sched_actions.timeout_ptr=NULL;
236 sched_actions.rejected=false;
237 sched_actions.activated=false;
238 sched_actions.suspended=false;
240 // lock the scheduler mutex to perform scheduler operations
241 // in mutual exclusion
242 CHK(pthread_mutex_lock(&(sch_thread_data->sch_mutex)));
244 // determine which kind of event has arrived, and invoke appropriate
246 switch (event.event_code) {
247 case POSIX_APPSCHED_NEW:
248 sch_thread_data->scheduler_ops.new_thread
253 if (!sched_actions.rejected) {
254 // create a memory area for the explicit messages
255 call_info=(struct explicit_call_info *)
256 malloc(sizeof(struct explicit_call_info));
257 if (call_info==NULL) {
258 CHK(posix_appsched_actions_addreject
259 (&(sched_actions.actions),event.thread));
261 CHK(posix_appsched_actions_addaccept
262 (&(sched_actions.actions),event.thread));
263 // store the memory area in thread-specific data
264 CHK(pthread_setspecific_for
265 (schedthreaddata.msg_key,event.thread,call_info));
266 // activate the thread unless suspended or already activated
267 if (!sched_actions.suspended && !sched_actions.activated) {
268 CHK(posix_appsched_actions_addactivate
269 (&(sched_actions.actions),event.thread));
274 case POSIX_APPSCHED_TERMINATE:
275 sch_thread_data->scheduler_ops.thread_terminate
281 case POSIX_APPSCHED_READY:
282 sch_thread_data->scheduler_ops.thread_ready
287 // activate the thread unless suspended or already activated
288 if (!sched_actions.suspended && !sched_actions.activated) {
289 CHK(posix_appsched_actions_addactivate
290 (&(sched_actions.actions),event.thread));
293 case POSIX_APPSCHED_BLOCK:
294 sch_thread_data->scheduler_ops.thread_block
300 case POSIX_APPSCHED_CHANGE_SCHED_PARAM:
301 sch_thread_data->scheduler_ops.change_sched_param_thread
307 //case POSIX_APPSCHED_EXPLICIT_CALL_WITH_DATA:
308 //sch_thread_data->scheduler_ops.explicit_call_with_data
311 // event.event_info.info,event.info_size,
312 // &reply, &reply_size,
316 case POSIX_APPSCHED_EXPLICIT_CALL:
317 CHK(pthread_getspecific_from
318 (schedthreaddata.msg_key,event.thread,(void **)(&call_info)));
319 sch_thread_data->scheduler_ops.explicit_call_with_data
323 call_info->info_size,
324 call_info->reply_ptr,
325 &(call_info->reply_size),
328 // activate the thread unless suspended or already activated
329 if (!sched_actions.suspended && !sched_actions.activated) {
330 CHK(posix_appsched_actions_addactivate
331 (&(sched_actions.actions),event.thread));
334 case POSIX_APPSCHED_TASK_NOTIFICATION:
335 clk=(clockid_t) pthread_getspecific(sch_thread_data->clock_key);
336 sch_thread_data->scheduler_ops.notification_for_thread
342 // t.b.d. check if state of thread is suspended by default
344 case POSIX_APPSCHED_TIMEOUT:
345 sch_thread_data->scheduler_ops.timeout
350 case POSIX_APPSCHED_SIGNAL:
351 sch_thread_data->scheduler_ops.signal
353 event.event_info.siginfo.si_signo,
354 *((frsh_signal_info_t *) (&(event.event_info.siginfo.si_value))),
355 // the above casting construct is used to overcome the compiler
356 // restriction that does not allow casts between unions
361 ASSERT_INFO(true,"Unexpected scheduling event received in scheduler");
362 } // end switch on event code
363 } // end of main scheduler loop
369 * fosa_ads_scheduler_create()
371 * Create the application defined scheduler
373 * The application defined scheduler is created with the primitive
374 * operations specified in the object pointed to by scheduler_ops.
376 * The clock used to read the time immediately before the invocation
377 * of each primitive operation, to be reported to the scheduler via
378 * the current_time parameter of each primitive operation is the
379 * FOSA_CLOCK_REALTIME clock.
381 * The scheduler_data_size parameter is used to request that a memory
382 * area of this size must be created and reserved for the scheduler to
383 * store its state. A pointer to this area is passed to the scheduler
384 * operations in the sched_data parameter.
386 * Parameter init_arg points to an area that contains configuration
387 * information for the scheduler. The function creates a memory area
388 * of init_arg_size bytes and copies into it the area pointed by
389 * arg. A pointer to this new created area will be passed to the
390 * primitive operation init() in its arg parameter.
392 * Returns 0 if successful; otherwise it returns an error code:
393 * EINVAL: The value of scheduler_ops was invalid
394 * EAGAIN: The system lacks enough resources to create the scheduler
396 * Alternatively, in case of error the implementation is allowed to
397 * notify it to the system console and then terminate the FRSH
398 * implementation and dependant applications
400 * The fosa_ads_scheduler_create function must be called before any
401 * other function in this header file
403 int fosa_ads_scheduler_create
404 (const fosa_ads_scheduler_ops_t * scheduler_ops,
405 size_t scheduler_data_size,
407 size_t init_args_size)
410 pthread_mutexattr_t mattr;
412 struct sched_param param;
414 #ifdef FULL_ERROR_CHECKING
415 // check for NULL scheduler operations
416 if (scheduler_ops==NULL) {
419 #endif // end if FULL_ERROR_CHECKING
421 // copy arguments in scheduler data
422 schedthreaddata.scheduler_ops=*scheduler_ops;
423 schedthreaddata.scheduler_data_size=scheduler_data_size;
424 schedthreaddata.init_args_size=init_args_size;
426 // create scheduler memory area
427 schedthreaddata.scheduler_data=malloc(scheduler_data_size);
428 if (schedthreaddata.scheduler_data==NULL) {
432 // create init args memory area and copy the init args
433 schedthreaddata.init_args=malloc(init_args_size);
434 if (schedthreaddata.init_args==NULL) {
437 memcpy(schedthreaddata.init_args,init_args,init_args_size);
439 // initialize the set of signals used by the scheduler to none
440 CHKE(sigemptyset(&(schedthreaddata.sch_signal_set)));
442 // initialize the mutex used to share data with the scheduler
443 CHK(pthread_mutexattr_init(&mattr));
444 // we use the priority protect protocol
445 CHK(pthread_mutexattr_setprotocol(&mattr,PTHREAD_PRIO_PROTECT));
446 // calculate the priority and set priority ceiling
447 param.sched_priority=sched_get_priority_max(SCHED_FIFO)-
448 FOSA_ADS_SCHEDULER_PRIO_DIFF;
449 CHK(pthread_mutexattr_setprioceiling(&mattr,param.sched_priority));
451 CHK(pthread_mutex_init(&(schedthreaddata.sch_mutex),&mattr));
452 CHK(pthread_mutexattr_destroy(&mattr));
454 // create the thread-specific data key for the clock id
455 CHK(pthread_key_create(&schedthreaddata.clock_key,NULL));
457 // create the thread-specific data key for the message pointers
458 CHK(pthread_key_create(&schedthreaddata.msg_key,NULL));
460 // set the attributes for the scheduler thread
461 err=pthread_attr_init(&attr);
465 CHK(pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED));
466 CHK(pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED));
467 CHK(pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED));
468 CHK(pthread_attr_setschedpolicy(&attr,SCHED_FIFO));
469 CHK(pthread_attr_setschedparam(&attr,¶m));
470 CHK(pthread_attr_setappschedulerstate(&attr,PTHREAD_APPSCHEDULER));
471 CHK(pthread_attr_setpreemptionlevel(&attr,FOSA_ADS_SCHEDULER_LEVEL));
473 // create the scheduler thread
474 return pthread_create(&scheduler_thread_id,&attr,
475 scheduler_thread_code, (void *) &schedthreaddata);
479 * fosa_thread_attr_set_appscheduled()
481 * Set the appscheduled attribute of a thread attributes object
483 * This function is used to set the appscheduled attribute in the
484 * object pointed to by attr. This attribute controls the kind of
485 * scheduling used for threads created with it. If true, the thread is
486 * scheduled by the application scheduler. If not, it is scheduled by
487 * the system under a fixed priority scheduler
489 * Returns 0 if successful; otherwise it returns an error code:
490 * EINVAL: The value of attr is invalid
492 * Alternatively, in case of error the implementation is allowed to
493 * notify it to the system console and then terminate the FRSH
494 * implementation and dependant applications
496 int fosa_thread_attr_set_appscheduled
497 (frsh_thread_attr_t *attr,
500 return pthread_attr_setschedpolicy(attr,SCHED_APP);
504 * fosa_thread_attr_get_appscheduled()
506 * Get the appscheduled attribute of a thread attributes object
508 * This function is used to get 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_get_appscheduled
522 (const frsh_thread_attr_t *attr,
525 int policy, ret_value;
527 ret_value=pthread_attr_getschedpolicy(attr,&policy);
529 if (policy==SCHED_APP) {
539 * fosa_thread_attr_set_appsched_params()
541 * Set the appsched_param attribute of a thread attributes object
543 * This function is used to set the appsched_param attribute in the
544 * object pointed to by attr. For those threads with appscheduled set
545 * to true, this attribute represents the application-specific
546 * scheduling parameters. If successful, the function shall set the
547 * size of the appsched_param attribute to the value specified by
548 * paramsize, and shall copy the scheduling parameters occupying
549 * paramsize bytes and pointed to by param into that attribute
551 * Returns 0 if successful; otherwise it returns an error code:
552 * EINVAL: The value of attr is invalid, or paramsize is less than
553 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
555 * Alternatively, in case of error the implementation is allowed to
556 * notify it to the system console and then terminate the FRSH
557 * implementation and dependant applications
559 int fosa_thread_attr_set_appsched_params
560 (frsh_thread_attr_t *attr,
564 return pthread_attr_setappschedparam(attr,param,paramsize);
568 * fosa_thread_attr_get_appsched_params()
570 * Get the appsched_param attribute of a thread attributes object
572 * This function is used to get the appsched_param attribute from the
573 * object pointed to by attr. For those threads with appscheduled set
574 * to true, this attribute represents the application-specific
575 * scheduling parameters. If successful, the function shall set the
576 * value pointed to by paramsize to the size of the appsched_param
577 * attribute, and shall copy the scheduling parameters occupying
578 * paramsize bytes into the variable pointed to by param. This
579 * variable should be capable of storing a number of bytes equal to
582 * Returns 0 if successful; otherwise it returns an error code:
583 * EINVAL: The value of attr is invalid
585 * Alternatively, in case of error the implementation is allowed to
586 * notify it to the system console and then terminate the FRSH
587 * implementation and dependant applications
589 int fosa_thread_attr_get_appsched_params
590 (const frsh_thread_attr_t *attr,
594 return pthread_attr_getappschedparam(attr,param,paramsize);
598 * fosa_ads_set_appscheduled()
600 * Dynamically set the appscheduled attribute of a thread
602 * This function is used to dynamically set the appscheduled attribute
603 * of the thread identified by thread. This attribute controls the
604 * kind of scheduling used for threads created with it. If true, the
605 * thread is scheduled by the application scheduler. If not, it is
606 * scheduled by the system under a fixed priority scheduler.
608 * Returns 0 if successful; otherwise it returns an error code:
609 * EINVAL: The value of thread is invalid
611 * EREJECT: the attachment of the thread to the frsh schehduler
612 * was rejected by the frsh scheduler possibly because of
613 * incorrect attributes, or because the requested minimum
614 * capacity cannot be guaranteed
616 * Alternatively, in case of error the implementation is allowed to
617 * notify it to the system console and then terminate the FRSH
618 * implementation and dependant applications
620 int fosa_ads_set_appscheduled
621 (frsh_thread_id_t thread,
624 int error_code, current_policy, new_policy;
625 struct sched_param param;
627 // set the application-defined scheduler thread
628 error_code=pthread_setappscheduler(thread,scheduler_thread_id);
629 if (error_code!=0) return error_code;
631 // switch to the appropriate scheduling policy
633 new_policy=SCHED_APP;
635 new_policy=SCHED_FIFO;
637 CHK(pthread_getschedparam(thread,¤t_policy,¶m));
638 if (((current_policy==SCHED_APP) && (!appscheduled)) ||
639 ((current_policy!=SCHED_APP) && appscheduled))
641 error_code=pthread_setschedparam(thread,new_policy,¶m);
647 * fosa_ads_getappscheduled()
649 * Dynamically get the appscheduled attribute of a thread
651 * This function is used to dynamically get the appscheduled attribute
652 * of the thread identified by thread. This attribute controls the
653 * kind of scheduling used for threads created with it. If true, the
654 * thread is scheduled by the application scheduler. If not, it is
655 * scheduled by the system under a fixed priority scheduler
657 * Returns 0 if successful; otherwise it returns an error code:
658 * EINVAL: The value of thread is invalid
660 * Alternatively, in case of error the implementation is allowed to
661 * notify it to the system console and then terminate the FRSH
662 * implementation and dependant applications
664 int fosa_ads_get_appscheduled
665 (frsh_thread_id_t thread,
668 int error_code, policy;
669 struct sched_param param;
671 error_code=pthread_getschedparam(thread,&policy,¶m);
675 return policy==SCHED_APP;
681 * fosa_ads_setappschedparam()
683 * Dynamically set the appsched_param attribute of a thread
685 * This function is used to dynamically set the appsched_param
686 * attribute of the thread identified by thread. For those threads
687 * with appscheduled set to true, this attribute represents the
688 * application-specific scheduling parameters. If successful, the
689 * function shall set the size of the appsched_param attribute to the
690 * value specified by paramsize, and shall copy the scheduling
691 * parameters occupying paramsize bytes and pointed to by param into
694 * Returns 0 if successful; otherwise it returns an error code:
695 * EINVAL: The value of thread is invalid, or paramsize is less than
696 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
698 * Alternatively, in case of error the implementation is allowed to
699 * notify it to the system console and then terminate the FRSH
700 * implementation and dependant applications
702 int fosa_ads_set_appsched_params
703 (frsh_thread_id_t thread,
707 return pthread_setappschedparam(thread,param,paramsize);
711 * fosa_ads_get_appsched_params()
713 * Dynamically get the appsched_param attribute of a thread
715 * This function is used to dynamically get the appsched_param
716 * attribute of the thread identified by thread. For those threads
717 * with appscheduled set to true, this attribute represents the
718 * application-specific scheduling parameters. If successful, the
719 * function shall set the variable pointed to by paramsize to the size
720 * of the appsched_param attribute, and shall copy the scheduling
721 * parameters occupying paramsize bytes into the variable pointed to
722 * by param. This variable should be capable of storing a number of
723 * bytes equal to paramsize.
725 * Returns 0 if successful; otherwise it returns an error code:
726 * EINVAL: The value of thread is invalid, or paramsize is less than
727 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
729 * Alternatively, in case of error the implementation is allowed to
730 * notify it to the system console and then terminate the FRSH
731 * implementation and dependant applications.
733 int fosa_ads_get_appsched_params
734 (frsh_thread_id_t thread,
738 return pthread_getappschedparam(thread,param,paramsize);
742 /*********************************
745 * A scheduling actions object is used to specify a series of actions
746 * to be performed by the system at the end of a scheduler primitive
747 * operation. The order of the actions added to the object shall be
750 *********************************/
753 * fosa_adsactions_add_reject()
755 * Add a reject-thread action
757 * This function adds a thread-reject action to the object referenced
758 * by sched_actions, that will serve to notify that the thread
759 * identified by thread has not been accepted by the scheduler to be
760 * scheduled by it, possibly because the thread contained invalid
761 * application scheduling attributes, or because there are not enough
762 * resources for the new thread. At the end of the new_thread()
763 * scheduler primitive operation, the parent of the rejected thread
764 * waiting on a fosa_thread_create() or the rejected thread itself
765 * waiting on a fosa_ads_set_appscheduled() function shall complete the
766 * function with an error code of EREJECT. If no reject-thread action
767 * is added during the new_thread() scheduler primitive operation, the
768 * thread is accepted to be scheduled by the scheduler and the
769 * associated fosa_thread_create() or the fosa_ads_set_appscheduled()
770 * function shall be completed without error. For the function to
771 * succeed, it has to be called from the new_thread() primitive
772 * operation and for the thread that is requesting attachment to the
775 * Returns 0 if successful; otherwise it returns an error code:
776 * ENOMEM: There is insufficient memory to add this action
777 * FOSA_EPOLICY: The thread specified by thread is not the one requesting
778 * attachment to the scheduler, or the function is not being
779 * called from the new_thread primitive operation
780 * EINVAL: The value specified by sched_actions is invalid
782 * Alternatively, in case of error the implementation is allowed to
783 * notify it to the system console and then terminate the FRSH
784 * implementation and dependant applications
786 int fosa_adsactions_add_reject(
787 fosa_ads_actions_t *sched_actions,
788 frsh_thread_id_t thread)
790 #ifdef FULL_ERROR_CHECKING
792 if (!pthread_equal(pthread_self(),scheduler_thread_id)) {
795 #endif // end if FULL_ERROR_CHECKING
797 sched_actions->rejected=true;
798 return posix_appsched_actions_addreject(&(sched_actions->actions),thread);
802 * fosa_adsactions_add_activate()
804 * Add a thread-activate action
806 * This function adds a thread-activate action to the object
807 * referenced by sched_actions. In case the thread had been previously
808 * suspended via posix_appsched_actions_addsuspend(), it will be
809 * activated at the end of the primitive operation.
811 * In those implementations that do not support urgency scheduling,
812 * the urgencu value is ignored. These implementations cannot support
813 * the frsh hierarchical scheduling module.
815 * In those implementations supporting urgency-scheduling, the action
816 * will cause the change of the urgency of the thread to the value
817 * specified in the urgency argument. Besides, if the thread was
818 * already active at the time the thread-activate action is executed,
819 * the change or urgency will imply a reordering of the thread in its
820 * priority queue, so that for threads of the same priority, those
821 * with more urgency will be scheduled before those of less urgency.
823 * Returns 0 if successful; otherwise it returns an error code:
824 * ENOMEM: There is insufficient memory to add this action
825 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
826 * attribute set to false,
827 * EINVAL: The value specified by sched_actions is invalid
829 * Alternatively, in case of error the implementation is allowed to
830 * notify it to the system console and then terminate the FRSH
831 * implementation and dependant applications
833 int fosa_adsactions_add_activate(
834 fosa_ads_actions_t *sched_actions,
835 frsh_thread_id_t thread,
836 fosa_ads_urgency_t urgency)
838 #ifdef FULL_ERROR_CHECKING
840 struct sched_param param;
843 CHK(pthread_getschedparam(thread,&policy,¶m));
844 if (policy!=SCHED_APP) {
847 #endif // end if FULL_ERROR_CHECKING
849 sched_actions->activated=true;
850 return posix_appsched_actions_addactivate(&(sched_actions->actions),thread);
854 * fosa_adsactions_add_suspend()
856 * Add a thread-suspend action
858 * This function adds a thread-suspend action to the object referenced
859 * by sched_actions, that will cause the thread identified by thread
860 * to be suspended waiting for a thread-activate action at the end of
861 * the scheduler operation. If the thread was already waiting for a
862 * thread-activate action the thread-suspend action has no effect. It
863 * is an error trying to suspend a thread that is blocked by the
866 * Returns 0 if successful; otherwise it returns an error code:
867 * ENOMEM: There is insufficient memory to add this action
868 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
869 * attribute set to false,
870 * EINVAL: The value specified by sched_actions is invalid
872 * Alternatively, in case of error the implementation is allowed to
873 * notify it to the system console and then terminate the FRSH
874 * implementation and dependant applications
876 int fosa_adsactions_add_suspend(
877 fosa_ads_actions_t *sched_actions,
878 frsh_thread_id_t thread)
880 #ifdef FULL_ERROR_CHECKING
882 struct sched_param param;
885 CHK(pthread_getschedparam(thread,&policy,¶m));
886 if (policy!=SCHED_APP) {
889 #endif // end if FULL_ERROR_CHECKING
890 sched_actions->suspended=true;
891 return posix_appsched_actions_addsuspend(&(sched_actions->actions),thread);
895 * fosa_adsactions_add_timeout()
897 * Add a timeout action
899 * This function adds a timeout action to the object referenced by
900 * sched_actions, that will cause the timeout() scheduler operation to
901 * be invoked if no other scheduler operation is invoked before
902 * timeout expires. The timeout shall expire when the clock specified by
903 * clock_id reaches the absolute time specified by the at_time
906 * Returns 0 if successful; otherwise it returns an error code:
907 * ENOMEM: There is insufficient memory to add this action
908 * EINVAL: The value specified by sched_actions is invalid
910 * Alternatively, in case of error the implementation is allowed to
911 * notify it to the system console and then terminate the FRSH
912 * implementation and dependant applications
914 int fosa_adsactions_add_timeout(
915 fosa_ads_actions_t *sched_actions,
916 fosa_clock_id_t clock_id,
917 const struct timespec *at_time)
919 sched_actions->timeout=*at_time;
920 sched_actions->timeout_ptr=&(sched_actions->timeout);
925 * fosa_adsactions_add_thread_notification()
927 * Add a timed-thread-notification action
929 * This function adds a thread-notification action associated with the
930 * thread specified in the thread argument that will cause the
931 * notification_for_thread() scheduler operation to be invoked at the
932 * time specified by at_time. This operation shall be invoked when the
933 * clock specified by clock_id reaches the absolute time specified by
934 * the at_time argument. In particular, a cpu-time clock may be used
935 * for parameter clock_id.Only one thread-notification can be active
936 * for each thread and clock. Calling the function shall remove the
937 * former thread-notification, if any, that had been programmed for
938 * the same thread and clock. A value of NULL for parameter at_time is
939 * used to cancel a previous thread-notification, if any, for the
940 * thread specified by thread and the clock specified by clock_id.
942 * Returns 0 if successful; otherwise it returns an error code:
943 * ENOMEM: There is insufficient memory to add this action
944 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
945 * attribute set to false,
946 * EINVAL: The value specified by sched_actions is invalid
948 * Alternatively, in case of error the implementation is allowed to
949 * notify it to the system console and then terminate the FRSH
950 * implementation and dependant applications
952 int fosa_adsactions_add_thread_notification(
953 fosa_ads_actions_t *sched_actions,
954 frsh_thread_id_t thread,
955 fosa_clock_id_t clock_id,
956 const struct timespec *at_time)
958 #ifdef FULL_ERROR_CHECKING
960 struct sched_param param;
963 CHK(pthread_getschedparam(thread,&policy,¶m));
964 if (policy!=SCHED_APP) {
967 #endif // end if FULL_ERROR_CHECKING
969 // the implementation uses a timer that generates a signal
970 // with the thread id encoded in the signal info
971 // the clock id is stored in thread-specific data
973 // store the clock id in thread-specific data
974 CHK(pthread_setspecific(schedthreaddata.clock_key,(void *) clock_id));
976 // t.b.d. this function is currently not used,
977 // therefore we don't implement it yet
983 * fosa_ads_set_handled_signal_set()
985 * Specifiy the set of signals that will be handled by the application
988 * This function is used to dynamically set the set of signals that
989 * are handled by the application scheduler. When a signal included
990 * in this set is generated, the signal() primitive operation of the
991 * application scheduler shall be executed. When a signal in tis set
992 * is generated, it shall always imply the execution of the signal()
993 * primitive operation, regardless of whether that signal could be
994 * accepted by some other thread. Once the signal() primitive
995 * operation is executed the signal is consumed, so no signal handlers
996 * shall be executed and no threads using a sigwait operation shall
997 * return for that particular signal instance. For this function to
998 * succeed, it has to be called from a primitive operation of a
1001 * Returns 0 if successful; otherwise it returns an error code:
1002 * FOSA_EPOLICY: The function has not been called from a scheduler
1003 * primitive operation
1004 * EINVAL: The value specified by set is invalid
1006 * Alternatively, in case of error the implementation is allowed to
1007 * notify it to the system console and then terminate the FRSH
1008 * implementation and dependant applications
1010 int fosa_ads_set_handled_signal_set(frsh_signal_t set[], int size)
1014 #ifdef FULL_ERROR_CHECKING
1016 if (!pthread_equal(pthread_self(),scheduler_thread_id)) {
1017 return FOSA_EPOLICY;
1019 #endif // end if FULL_ERROR_CHECKING
1020 // empty the signal set
1021 CHKE(sigemptyset(&(schedthreaddata.sch_signal_set)));
1022 // loop for all signals in set, to add them to the set of signals used
1024 for(i=0;i<size;i++) {
1025 CHKE(sigaddset(&(schedthreaddata.sch_signal_set),set[i]));
1032 * fosa_ads_invoke_withdata()
1034 * Explicitly invoke the scheduler, with data
1036 * This function can be used by any thread in the process to invoke
1037 * the ads scheduler or to share data with it.
1039 * If successful, the function shall cause the execution of the
1040 * primitive operation explicit_call_with_data() of the ads scheduler
1041 * with its thread parameter equal to the thread ID of the calling
1042 * thread, and its msg_size parameter equal to msg_size. In addition,
1043 * if msg_size is larger than zero, the function shall make available
1044 * to the scheduler a memory area whose contents are identical to the
1045 * memory area pointed to by msg in the msg parameter of the
1046 * explicit_call_with_data() primitive operation (note that copying
1047 * the information is not needed).
1049 * The function shall not return until the system has finished
1050 * execution of the explicit_call_with_data() primitive operation. If
1051 * the reply argument is non NULL, the memory area pointed to by the
1052 * reply parameter of explicit_call_with_data() primitive operation is
1053 * copied into the memory area pointed to by reply, and its size is
1054 * copied into the variable pointed to by reply_size. The size of the
1055 * reply information is limited to the value FOSA_ADS_SCHEDINFO_MAX.
1057 * The function shall fail if the size specified by msg_size is larger
1058 * than FOSA_ADS_SCHEDINFO_MAX. The function shall fail if primitive
1059 * operation explicit_call_with_data() is set to NULL for the ads
1062 * Returns 0 if successful; otherwise it returns an error code:
1063 * FOSA_EPOLICY: The function been called from inside a scheduler
1064 * primitive operation
1065 * EINVAL: The value of msg_size is less than zero or larger than
1066 * FOSA_ADS_SCHEDINFO_MAX
1067 * FOSA_EMASKED: The operation cannot be executed because the primitive
1068 * operation explicit_call_with_data() is set to NULL
1070 * Alternatively, in case of error the implementation is allowed to
1071 * notify it to the system console and then terminate the FRSH
1072 * implementation and dependant applications
1074 int fosa_ads_invoke_withdata
1075 (const void *msg, size_t msg_size, void *reply, size_t *reply_size)
1077 // The corresponding function in MaRTE OS is not yet implemented
1078 // We implement this function by creating a memory area for each thread
1079 // and using the invoke with no data function
1080 struct explicit_call_info * call_info;
1083 #ifdef FULL_ERROR_CHECKING
1085 if (pthread_equal(pthread_self(),scheduler_thread_id)) {
1086 return FOSA_EPOLICY;
1088 if (msg_size>FOSA_ADS_SCHEDINFO_MAX) {
1091 if (schedthreaddata.scheduler_ops.explicit_call_with_data==NULL) {
1092 return FOSA_EMASKED;
1094 #endif // end if FULL_ERROR_CHECKING
1096 call_info = (struct explicit_call_info *)
1097 pthread_getspecific(schedthreaddata.msg_key);
1098 ASSERT_INFO(call_info!=NULL,
1099 "Error in access to specific data for explicit call");
1100 if (call_info==NULL) return EINVAL;
1101 call_info->info_size=msg_size;
1102 // the following type cast is to avoid warnings, but should be OK
1103 call_info->info_ptr=(void *)msg;
1104 call_info->reply_ptr=reply;
1105 error_code=posix_appsched_invoke_scheduler(0);
1106 *reply_size=call_info->reply_size;