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"
65 #include <sys/marte_sched_events_codes.h>
67 #include <misc/error_checks.h>
69 // Full error checking option
70 // --------------------------
71 // Uncomment the following definition if full error checking is desired
72 // Beware that this option will introduce overhead in each context switch
74 #define FULL_ERROR_CHECKING
76 /********************************
77 * Application-defined scheduling
78 ********************************/
81 * We make the following ASSUMPTIONS:
83 * - The ADS always executes in the user memory space, so we don't
84 * need to manage the memory space translation.
86 * - Only one application scheduler exists, so we don't need a
92 * Data structures for the scheduler thread
95 // data structure that is passed to the scheduler thread
96 struct scheduler_thread_data {
97 fosa_ads_scheduler_ops_t scheduler_ops; // entry points
98 size_t scheduler_data_size; // size of scheduler data
99 void * scheduler_data; // pointer to scheduler data
100 void * init_args; // pointer to init args
101 size_t init_args_size; // size of init args
102 sigset_t sch_signal_set; // set of signals used by the
104 pthread_mutex_t sch_mutex; // mutex used to share info with
106 pthread_key_t clock_key; // key to thread-specific data where
107 // a clock id is stored
108 pthread_key_t msg_key; // key to thread-specific data with
109 // a pointer to the messages for
110 // explicit invoke operations
113 // data structure used in the explicit call with data operation
114 struct explicit_call_info {
122 static struct scheduler_thread_data schedthreaddata;
123 static pthread_t scheduler_thread_id;
126 * Code of application-defined thread. The current version of MaRTE OS
127 * requires a thread to perform the scheduler actions.
128 * In the future it is expected that this thread will not be necessary.
130 void * scheduler_thread_code(void *arg) {
131 fosa_ads_actions_t sched_actions;
132 struct posix_appsched_event event;
133 struct scheduler_thread_data *sch_thread_data=
134 (struct scheduler_thread_data *) arg;
135 void * scheduler_data = sch_thread_data->scheduler_data;
136 posix_appsched_eventset_t event_set;
137 struct timespec current_time;
138 sigset_t copy_of_signalset;
139 struct explicit_call_info *call_info;
143 // set the clock to be used by the scheduler
144 CHK(posix_appschedattr_setclock(FOSA_CLOCK_REALTIME));
146 // set the timeouts to be used in the scheduler to be absolute
147 posix_appschedattr_setflags (POSIX_APPSCHED_ABSTIMEOUT);
149 // set the mask of events to mask all events except for those
150 // corresponding to non-null entry points
151 CHK(posix_appsched_fillset(&event_set));
153 if (sch_thread_data->scheduler_ops.new_thread!=NULL) {
154 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_NEW));
157 if (sch_thread_data->scheduler_ops.thread_terminate!=NULL) {
158 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_TERMINATE));
161 if (sch_thread_data->scheduler_ops.thread_ready!=NULL) {
162 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_READY));
165 if (sch_thread_data->scheduler_ops.thread_block!=NULL) {
166 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_BLOCK));
168 // change_sched_param_thread
169 if (sch_thread_data->scheduler_ops.change_sched_param_thread!=NULL) {
170 CHK(posix_appsched_delset(&event_set,
171 POSIX_APPSCHED_CHANGE_SCHED_PARAM));
173 // explicit_call_with_data
174 if (sch_thread_data->scheduler_ops.explicit_call_with_data!=NULL) {
175 CHK(posix_appsched_delset(&event_set,
176 POSIX_APPSCHED_EXPLICIT_CALL_WITH_DATA));
178 // notification_for_thread
179 if (sch_thread_data->scheduler_ops.notification_for_thread!=NULL) {
180 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_TASK_NOTIFICATION));
183 if (sch_thread_data->scheduler_ops.timeout!=NULL) {
184 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_TIMEOUT));
187 if (sch_thread_data->scheduler_ops.signal!=NULL) {
188 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_SIGNAL));
190 // set the event mask
191 CHK(posix_appschedattr_seteventmask(&event_set));
193 // invoke the init entry point
194 sch_thread_data->scheduler_ops.init(scheduler_data,
195 sch_thread_data->init_args);
197 // clear the scheduling actions data structure
198 CHK(posix_appsched_actions_init(&(sched_actions.actions)));
199 sched_actions.timeout_ptr=NULL;
200 sched_actions.rejected=false;
201 sched_actions.activated=false;
202 sched_actions.suspended=false;
204 // lock the scheduler mutex
205 CHK(pthread_mutex_lock(&(sch_thread_data->sch_mutex)));
207 // main scheduler loop
210 // copy the set of signals to be handled with mutex locked
211 copy_of_signalset=sch_thread_data->sch_signal_set;
213 // unlock the scheduler mutex before waiting
214 CHK(pthread_mutex_unlock(&(sch_thread_data->sch_mutex)));
216 // execute pending scheduling actions and wait for next event
217 err=posix_appsched_execute_actions
218 (&(sched_actions.actions),©_of_signalset,
219 sched_actions.timeout_ptr,¤t_time,&event);
221 sch_thread_data->scheduler_ops.appsched_error
224 FOSA_ADS_THREAD_NOT_ATTACHED,
226 } else if (err==ESRCH) {
227 sch_thread_data->scheduler_ops.appsched_error
230 FOSA_ADS_INVALID_ACTION,
234 // clear the scheduling actions data structure
235 CHK(posix_appsched_actions_init(&(sched_actions.actions)));
236 sched_actions.timeout_ptr=NULL;
237 sched_actions.rejected=false;
238 sched_actions.activated=false;
239 sched_actions.suspended=false;
241 // lock the scheduler mutex to perform scheduler operations
242 // in mutual exclusion
243 CHK(pthread_mutex_lock(&(sch_thread_data->sch_mutex)));
245 // determine which kind of event has arrived, and invoke appropriate
247 switch (event.event_code) {
248 case POSIX_APPSCHED_NEW:
249 sch_thread_data->scheduler_ops.new_thread
254 if (!sched_actions.rejected) {
255 // create a memory area for the explicit messages
256 call_info=(struct explicit_call_info *)
257 malloc(sizeof(struct explicit_call_info));
258 if (call_info==NULL) {
259 CHK(posix_appsched_actions_addreject
260 (&(sched_actions.actions),event.thread));
262 CHK(posix_appsched_actions_addaccept
263 (&(sched_actions.actions),event.thread));
264 // store the memory area in thread-specific data
265 CHK(pthread_setspecific_for
266 (schedthreaddata.msg_key,event.thread,call_info));
267 // activate the thread unless suspended or already activated
268 if (!sched_actions.suspended && !sched_actions.activated) {
269 CHK(posix_appsched_actions_addactivate
270 (&(sched_actions.actions),event.thread));
275 case POSIX_APPSCHED_TERMINATE:
276 sch_thread_data->scheduler_ops.thread_terminate
282 case POSIX_APPSCHED_READY:
283 sch_thread_data->scheduler_ops.thread_ready
288 // activate the thread unless suspended or already activated
289 if (!sched_actions.suspended && !sched_actions.activated) {
290 CHK(posix_appsched_actions_addactivate
291 (&(sched_actions.actions),event.thread));
294 case POSIX_APPSCHED_BLOCK:
295 sch_thread_data->scheduler_ops.thread_block
301 case POSIX_APPSCHED_CHANGE_SCHED_PARAM:
302 sch_thread_data->scheduler_ops.change_sched_param_thread
308 //case POSIX_APPSCHED_EXPLICIT_CALL_WITH_DATA:
309 //sch_thread_data->scheduler_ops.explicit_call_with_data
312 // event.event_info.info,event.info_size,
313 // &reply, &reply_size,
317 case POSIX_APPSCHED_EXPLICIT_CALL:
318 CHK(pthread_getspecific_from
319 (schedthreaddata.msg_key,event.thread,(void **)(&call_info)));
320 sch_thread_data->scheduler_ops.explicit_call_with_data
324 call_info->info_size,
325 call_info->reply_ptr,
326 &(call_info->reply_size),
329 // activate the thread unless suspended or already activated
330 if (!sched_actions.suspended && !sched_actions.activated) {
331 CHK(posix_appsched_actions_addactivate
332 (&(sched_actions.actions),event.thread));
335 case POSIX_APPSCHED_TASK_NOTIFICATION:
336 clk=(clockid_t) pthread_getspecific(sch_thread_data->clock_key);
337 sch_thread_data->scheduler_ops.notification_for_thread
343 // t.b.d. check if state of thread is suspended by default
345 case POSIX_APPSCHED_TIMEOUT:
346 sch_thread_data->scheduler_ops.timeout
351 case POSIX_APPSCHED_SIGNAL:
352 sch_thread_data->scheduler_ops.signal
354 event.event_info.siginfo.si_signo,
355 *((frsh_signal_info_t *) (&(event.event_info.siginfo.si_value))),
356 // the above casting construct is used to overcome the compiler
357 // restriction that does not allow casts between unions
362 ASSERT_INFO(true,"Unexpected scheduling event received in scheduler");
363 } // end switch on event code
364 } // end of main scheduler loop
370 * fosa_ads_scheduler_create()
372 * Create the application defined scheduler
374 * The application defined scheduler is created with the primitive
375 * operations specified in the object pointed to by scheduler_ops.
377 * The clock used to read the time immediately before the invocation
378 * of each primitive operation, to be reported to the scheduler via
379 * the current_time parameter of each primitive operation is the
380 * FOSA_CLOCK_REALTIME clock.
382 * The scheduler_data_size parameter is used to request that a memory
383 * area of this size must be created and reserved for the scheduler to
384 * store its state. A pointer to this area is passed to the scheduler
385 * operations in the sched_data parameter.
387 * Parameter init_arg points to an area that contains configuration
388 * information for the scheduler. The function creates a memory area
389 * of init_arg_size bytes and copies into it the area pointed by
390 * arg. A pointer to this new created area will be passed to the
391 * primitive operation init() in its arg parameter.
393 * Returns 0 if successful; otherwise it returns an error code:
394 * EINVAL: The value of scheduler_ops was invalid
395 * EAGAIN: The system lacks enough resources to create the scheduler
397 * Alternatively, in case of error the implementation is allowed to
398 * notify it to the system console and then terminate the FRSH
399 * implementation and dependant applications
401 * The fosa_ads_scheduler_create function must be called before any
402 * other function in this header file
404 int fosa_ads_scheduler_create
405 (const fosa_ads_scheduler_ops_t * scheduler_ops,
406 size_t scheduler_data_size,
408 size_t init_args_size)
411 pthread_mutexattr_t mattr;
413 struct sched_param param;
415 #ifdef FULL_ERROR_CHECKING
416 // check for NULL scheduler operations
417 if (scheduler_ops==NULL) {
420 #endif // end if FULL_ERROR_CHECKING
422 // copy arguments in scheduler data
423 schedthreaddata.scheduler_ops=*scheduler_ops;
424 schedthreaddata.scheduler_data_size=scheduler_data_size;
425 schedthreaddata.init_args_size=init_args_size;
427 // create scheduler memory area
428 schedthreaddata.scheduler_data=malloc(scheduler_data_size);
429 if (schedthreaddata.scheduler_data==NULL) {
433 // create init args memory area and copy the init args
434 schedthreaddata.init_args=malloc(init_args_size);
435 if (schedthreaddata.init_args==NULL) {
438 memcpy(schedthreaddata.init_args,init_args,init_args_size);
440 // initialize the set of signals used by the scheduler to none
441 CHKE(sigemptyset(&(schedthreaddata.sch_signal_set)));
443 // initialize the mutex used to share data with the scheduler
444 CHK(pthread_mutexattr_init(&mattr));
445 // we use the priority protect protocol
446 CHK(pthread_mutexattr_setprotocol(&mattr,PTHREAD_PRIO_PROTECT));
447 // calculate the priority and set priority ceiling
448 param.sched_priority=sched_get_priority_max(SCHED_FIFO)-
449 FOSA_ADS_SCHEDULER_PRIO_DIFF;
450 CHK(pthread_mutexattr_setprioceiling(&mattr,param.sched_priority));
452 CHK(pthread_mutex_init(&(schedthreaddata.sch_mutex),&mattr));
453 CHK(pthread_mutexattr_destroy(&mattr));
455 // create the thread-specific data key for the clock id
456 CHK(pthread_key_create(&schedthreaddata.clock_key,NULL));
458 // create the thread-specific data key for the message pointers
459 CHK(pthread_key_create(&schedthreaddata.msg_key,NULL));
461 // set the attributes for the scheduler thread
462 err=pthread_attr_init(&attr);
466 CHK(pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED));
467 CHK(pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED));
468 CHK(pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED));
469 CHK(pthread_attr_setschedpolicy(&attr,SCHED_FIFO));
470 CHK(pthread_attr_setschedparam(&attr,¶m));
471 CHK(pthread_attr_setappschedulerstate(&attr,PTHREAD_APPSCHEDULER));
472 CHK(pthread_attr_setpreemptionlevel(&attr,FOSA_ADS_SCHEDULER_LEVEL));
474 // create the scheduler thread
475 return pthread_create(&scheduler_thread_id,&attr,
476 scheduler_thread_code, (void *) &schedthreaddata);
480 * fosa_thread_attr_set_appscheduled()
482 * Set the appscheduled attribute of a thread attributes object
484 * This function is used to set the appscheduled attribute in the
485 * object pointed to by attr. This attribute controls the kind of
486 * scheduling used for threads created with it. If true, the thread is
487 * scheduled by the application scheduler. If not, it is scheduled by
488 * the system under a fixed priority scheduler
490 * Returns 0 if successful; otherwise it returns an error code:
491 * EINVAL: The value of attr is invalid
493 * Alternatively, in case of error the implementation is allowed to
494 * notify it to the system console and then terminate the FRSH
495 * implementation and dependant applications
497 int fosa_thread_attr_set_appscheduled
498 (frsh_thread_attr_t *attr,
503 // set the application-defined scheduler thread
504 error_code=pthread_attr_setappscheduler(attr,scheduler_thread_id);
505 if (error_code!=0) return error_code;
508 return pthread_attr_setschedpolicy(attr,SCHED_APP);
510 return pthread_attr_setschedpolicy(attr,SCHED_FIFO);
515 * fosa_thread_attr_get_appscheduled()
517 * Get the appscheduled attribute of a thread attributes object
519 * This function is used to get the appscheduled attribute in the
520 * object pointed to by attr. This attribute controls the kind of
521 * scheduling used for threads created with it. If true, the thread is
522 * scheduled by the application scheduler. If not, it is scheduled by
523 * the system under a fixed priority scheduler.
525 * Returns 0 if successful; otherwise it returns an error code:
526 * EINVAL: The value of attr is invalid
528 * Alternatively, in case of error the implementation is allowed to
529 * notify it to the system console and then terminate the FRSH
530 * implementation and dependant applications
532 int fosa_thread_attr_get_appscheduled
533 (const frsh_thread_attr_t *attr,
536 int policy, ret_value;
538 ret_value=pthread_attr_getschedpolicy(attr,&policy);
540 if (policy==SCHED_APP) {
550 * fosa_thread_attr_set_appsched_params()
552 * Set the appsched_param attribute of a thread attributes object
554 * This function is used to set the appsched_param attribute in the
555 * object pointed to by attr. For those threads with appscheduled set
556 * to true, this attribute represents the application-specific
557 * scheduling parameters. If successful, the function shall set the
558 * size of the appsched_param attribute to the value specified by
559 * paramsize, and shall copy the scheduling parameters occupying
560 * paramsize bytes and pointed to by param into that attribute
562 * Returns 0 if successful; otherwise it returns an error code:
563 * EINVAL: The value of attr is invalid, or paramsize is less than
564 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
566 * Alternatively, in case of error the implementation is allowed to
567 * notify it to the system console and then terminate the FRSH
568 * implementation and dependant applications
570 int fosa_thread_attr_set_appsched_params
571 (frsh_thread_attr_t *attr,
575 return pthread_attr_setappschedparam(attr,param,paramsize);
579 * fosa_thread_attr_get_appsched_params()
581 * Get the appsched_param attribute of a thread attributes object
583 * This function is used to get the appsched_param attribute from the
584 * object pointed to by attr. For those threads with appscheduled set
585 * to true, this attribute represents the application-specific
586 * scheduling parameters. If successful, the function shall set the
587 * value pointed to by paramsize to the size of the appsched_param
588 * attribute, and shall copy the scheduling parameters occupying
589 * paramsize bytes into the variable pointed to by param. This
590 * variable should be capable of storing a number of bytes equal to
593 * Returns 0 if successful; otherwise it returns an error code:
594 * EINVAL: The value of attr is invalid
596 * Alternatively, in case of error the implementation is allowed to
597 * notify it to the system console and then terminate the FRSH
598 * implementation and dependant applications
600 int fosa_thread_attr_get_appsched_params
601 (const frsh_thread_attr_t *attr,
605 return pthread_attr_getappschedparam(attr,param,paramsize);
609 * fosa_ads_set_appscheduled()
611 * Dynamically set the appscheduled attribute of a thread
613 * This function is used to dynamically set the appscheduled attribute
614 * of the thread identified by thread. This attribute controls the
615 * kind of scheduling used for threads created with it. If true, the
616 * thread is scheduled by the application scheduler. If not, it is
617 * scheduled by the system under a fixed priority scheduler.
619 * Returns 0 if successful; otherwise it returns an error code:
620 * EINVAL: The value of thread is invalid
622 * EREJECT: the attachment of the thread to the frsh schehduler
623 * was rejected by the frsh scheduler possibly because of
624 * incorrect attributes, or because the requested minimum
625 * capacity cannot be guaranteed
627 * Alternatively, in case of error the implementation is allowed to
628 * notify it to the system console and then terminate the FRSH
629 * implementation and dependant applications
631 int fosa_ads_set_appscheduled
632 (frsh_thread_id_t thread,
635 int error_code, current_policy, new_policy;
636 struct sched_param param;
638 // set the application-defined scheduler thread
639 error_code=pthread_setappscheduler(thread,scheduler_thread_id);
640 if (error_code!=0) return error_code;
642 // switch to the appropriate scheduling policy
644 new_policy=SCHED_APP;
646 new_policy=SCHED_FIFO;
648 CHK(pthread_getschedparam(thread,¤t_policy,¶m));
649 if (((current_policy==SCHED_APP) && (!appscheduled)) ||
650 ((current_policy!=SCHED_APP) && appscheduled))
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 return policy==SCHED_APP;
692 * fosa_ads_setappschedparam()
694 * Dynamically set the appsched_param attribute of a thread
696 * This function is used to dynamically set the appsched_param
697 * attribute of the thread identified by thread. For those threads
698 * with appscheduled set to true, this attribute represents the
699 * application-specific scheduling parameters. If successful, the
700 * function shall set the size of the appsched_param attribute to the
701 * value specified by paramsize, and shall copy the scheduling
702 * parameters occupying paramsize bytes and pointed to by param into
705 * Returns 0 if successful; otherwise it returns an error code:
706 * EINVAL: The value of thread is invalid, or paramsize is less than
707 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
709 * Alternatively, in case of error the implementation is allowed to
710 * notify it to the system console and then terminate the FRSH
711 * implementation and dependant applications
713 int fosa_ads_set_appsched_params
714 (frsh_thread_id_t thread,
718 return pthread_setappschedparam(thread,param,paramsize);
722 * fosa_ads_get_appsched_params()
724 * Dynamically get the appsched_param attribute of a thread
726 * This function is used to dynamically get the appsched_param
727 * attribute of the thread identified by thread. For those threads
728 * with appscheduled set to true, this attribute represents the
729 * application-specific scheduling parameters. If successful, the
730 * function shall set the variable pointed to by paramsize to the size
731 * of the appsched_param attribute, and shall copy the scheduling
732 * parameters occupying paramsize bytes into the variable pointed to
733 * by param. This variable should be capable of storing a number of
734 * bytes equal to paramsize.
736 * Returns 0 if successful; otherwise it returns an error code:
737 * EINVAL: The value of thread is invalid, or paramsize is less than
738 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
740 * Alternatively, in case of error the implementation is allowed to
741 * notify it to the system console and then terminate the FRSH
742 * implementation and dependant applications.
744 int fosa_ads_get_appsched_params
745 (frsh_thread_id_t thread,
749 return pthread_getappschedparam(thread,param,paramsize);
753 /*********************************
756 * A scheduling actions object is used to specify a series of actions
757 * to be performed by the system at the end of a scheduler primitive
758 * operation. The order of the actions added to the object shall be
761 *********************************/
764 * fosa_adsactions_add_reject()
766 * Add a reject-thread action
768 * This function adds a thread-reject action to the object referenced
769 * by sched_actions, that will serve to notify that the thread
770 * identified by thread has not been accepted by the scheduler to be
771 * scheduled by it, possibly because the thread contained invalid
772 * application scheduling attributes, or because there are not enough
773 * resources for the new thread. At the end of the new_thread()
774 * scheduler primitive operation, the parent of the rejected thread
775 * waiting on a fosa_thread_create() or the rejected thread itself
776 * waiting on a fosa_ads_set_appscheduled() function shall complete the
777 * function with an error code of EREJECT. If no reject-thread action
778 * is added during the new_thread() scheduler primitive operation, the
779 * thread is accepted to be scheduled by the scheduler and the
780 * associated fosa_thread_create() or the fosa_ads_set_appscheduled()
781 * function shall be completed without error. For the function to
782 * succeed, it has to be called from the new_thread() primitive
783 * operation and for the thread that is requesting attachment to the
786 * Returns 0 if successful; otherwise it returns an error code:
787 * ENOMEM: There is insufficient memory to add this action
788 * FOSA_EPOLICY: The thread specified by thread is not the one requesting
789 * attachment to the scheduler, or the function is not being
790 * called from the new_thread primitive operation
791 * EINVAL: The value specified by sched_actions is invalid
793 * Alternatively, in case of error the implementation is allowed to
794 * notify it to the system console and then terminate the FRSH
795 * implementation and dependant applications
797 int fosa_adsactions_add_reject(
798 fosa_ads_actions_t *sched_actions,
799 frsh_thread_id_t thread)
801 #ifdef FULL_ERROR_CHECKING
803 if (!pthread_equal(pthread_self(),scheduler_thread_id)) {
806 #endif // end if FULL_ERROR_CHECKING
808 sched_actions->rejected=true;
809 return posix_appsched_actions_addreject(&(sched_actions->actions),thread);
813 * fosa_adsactions_add_activate()
815 * Add a thread-activate action
817 * This function adds a thread-activate action to the object
818 * referenced by sched_actions. In case the thread had been previously
819 * suspended via posix_appsched_actions_addsuspend(), it will be
820 * activated at the end of the primitive operation.
822 * In those implementations that do not support urgency scheduling,
823 * the urgencu value is ignored. These implementations cannot support
824 * the frsh hierarchical scheduling module.
826 * In those implementations supporting urgency-scheduling, the action
827 * will cause the change of the urgency of the thread to the value
828 * specified in the urgency argument. Besides, if the thread was
829 * already active at the time the thread-activate action is executed,
830 * the change or urgency will imply a reordering of the thread in its
831 * priority queue, so that for threads of the same priority, those
832 * with more urgency will be scheduled before those of less urgency.
834 * Returns 0 if successful; otherwise it returns an error code:
835 * ENOMEM: There is insufficient memory to add this action
836 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
837 * attribute set to false,
838 * EINVAL: The value specified by sched_actions is invalid
840 * Alternatively, in case of error the implementation is allowed to
841 * notify it to the system console and then terminate the FRSH
842 * implementation and dependant applications
844 int fosa_adsactions_add_activate(
845 fosa_ads_actions_t *sched_actions,
846 frsh_thread_id_t thread,
847 fosa_ads_urgency_t urgency)
849 #ifdef FULL_ERROR_CHECKING
851 struct sched_param param;
854 CHK(pthread_getschedparam(thread,&policy,¶m));
855 if (policy!=SCHED_APP) {
858 #endif // end if FULL_ERROR_CHECKING
860 sched_actions->activated=true;
861 return posix_appsched_actions_addactivate(&(sched_actions->actions),thread);
865 * fosa_adsactions_add_suspend()
867 * Add a thread-suspend action
869 * This function adds a thread-suspend action to the object referenced
870 * by sched_actions, that will cause the thread identified by thread
871 * to be suspended waiting for a thread-activate action at the end of
872 * the scheduler operation. If the thread was already waiting for a
873 * thread-activate action the thread-suspend action has no effect. It
874 * is an error trying to suspend a thread that is blocked by the
877 * Returns 0 if successful; otherwise it returns an error code:
878 * ENOMEM: There is insufficient memory to add this action
879 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
880 * attribute set to false,
881 * EINVAL: The value specified by sched_actions is invalid
883 * Alternatively, in case of error the implementation is allowed to
884 * notify it to the system console and then terminate the FRSH
885 * implementation and dependant applications
887 int fosa_adsactions_add_suspend(
888 fosa_ads_actions_t *sched_actions,
889 frsh_thread_id_t thread)
891 #ifdef FULL_ERROR_CHECKING
893 struct sched_param param;
896 CHK(pthread_getschedparam(thread,&policy,¶m));
897 if (policy!=SCHED_APP) {
900 #endif // end if FULL_ERROR_CHECKING
901 sched_actions->suspended=true;
902 return posix_appsched_actions_addsuspend(&(sched_actions->actions),thread);
906 * fosa_adsactions_add_timeout()
908 * Add a timeout action
910 * This function adds a timeout action to the object referenced by
911 * sched_actions, that will cause the timeout() scheduler operation to
912 * be invoked if no other scheduler operation is invoked before
913 * timeout expires. The timeout shall expire when the clock specified by
914 * clock_id reaches the absolute time specified by the at_time
917 * Returns 0 if successful; otherwise it returns an error code:
918 * ENOMEM: There is insufficient memory to add this action
919 * EINVAL: The value specified by sched_actions is invalid
921 * Alternatively, in case of error the implementation is allowed to
922 * notify it to the system console and then terminate the FRSH
923 * implementation and dependant applications
925 int fosa_adsactions_add_timeout(
926 fosa_ads_actions_t *sched_actions,
927 fosa_clock_id_t clock_id,
928 const struct timespec *at_time)
930 sched_actions->timeout=*at_time;
931 sched_actions->timeout_ptr=&(sched_actions->timeout);
936 * fosa_adsactions_add_thread_notification()
938 * Add a timed-thread-notification action
940 * This function adds a thread-notification action associated with the
941 * thread specified in the thread argument that will cause the
942 * notification_for_thread() scheduler operation to be invoked at the
943 * time specified by at_time. This operation shall be invoked when the
944 * clock specified by clock_id reaches the absolute time specified by
945 * the at_time argument. In particular, a cpu-time clock may be used
946 * for parameter clock_id.Only one thread-notification can be active
947 * for each thread and clock. Calling the function shall remove the
948 * former thread-notification, if any, that had been programmed for
949 * the same thread and clock. A value of NULL for parameter at_time is
950 * used to cancel a previous thread-notification, if any, for the
951 * thread specified by thread and the clock specified by clock_id.
953 * Returns 0 if successful; otherwise it returns an error code:
954 * ENOMEM: There is insufficient memory to add this action
955 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
956 * attribute set to false,
957 * EINVAL: The value specified by sched_actions is invalid
959 * Alternatively, in case of error the implementation is allowed to
960 * notify it to the system console and then terminate the FRSH
961 * implementation and dependant applications
963 int fosa_adsactions_add_thread_notification(
964 fosa_ads_actions_t *sched_actions,
965 frsh_thread_id_t thread,
966 fosa_clock_id_t clock_id,
967 const struct timespec *at_time)
969 #ifdef FULL_ERROR_CHECKING
971 struct sched_param param;
974 CHK(pthread_getschedparam(thread,&policy,¶m));
975 if (policy!=SCHED_APP) {
978 #endif // end if FULL_ERROR_CHECKING
980 // the implementation uses a timer that generates a signal
981 // with the thread id encoded in the signal info
982 // the clock id is stored in thread-specific data
984 // store the clock id in thread-specific data
985 CHK(pthread_setspecific(schedthreaddata.clock_key,(void *) clock_id));
987 // t.b.d. this function is currently not used,
988 // therefore we don't implement it yet
994 * fosa_ads_set_handled_signal_set()
996 * Specifiy the set of signals that will be handled by the application
999 * This function is used to dynamically set the set of signals that
1000 * are handled by the application scheduler. When a signal included
1001 * in this set is generated, the signal() primitive operation of the
1002 * application scheduler shall be executed. When a signal in tis set
1003 * is generated, it shall always imply the execution of the signal()
1004 * primitive operation, regardless of whether that signal could be
1005 * accepted by some other thread. Once the signal() primitive
1006 * operation is executed the signal is consumed, so no signal handlers
1007 * shall be executed and no threads using a sigwait operation shall
1008 * return for that particular signal instance. For this function to
1009 * succeed, it has to be called from a primitive operation of a
1012 * Returns 0 if successful; otherwise it returns an error code:
1013 * FOSA_EPOLICY: The function has not been called from a scheduler
1014 * primitive operation
1015 * EINVAL: The value specified by set is invalid
1017 * Alternatively, in case of error the implementation is allowed to
1018 * notify it to the system console and then terminate the FRSH
1019 * implementation and dependant applications
1021 int fosa_ads_set_handled_signal_set(frsh_signal_t set[], int size)
1025 #ifdef FULL_ERROR_CHECKING
1027 if (!pthread_equal(pthread_self(),scheduler_thread_id)) {
1028 return FOSA_EPOLICY;
1030 #endif // end if FULL_ERROR_CHECKING
1031 // empty the signal set
1032 CHKE(sigemptyset(&(schedthreaddata.sch_signal_set)));
1033 // loop for all signals in set, to add them to the set of signals used
1035 for(i=0;i<size;i++) {
1036 CHKE(sigaddset(&(schedthreaddata.sch_signal_set),set[i]));
1043 * fosa_ads_invoke_withdata()
1045 * Explicitly invoke the scheduler, with data
1047 * This function can be used by any thread in the process to invoke
1048 * the ads scheduler or to share data with it.
1050 * If successful, the function shall cause the execution of the
1051 * primitive operation explicit_call_with_data() of the ads scheduler
1052 * with its thread parameter equal to the thread ID of the calling
1053 * thread, and its msg_size parameter equal to msg_size. In addition,
1054 * if msg_size is larger than zero, the function shall make available
1055 * to the scheduler a memory area whose contents are identical to the
1056 * memory area pointed to by msg in the msg parameter of the
1057 * explicit_call_with_data() primitive operation (note that copying
1058 * the information is not needed).
1060 * The function shall not return until the system has finished
1061 * execution of the explicit_call_with_data() primitive operation. If
1062 * the reply argument is non NULL, the memory area pointed to by the
1063 * reply parameter of explicit_call_with_data() primitive operation is
1064 * copied into the memory area pointed to by reply, and its size is
1065 * copied into the variable pointed to by reply_size. The size of the
1066 * reply information is limited to the value FOSA_ADS_SCHEDINFO_MAX.
1068 * The function shall fail if the size specified by msg_size is larger
1069 * than FOSA_ADS_SCHEDINFO_MAX. The function shall fail if primitive
1070 * operation explicit_call_with_data() is set to NULL for the ads
1073 * Returns 0 if successful; otherwise it returns an error code:
1074 * FOSA_EPOLICY: The function been called from inside a scheduler
1075 * primitive operation
1076 * EINVAL: The value of msg_size is less than zero or larger than
1077 * FOSA_ADS_SCHEDINFO_MAX
1078 * FOSA_EMASKED: The operation cannot be executed because the primitive
1079 * operation explicit_call_with_data() is set to NULL
1081 * Alternatively, in case of error the implementation is allowed to
1082 * notify it to the system console and then terminate the FRSH
1083 * implementation and dependant applications
1085 int fosa_ads_invoke_withdata
1086 (const void *msg, size_t msg_size, void *reply, size_t *reply_size)
1088 // The corresponding function in MaRTE OS is not yet implemented
1089 // We implement this function by creating a memory area for each thread
1090 // and using the invoke with no data function
1091 struct explicit_call_info * call_info;
1094 #ifdef FULL_ERROR_CHECKING
1096 if (pthread_equal(pthread_self(),scheduler_thread_id)) {
1097 return FOSA_EPOLICY;
1099 if (msg_size>FOSA_ADS_SCHEDINFO_MAX) {
1102 if (schedthreaddata.scheduler_ops.explicit_call_with_data==NULL) {
1103 return FOSA_EMASKED;
1105 #endif // end if FULL_ERROR_CHECKING
1107 call_info = (struct explicit_call_info *)
1108 pthread_getspecific(schedthreaddata.msg_key);
1109 ASSERT_INFO(call_info!=NULL,
1110 "Error in access to specific data for explicit call");
1111 if (call_info==NULL) return EINVAL;
1112 call_info->info_size=msg_size;
1113 // the following type cast is to avoid warnings, but should be OK
1114 call_info->info_ptr=(void *)msg;
1115 call_info->reply_ptr=reply;
1116 error_code=posix_appsched_invoke_scheduler(0);
1117 *reply_size=call_info->reply_size;