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 "fosa_threads_and_signals.h"
58 #include "frsh_error.h"
59 #include "frsh_fosa.h"
66 #include <sys/marte_sched_events_codes.h>
68 #include <misc/error_checks.h>
70 // Full error checking option
71 // --------------------------
72 // Uncomment the following definition if full error checking is desired
73 // Beware that this option will introduce overhead in each context switch
75 #define FULL_ERROR_CHECKING
77 /********************************
78 * Application-defined scheduling
79 ********************************/
82 * We make the following ASSUMPTIONS:
84 * - The ADS always executes in the user memory space, so we don't
85 * need to manage the memory space translation.
87 * - Only one application scheduler exists, so we don't need a
93 * Data structures for the scheduler thread
96 // data structure that is passed to the scheduler thread
97 struct scheduler_thread_data {
98 fosa_ads_scheduler_ops_t scheduler_ops; // entry points
99 size_t scheduler_data_size; // size of scheduler data
100 void * scheduler_data; // pointer to scheduler data
101 void * init_args; // pointer to init args
102 size_t init_args_size; // size of init args
103 sigset_t sch_signal_set; // set of signals used by the
105 pthread_mutex_t sch_mutex; // mutex used to share info with
107 pthread_key_t clock_key; // key to thread-specific data where
108 // a clock id is stored
109 pthread_key_t msg_key; // key to thread-specific data with
110 // a pointer to the messages for
111 // explicit invoke operations
114 // data structure used in the explicit call with data operation
115 struct explicit_call_info {
123 static struct scheduler_thread_data schedthreaddata;
124 static pthread_t scheduler_thread_id;
127 * Code of application-defined thread. The current version of MaRTE OS
128 * requires a thread to perform the scheduler actions.
129 * In the future it is expected that this thread will not be necessary.
131 void * scheduler_thread_code(void *arg) {
132 fosa_ads_actions_t sched_actions;
133 struct posix_appsched_event event;
134 struct scheduler_thread_data *sch_thread_data=
135 (struct scheduler_thread_data *) arg;
136 void * scheduler_data = sch_thread_data->scheduler_data;
137 posix_appsched_eventset_t event_set;
138 struct timespec current_time;
139 sigset_t copy_of_signalset;
140 struct explicit_call_info *call_info;
144 // set the clock to be used by the scheduler
145 CHK(posix_appschedattr_setclock(FOSA_CLOCK_REALTIME));
147 // set the timeouts to be used in the scheduler to be absolute
148 posix_appschedattr_setflags (POSIX_APPSCHED_ABSTIMEOUT);
150 // set the mask of events to mask all events except for those
151 // corresponding to non-null entry points
152 CHK(posix_appsched_fillset(&event_set));
154 if (sch_thread_data->scheduler_ops.new_thread!=NULL) {
155 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_NEW));
158 if (sch_thread_data->scheduler_ops.thread_terminate!=NULL) {
159 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_TERMINATE));
162 if (sch_thread_data->scheduler_ops.thread_ready!=NULL) {
163 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_READY));
166 if (sch_thread_data->scheduler_ops.thread_block!=NULL) {
167 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_BLOCK));
169 // change_sched_param_thread
170 if (sch_thread_data->scheduler_ops.change_sched_param_thread!=NULL) {
171 CHK(posix_appsched_delset(&event_set,
172 POSIX_APPSCHED_CHANGE_SCHED_PARAM));
174 // explicit_call_with_data
175 if (sch_thread_data->scheduler_ops.explicit_call_with_data!=NULL) {
176 CHK(posix_appsched_delset(&event_set,
177 POSIX_APPSCHED_EXPLICIT_CALL));
179 // notification_for_thread
180 if (sch_thread_data->scheduler_ops.notification_for_thread!=NULL) {
181 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_TASK_NOTIFICATION));
184 if (sch_thread_data->scheduler_ops.timeout!=NULL) {
185 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_TIMEOUT));
188 if (sch_thread_data->scheduler_ops.signal!=NULL) {
189 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_SIGNAL));
191 // set the event mask
192 CHK(posix_appschedattr_seteventmask(&event_set));
194 // invoke the init entry point
195 sch_thread_data->scheduler_ops.init(scheduler_data,
196 sch_thread_data->init_args);
198 // clear the scheduling actions data structure
199 CHK(posix_appsched_actions_init(&(sched_actions.actions)));
200 sched_actions.timeout_ptr=NULL;
201 sched_actions.rejected=false;
202 sched_actions.activated=false;
203 sched_actions.suspended=false;
205 // lock the scheduler mutex
206 CHK(pthread_mutex_lock(&(sch_thread_data->sch_mutex)));
208 // main scheduler loop
211 // copy the set of signals to be handled with mutex locked
212 copy_of_signalset=sch_thread_data->sch_signal_set;
214 // unlock the scheduler mutex before waiting
215 CHK(pthread_mutex_unlock(&(sch_thread_data->sch_mutex)));
217 // execute pending scheduling actions and wait for next event
218 err=posix_appsched_execute_actions
219 (&(sched_actions.actions),©_of_signalset,
220 sched_actions.timeout_ptr,¤t_time,&event);
222 sch_thread_data->scheduler_ops.appsched_error
225 FOSA_ADS_THREAD_NOT_ATTACHED,
227 } else if (err==ESRCH) {
228 sch_thread_data->scheduler_ops.appsched_error
231 FOSA_ADS_INVALID_ACTION,
235 // clear the scheduling actions data structure
236 CHK(posix_appsched_actions_init(&(sched_actions.actions)));
237 sched_actions.timeout_ptr=NULL;
238 sched_actions.rejected=false;
239 sched_actions.activated=false;
240 sched_actions.suspended=false;
242 // lock the scheduler mutex to perform scheduler operations
243 // in mutual exclusion
244 CHK(pthread_mutex_lock(&(sch_thread_data->sch_mutex)));
246 // determine which kind of event has arrived, and invoke appropriate
248 switch (event.event_code) {
249 case POSIX_APPSCHED_NEW:
250 sch_thread_data->scheduler_ops.new_thread
255 if (!sched_actions.rejected) {
256 // create a memory area for the explicit messages
257 call_info=(struct explicit_call_info *)
258 malloc(sizeof(struct explicit_call_info));
259 if (call_info==NULL) {
260 CHK(posix_appsched_actions_addreject
261 (&(sched_actions.actions),event.thread));
263 CHK(posix_appsched_actions_addaccept
264 (&(sched_actions.actions),event.thread));
265 // store the memory area in thread-specific data
266 CHK(pthread_setspecific_for
267 (schedthreaddata.msg_key,event.thread,call_info));
268 // activate the thread unless suspended or already activated
269 if (!sched_actions.suspended && !sched_actions.activated) {
270 CHK(posix_appsched_actions_addactivate
271 (&(sched_actions.actions),event.thread));
276 case POSIX_APPSCHED_TERMINATE:
277 sch_thread_data->scheduler_ops.thread_terminate
283 case POSIX_APPSCHED_READY:
284 sch_thread_data->scheduler_ops.thread_ready
289 // activate the thread unless suspended or already activated
290 if (!sched_actions.suspended && !sched_actions.activated) {
291 CHK(posix_appsched_actions_addactivate
292 (&(sched_actions.actions),event.thread));
295 case POSIX_APPSCHED_BLOCK:
296 sch_thread_data->scheduler_ops.thread_block
302 case POSIX_APPSCHED_CHANGE_SCHED_PARAM:
303 sch_thread_data->scheduler_ops.change_sched_param_thread
309 //case POSIX_APPSCHED_EXPLICIT_CALL_WITH_DATA:
310 //sch_thread_data->scheduler_ops.explicit_call_with_data
313 // event.event_info.info,event.info_size,
314 // &reply, &reply_size,
318 case POSIX_APPSCHED_EXPLICIT_CALL:
319 CHK(pthread_getspecific_from
320 (schedthreaddata.msg_key,event.thread,(void **)(&call_info)));
321 sch_thread_data->scheduler_ops.explicit_call_with_data
325 call_info->info_size,
326 call_info->reply_ptr,
327 &(call_info->reply_size),
330 // activate the thread unless suspended or already activated
331 if (!sched_actions.suspended && !sched_actions.activated) {
332 CHK(posix_appsched_actions_addactivate
333 (&(sched_actions.actions),event.thread));
336 case POSIX_APPSCHED_TASK_NOTIFICATION:
337 clk=(clockid_t) pthread_getspecific(sch_thread_data->clock_key);
338 sch_thread_data->scheduler_ops.notification_for_thread
344 // t.b.d. check if state of thread is suspended by default
346 case POSIX_APPSCHED_TIMEOUT:
347 sch_thread_data->scheduler_ops.timeout
352 case POSIX_APPSCHED_SIGNAL:
353 sch_thread_data->scheduler_ops.signal
355 event.event_info.siginfo.si_signo,
356 *((frsh_signal_info_t *) (&(event.event_info.siginfo.si_value))),
357 // the above casting construct is used to overcome the compiler
358 // restriction that does not allow casts between unions
363 ASSERT_INFO(true,"Unexpected scheduling event received in scheduler");
364 } // end switch on event code
365 } // end of main scheduler loop
371 * fosa_ads_scheduler_create()
373 * Create the application defined scheduler
375 * The application defined scheduler is created with the primitive
376 * operations specified in the object pointed to by scheduler_ops.
378 * The clock used to read the time immediately before the invocation
379 * of each primitive operation, to be reported to the scheduler via
380 * the current_time parameter of each primitive operation is the
381 * FOSA_CLOCK_REALTIME clock.
383 * The scheduler_data_size parameter is used to request that a memory
384 * area of this size must be created and reserved for the scheduler to
385 * store its state. A pointer to this area is passed to the scheduler
386 * operations in the sched_data parameter.
388 * Parameter init_arg points to an area that contains configuration
389 * information for the scheduler. The function creates a memory area
390 * of init_arg_size bytes and copies into it the area pointed by
391 * arg. A pointer to this new created area will be passed to the
392 * primitive operation init() in its arg parameter.
394 * Returns 0 if successful; otherwise it returns an error code:
395 * EINVAL: The value of scheduler_ops was invalid
396 * EAGAIN: The system lacks enough resources to create the scheduler
398 * Alternatively, in case of error the implementation is allowed to
399 * notify it to the system console and then terminate the FRSH
400 * implementation and dependant applications
402 * The fosa_ads_scheduler_create function must be called before any
403 * other function in this header file
405 int fosa_ads_scheduler_create
406 (const fosa_ads_scheduler_ops_t * scheduler_ops,
407 size_t scheduler_data_size,
409 size_t init_args_size)
412 pthread_mutexattr_t mattr;
414 struct sched_param param;
416 #ifdef FULL_ERROR_CHECKING
417 // check for NULL scheduler operations
418 if (scheduler_ops==NULL) {
421 #endif // end if FULL_ERROR_CHECKING
423 // copy arguments in scheduler data
424 schedthreaddata.scheduler_ops=*scheduler_ops;
425 schedthreaddata.scheduler_data_size=scheduler_data_size;
426 schedthreaddata.init_args_size=init_args_size;
428 // create scheduler memory area
429 schedthreaddata.scheduler_data=malloc(scheduler_data_size);
430 if (schedthreaddata.scheduler_data==NULL) {
434 // create init args memory area and copy the init args
435 schedthreaddata.init_args=malloc(init_args_size);
436 if (schedthreaddata.init_args==NULL) {
439 memcpy(schedthreaddata.init_args,init_args,init_args_size);
441 // initialize the set of signals used by the scheduler to none
442 CHKE(sigemptyset(&(schedthreaddata.sch_signal_set)));
444 // initialize the mutex used to share data with the scheduler
445 CHK(pthread_mutexattr_init(&mattr));
446 // we use the priority protect protocol
447 CHK(pthread_mutexattr_setprotocol(&mattr,PTHREAD_PRIO_PROTECT));
448 // calculate the priority and set priority ceiling
449 param.sched_priority=sched_get_priority_max(SCHED_FIFO)-
450 FOSA_ADS_SCHEDULER_PRIO_DIFF;
451 CHK(pthread_mutexattr_setprioceiling(&mattr,param.sched_priority));
453 CHK(pthread_mutex_init(&(schedthreaddata.sch_mutex),&mattr));
454 CHK(pthread_mutexattr_destroy(&mattr));
456 // create the thread-specific data key for the clock id
457 CHK(pthread_key_create(&schedthreaddata.clock_key,NULL));
459 // create the thread-specific data key for the message pointers
460 CHK(pthread_key_create(&schedthreaddata.msg_key,NULL));
462 // set the attributes for the scheduler thread
463 err=pthread_attr_init(&attr);
467 CHK(pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED));
468 CHK(pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED));
469 CHK(pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED));
470 CHK(pthread_attr_setschedpolicy(&attr,SCHED_FIFO));
471 CHK(pthread_attr_setschedparam(&attr,¶m));
472 CHK(pthread_attr_setappschedulerstate(&attr,PTHREAD_APPSCHEDULER));
473 CHK(pthread_attr_setpreemptionlevel(&attr,FOSA_ADS_SCHEDULER_LEVEL));
475 // create the scheduler thread
476 return pthread_create(&scheduler_thread_id,&attr,
477 scheduler_thread_code, (void *) &schedthreaddata);
481 * fosa_thread_attr_set_appscheduled()
483 * Set the appscheduled attribute of a thread attributes object
485 * This function is used to set the appscheduled attribute in the
486 * object pointed to by attr. This attribute controls the kind of
487 * scheduling used for threads created with it. If true, the thread is
488 * scheduled by the application scheduler. If not, it is scheduled by
489 * the system under a fixed priority scheduler
491 * Returns 0 if successful; otherwise it returns an error code:
492 * EINVAL: The value of attr is invalid
494 * Alternatively, in case of error the implementation is allowed to
495 * notify it to the system console and then terminate the FRSH
496 * implementation and dependant applications
498 int fosa_thread_attr_set_appscheduled
499 (frsh_thread_attr_t *attr,
504 // set the application-defined scheduler thread
505 error_code=pthread_attr_setappscheduler(attr,scheduler_thread_id);
506 if (error_code!=0) return error_code;
509 return pthread_attr_setschedpolicy(attr,SCHED_APP);
511 return pthread_attr_setschedpolicy(attr,SCHED_FIFO);
516 * fosa_thread_attr_get_appscheduled()
518 * Get the appscheduled attribute of a thread attributes object
520 * This function is used to get the appscheduled attribute in the
521 * object pointed to by attr. This attribute controls the kind of
522 * scheduling used for threads created with it. If true, the thread is
523 * scheduled by the application scheduler. If not, it is scheduled by
524 * the system under a fixed priority scheduler.
526 * Returns 0 if successful; otherwise it returns an error code:
527 * EINVAL: The value of attr is invalid
529 * Alternatively, in case of error the implementation is allowed to
530 * notify it to the system console and then terminate the FRSH
531 * implementation and dependant applications
533 int fosa_thread_attr_get_appscheduled
534 (const frsh_thread_attr_t *attr,
537 int policy, ret_value;
539 ret_value=pthread_attr_getschedpolicy(attr,&policy);
541 if (policy==SCHED_APP) {
551 * fosa_thread_attr_set_appsched_params()
553 * Set the appsched_param attribute of a thread attributes object
555 * This function is used to set the appsched_param attribute in the
556 * object pointed to by attr. For those threads with appscheduled set
557 * to true, this attribute represents the application-specific
558 * scheduling parameters. If successful, the function shall set the
559 * size of the appsched_param attribute to the value specified by
560 * paramsize, and shall copy the scheduling parameters occupying
561 * paramsize bytes and pointed to by param into that attribute
563 * Returns 0 if successful; otherwise it returns an error code:
564 * EINVAL: The value of attr is invalid, or paramsize is less than
565 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
567 * Alternatively, in case of error the implementation is allowed to
568 * notify it to the system console and then terminate the FRSH
569 * implementation and dependant applications
571 int fosa_thread_attr_set_appsched_params
572 (frsh_thread_attr_t *attr,
576 return pthread_attr_setappschedparam(attr,param,paramsize);
580 * fosa_thread_attr_get_appsched_params()
582 * Get the appsched_param attribute of a thread attributes object
584 * This function is used to get the appsched_param attribute from the
585 * object pointed to by attr. For those threads with appscheduled set
586 * to true, this attribute represents the application-specific
587 * scheduling parameters. If successful, the function shall set the
588 * value pointed to by paramsize to the size of the appsched_param
589 * attribute, and shall copy the scheduling parameters occupying
590 * paramsize bytes into the variable pointed to by param. This
591 * variable should be capable of storing a number of bytes equal to
594 * Returns 0 if successful; otherwise it returns an error code:
595 * EINVAL: The value of attr is invalid
597 * Alternatively, in case of error the implementation is allowed to
598 * notify it to the system console and then terminate the FRSH
599 * implementation and dependant applications
601 int fosa_thread_attr_get_appsched_params
602 (const frsh_thread_attr_t *attr,
606 return pthread_attr_getappschedparam(attr,param,paramsize);
610 * fosa_ads_set_appscheduled()
612 * Dynamically set the appscheduled attribute of a thread
614 * This function is used to dynamically set the appscheduled attribute
615 * of the thread identified by thread. This attribute controls the
616 * kind of scheduling used for threads created with it. If true, the
617 * thread is scheduled by the application scheduler. If not, it is
618 * scheduled by the system under a fixed priority scheduler.
620 * Returns 0 if successful; otherwise it returns an error code:
621 * EINVAL: The value of thread is invalid
623 * EREJECT: the attachment of the thread to the frsh schehduler
624 * was rejected by the frsh scheduler possibly because of
625 * incorrect attributes, or because the requested minimum
626 * capacity cannot be guaranteed
628 * Alternatively, in case of error the implementation is allowed to
629 * notify it to the system console and then terminate the FRSH
630 * implementation and dependant applications
632 int fosa_ads_set_appscheduled
633 (frsh_thread_id_t thread,
637 int current_policy, new_policy;
638 struct sched_param param;
640 // switch to the appropriate scheduling policy
641 CHK(pthread_getschedparam(thread,¤t_policy,¶m));
642 if (((current_policy==SCHED_APP) && (!appscheduled)) ||
643 ((current_policy!=SCHED_APP) && appscheduled)) {
645 new_policy=SCHED_APP;
646 // set the application-defined scheduler thread
647 error_code=pthread_setappscheduler(thread,scheduler_thread_id);
648 if (error_code!=0) return error_code;
650 new_policy=SCHED_FIFO;
652 error_code=pthread_setschedparam(thread,new_policy,¶m);
658 * fosa_ads_getappscheduled()
660 * Dynamically get the appscheduled attribute of a thread
662 * This function is used to dynamically get the appscheduled attribute
663 * of the thread identified by thread. This attribute controls the
664 * kind of scheduling used for threads created with it. If true, the
665 * thread is scheduled by the application scheduler. If not, it is
666 * scheduled by the system under a fixed priority scheduler
668 * Returns 0 if successful; otherwise it returns an error code:
669 * EINVAL: The value of thread is invalid
671 * Alternatively, in case of error the implementation is allowed to
672 * notify it to the system console and then terminate the FRSH
673 * implementation and dependant applications
675 int fosa_ads_get_appscheduled
676 (frsh_thread_id_t thread,
679 int error_code, policy;
680 struct sched_param param;
682 error_code=pthread_getschedparam(thread,&policy,¶m);
686 *appscheduled = (policy==SCHED_APP);
693 * fosa_ads_setappschedparam()
695 * Dynamically set the appsched_param attribute of a thread
697 * This function is used to dynamically set the appsched_param
698 * attribute of the thread identified by thread. For those threads
699 * with appscheduled set to true, this attribute represents the
700 * application-specific scheduling parameters. If successful, the
701 * function shall set the size of the appsched_param attribute to the
702 * value specified by paramsize, and shall copy the scheduling
703 * parameters occupying paramsize bytes and pointed to by param into
706 * Returns 0 if successful; otherwise it returns an error code:
707 * EINVAL: The value of thread is invalid, or paramsize is less than
708 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
710 * Alternatively, in case of error the implementation is allowed to
711 * notify it to the system console and then terminate the FRSH
712 * implementation and dependant applications
714 int fosa_ads_set_appsched_params
715 (frsh_thread_id_t thread,
719 return pthread_setappschedparam(thread,param,paramsize);
723 * fosa_ads_get_appsched_params()
725 * Dynamically get the appsched_param attribute of a thread
727 * This function is used to dynamically get the appsched_param
728 * attribute of the thread identified by thread. For those threads
729 * with appscheduled set to true, this attribute represents the
730 * application-specific scheduling parameters. If successful, the
731 * function shall set the variable pointed to by paramsize to the size
732 * of the appsched_param attribute, and shall copy the scheduling
733 * parameters occupying paramsize bytes into the variable pointed to
734 * by param. This variable should be capable of storing a number of
735 * bytes equal to paramsize.
737 * Returns 0 if successful; otherwise it returns an error code:
738 * EINVAL: The value of thread is invalid, or paramsize is less than
739 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
741 * Alternatively, in case of error the implementation is allowed to
742 * notify it to the system console and then terminate the FRSH
743 * implementation and dependant applications.
745 int fosa_ads_get_appsched_params
746 (frsh_thread_id_t thread,
750 return pthread_getappschedparam(thread,param,paramsize);
754 /*********************************
757 * A scheduling actions object is used to specify a series of actions
758 * to be performed by the system at the end of a scheduler primitive
759 * operation. The order of the actions added to the object shall be
762 *********************************/
765 * fosa_adsactions_add_reject()
767 * Add a reject-thread action
769 * This function adds a thread-reject action to the object referenced
770 * by sched_actions, that will serve to notify that the thread
771 * identified by thread has not been accepted by the scheduler to be
772 * scheduled by it, possibly because the thread contained invalid
773 * application scheduling attributes, or because there are not enough
774 * resources for the new thread. At the end of the new_thread()
775 * scheduler primitive operation, the parent of the rejected thread
776 * waiting on a fosa_thread_create() or the rejected thread itself
777 * waiting on a fosa_ads_set_appscheduled() function shall complete the
778 * function with an error code of EREJECT. If no reject-thread action
779 * is added during the new_thread() scheduler primitive operation, the
780 * thread is accepted to be scheduled by the scheduler and the
781 * associated fosa_thread_create() or the fosa_ads_set_appscheduled()
782 * function shall be completed without error. For the function to
783 * succeed, it has to be called from the new_thread() primitive
784 * operation and for the thread that is requesting attachment to the
787 * Returns 0 if successful; otherwise it returns an error code:
788 * ENOMEM: There is insufficient memory to add this action
789 * FOSA_EPOLICY: The thread specified by thread is not the one requesting
790 * attachment to the scheduler, or the function is not being
791 * called from the new_thread primitive operation
792 * EINVAL: The value specified by sched_actions is invalid
794 * Alternatively, in case of error the implementation is allowed to
795 * notify it to the system console and then terminate the FRSH
796 * implementation and dependant applications
798 int fosa_adsactions_add_reject(
799 fosa_ads_actions_t *sched_actions,
800 frsh_thread_id_t thread)
802 #ifdef FULL_ERROR_CHECKING
804 if (!pthread_equal(pthread_self(),scheduler_thread_id)) {
807 #endif // end if FULL_ERROR_CHECKING
809 sched_actions->rejected=true;
810 return posix_appsched_actions_addreject(&(sched_actions->actions),thread);
814 * fosa_adsactions_add_activate()
816 * Add a thread-activate action
818 * This function adds a thread-activate action to the object
819 * referenced by sched_actions. In case the thread had been previously
820 * suspended via posix_appsched_actions_addsuspend(), it will be
821 * activated at the end of the primitive operation.
823 * In those implementations that do not support urgency scheduling,
824 * the urgencu value is ignored. These implementations cannot support
825 * the frsh hierarchical scheduling module.
827 * In those implementations supporting urgency-scheduling, the action
828 * will cause the change of the urgency of the thread to the value
829 * specified in the urgency argument. Besides, if the thread was
830 * already active at the time the thread-activate action is executed,
831 * the change or urgency will imply a reordering of the thread in its
832 * priority queue, so that for threads of the same priority, those
833 * with more urgency will be scheduled before those of less urgency.
835 * Returns 0 if successful; otherwise it returns an error code:
836 * ENOMEM: There is insufficient memory to add this action
837 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
838 * attribute set to false,
839 * EINVAL: The value specified by sched_actions is invalid
841 * Alternatively, in case of error the implementation is allowed to
842 * notify it to the system console and then terminate the FRSH
843 * implementation and dependant applications
845 int fosa_adsactions_add_activate(
846 fosa_ads_actions_t *sched_actions,
847 frsh_thread_id_t thread,
848 fosa_ads_urgency_t urgency)
850 #ifdef FULL_ERROR_CHECKING
852 struct sched_param param;
855 CHK(pthread_getschedparam(thread,&policy,¶m));
856 if (policy!=SCHED_APP) {
859 #endif // end if FULL_ERROR_CHECKING
861 sched_actions->activated=true;
862 return posix_appsched_actions_addactivate(&(sched_actions->actions),thread);
866 * fosa_adsactions_add_suspend()
868 * Add a thread-suspend action
870 * This function adds a thread-suspend action to the object referenced
871 * by sched_actions, that will cause the thread identified by thread
872 * to be suspended waiting for a thread-activate action at the end of
873 * the scheduler operation. If the thread was already waiting for a
874 * thread-activate action the thread-suspend action has no effect. It
875 * is an error trying to suspend a thread that is blocked by the
878 * Returns 0 if successful; otherwise it returns an error code:
879 * ENOMEM: There is insufficient memory to add this action
880 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
881 * attribute set to false,
882 * EINVAL: The value specified by sched_actions is invalid
884 * Alternatively, in case of error the implementation is allowed to
885 * notify it to the system console and then terminate the FRSH
886 * implementation and dependant applications
888 int fosa_adsactions_add_suspend(
889 fosa_ads_actions_t *sched_actions,
890 frsh_thread_id_t thread)
892 #ifdef FULL_ERROR_CHECKING
894 struct sched_param param;
897 CHK(pthread_getschedparam(thread,&policy,¶m));
898 if (policy!=SCHED_APP) {
901 #endif // end if FULL_ERROR_CHECKING
902 sched_actions->suspended=true;
903 return posix_appsched_actions_addsuspend(&(sched_actions->actions),thread);
907 * fosa_adsactions_add_timeout()
909 * Add a timeout action
911 * This function adds a timeout action to the object referenced by
912 * sched_actions, that will cause the timeout() scheduler operation to
913 * be invoked if no other scheduler operation is invoked before
914 * timeout expires. The timeout shall expire when the clock specified by
915 * clock_id reaches the absolute time specified by the at_time
918 * Returns 0 if successful; otherwise it returns an error code:
919 * ENOMEM: There is insufficient memory to add this action
920 * EINVAL: The value specified by sched_actions is invalid
922 * Alternatively, in case of error the implementation is allowed to
923 * notify it to the system console and then terminate the FRSH
924 * implementation and dependant applications
926 int fosa_adsactions_add_timeout(
927 fosa_ads_actions_t *sched_actions,
928 fosa_clock_id_t clock_id,
929 const struct timespec *at_time)
931 sched_actions->timeout=*at_time;
932 sched_actions->timeout_ptr=&(sched_actions->timeout);
937 * fosa_adsactions_add_thread_notification()
939 * Add a timed-thread-notification action
941 * This function adds a thread-notification action associated with the
942 * thread specified in the thread argument that will cause the
943 * notification_for_thread() scheduler operation to be invoked at the
944 * time specified by at_time. This operation shall be invoked when the
945 * clock specified by clock_id reaches the absolute time specified by
946 * the at_time argument. In particular, a cpu-time clock may be used
947 * for parameter clock_id.Only one thread-notification can be active
948 * for each thread and clock. Calling the function shall remove the
949 * former thread-notification, if any, that had been programmed for
950 * the same thread and clock. A value of NULL for parameter at_time is
951 * used to cancel a previous thread-notification, if any, for the
952 * thread specified by thread and the clock specified by clock_id.
954 * Returns 0 if successful; otherwise it returns an error code:
955 * ENOMEM: There is insufficient memory to add this action
956 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
957 * attribute set to false,
958 * EINVAL: The value specified by sched_actions is invalid
960 * Alternatively, in case of error the implementation is allowed to
961 * notify it to the system console and then terminate the FRSH
962 * implementation and dependant applications
964 int fosa_adsactions_add_thread_notification(
965 fosa_ads_actions_t *sched_actions,
966 frsh_thread_id_t thread,
967 fosa_clock_id_t clock_id,
968 const struct timespec *at_time)
970 #ifdef FULL_ERROR_CHECKING
972 struct sched_param param;
975 CHK(pthread_getschedparam(thread,&policy,¶m));
976 if (policy!=SCHED_APP) {
979 #endif // end if FULL_ERROR_CHECKING
981 // the implementation uses a timer that generates a signal
982 // with the thread id encoded in the signal info
983 // the clock id is stored in thread-specific data
985 // store the clock id in thread-specific data
986 CHK(pthread_setspecific(schedthreaddata.clock_key,(void *) clock_id));
988 // t.b.d. this function is currently not used,
989 // therefore we don't implement it yet
995 * fosa_ads_set_handled_signal_set()
997 * Specifiy the set of signals that will be handled by the application
1000 * This function is used to dynamically set the set of signals that
1001 * are handled by the application scheduler. When a signal included
1002 * in this set is generated, the signal() primitive operation of the
1003 * application scheduler shall be executed. When a signal in tis set
1004 * is generated, it shall always imply the execution of the signal()
1005 * primitive operation, regardless of whether that signal could be
1006 * accepted by some other thread. Once the signal() primitive
1007 * operation is executed the signal is consumed, so no signal handlers
1008 * shall be executed and no threads using a sigwait operation shall
1009 * return for that particular signal instance. For this function to
1010 * succeed, it has to be called from a primitive operation of a
1013 * Returns 0 if successful; otherwise it returns an error code:
1014 * FOSA_EPOLICY: The function has not been called from a scheduler
1015 * primitive operation
1016 * EINVAL: The value specified by set is invalid
1018 * Alternatively, in case of error the implementation is allowed to
1019 * notify it to the system console and then terminate the FRSH
1020 * implementation and dependant applications
1022 int fosa_ads_set_handled_signal_set(frsh_signal_t set[], int size)
1026 #ifdef FULL_ERROR_CHECKING
1028 if (!pthread_equal(pthread_self(),scheduler_thread_id)) {
1029 return FOSA_EPOLICY;
1031 #endif // end if FULL_ERROR_CHECKING
1032 // empty the signal set
1033 CHKE(sigemptyset(&(schedthreaddata.sch_signal_set)));
1034 // loop for all signals in set, to add them to the set of signals used
1036 for(i=0;i<size;i++) {
1037 CHKE(sigaddset(&(schedthreaddata.sch_signal_set),set[i]));
1044 * fosa_signal_queue_scheduler()
1046 * Queue a signal destinated to the scheduler
1048 * This is a special case of fosa_signal_queue() in which the
1049 * destinator is the scheduler itself. It is needed by the service
1050 * thread to notify the results to the scheduler.
1052 * The problem with this case is that, depending on the implementation,
1053 * this call would be translated to a true signal or to a scheduler
1054 * notification message.
1056 * Besides for the scheduler we don't have always a destinator
1057 * thread_id needed in frsh_signal_queue for OSE.
1059 * So the fosa implementation will solve this issue internally.
1061 * Returns 0 if successful; otherwise it returns an error code:
1062 * FOSA_EINVAL: the signal specified by signal is not
1063 * between FOSA_SIGNAL_MIN and FOSA_SIGNAL_MAX
1065 * FOSA_EAGAIN: no resources are available to queue the signal; the
1066 * maximum number of queued signals has been reached, or a
1067 * systemwide resource limit has been exceeded
1069 * Alternatively, in case of error the implementation is allowed to
1070 * notify it to the system console and then terminate the FRSH
1071 * implementation and dependant applications
1073 int fosa_signal_queue_scheduler(frsh_signal_t signal, frsh_signal_info_t info)
1075 /* In MaRTE OS this function is completely equivalent to
1076 fosa_signal_queue, because there is no notion of receiver.
1079 frsh_thread_id_t receiver = 0; /* Dummy value, not used by MaRTE OS */
1082 return fosa_signal_queue(signal, info, receiver);
1087 * fosa_ads_invoke_withdata()
1089 * Explicitly invoke the scheduler, with data
1091 * This function can be used by any thread in the process to invoke
1092 * the ads scheduler or to share data with it.
1094 * If successful, the function shall cause the execution of the
1095 * primitive operation explicit_call_with_data() of the ads scheduler
1096 * with its thread parameter equal to the thread ID of the calling
1097 * thread, and its msg_size parameter equal to msg_size. In addition,
1098 * if msg_size is larger than zero, the function shall make available
1099 * to the scheduler a memory area whose contents are identical to the
1100 * memory area pointed to by msg in the msg parameter of the
1101 * explicit_call_with_data() primitive operation (note that copying
1102 * the information is not needed).
1104 * The function shall not return until the system has finished
1105 * execution of the explicit_call_with_data() primitive operation. If
1106 * the reply argument is non NULL, the memory area pointed to by the
1107 * reply parameter of explicit_call_with_data() primitive operation is
1108 * copied into the memory area pointed to by reply, and its size is
1109 * copied into the variable pointed to by reply_size. The size of the
1110 * reply information is limited to the value FOSA_ADS_SCHEDINFO_MAX.
1112 * The function shall fail if the size specified by msg_size is larger
1113 * than FOSA_ADS_SCHEDINFO_MAX. The function shall fail if primitive
1114 * operation explicit_call_with_data() is set to NULL for the ads
1117 * Returns 0 if successful; otherwise it returns an error code:
1118 * FOSA_EPOLICY: The function been called from inside a scheduler
1119 * primitive operation
1120 * EINVAL: The value of msg_size is less than zero or larger than
1121 * FOSA_ADS_SCHEDINFO_MAX
1122 * FOSA_EMASKED: The operation cannot be executed because the primitive
1123 * operation explicit_call_with_data() is set to NULL
1125 * Alternatively, in case of error the implementation is allowed to
1126 * notify it to the system console and then terminate the FRSH
1127 * implementation and dependant applications
1129 int fosa_ads_invoke_withdata
1130 (const void *msg, size_t msg_size, void *reply, size_t *reply_size)
1132 // The corresponding function in MaRTE OS is not yet implemented
1133 // We implement this function by creating a memory area for each thread
1134 // and using the invoke with no data function
1135 struct explicit_call_info * call_info;
1138 #ifdef FULL_ERROR_CHECKING
1140 if (pthread_equal(pthread_self(),scheduler_thread_id)) {
1141 return FOSA_EPOLICY;
1143 if (msg_size>FOSA_ADS_SCHEDINFO_MAX) {
1146 if (schedthreaddata.scheduler_ops.explicit_call_with_data==NULL) {
1147 return FOSA_EMASKED;
1149 #endif // end if FULL_ERROR_CHECKING
1151 call_info = (struct explicit_call_info *)
1152 pthread_getspecific(schedthreaddata.msg_key);
1153 ASSERT_INFO(call_info!=NULL,
1154 "Error in access to specific data for explicit call");
1155 if (call_info==NULL) return EINVAL;
1156 call_info->info_size=msg_size;
1157 // the following type cast is to avoid warnings, but should be OK
1158 call_info->info_ptr=(void *)msg;
1159 call_info->reply_ptr=reply;
1160 error_code=posix_appsched_invoke_scheduler(0);
1161 *reply_size=call_info->reply_size;