1 //----------------------------------------------------------------------
2 // Copyright (C) 2006 - 2007 by the FRESCOR consortium:
4 // Universidad de Cantabria, SPAIN
5 // University of York, UK
6 // Scuola Superiore Sant'Anna, ITALY
7 // Kaiserslautern University, GERMANY
8 // Univ. Politecnica Valencia, SPAIN
9 // Czech Technical University in Prague, CZECH REPUBLIC
11 // Thales Communication S.A. FRANCE
12 // Visual Tools S.A. SPAIN
13 // Rapita Systems Ltd UK
16 // See http://www.frescor.org
18 // The FRESCOR project (FP6/2005/IST/5-034026) is funded
19 // in part by the European Union Sixth Framework Programme
20 // The European Union is not liable of any use that may be
24 // based on previous work (FSF) done in the FIRST project
26 // Copyright (C) 2005 Mälardalen University, SWEDEN
27 // Scuola Superiore S.Anna, ITALY
28 // Universidad de Cantabria, SPAIN
29 // University of York, UK
31 // This file is part of FOSA (Frsh Operating System Abstraction)
33 // FOSA is free software; you can redistribute it and/or modify it
34 // under terms of the GNU General Public License as published by the
35 // Free Software Foundation; either version 2, or (at your option) any
36 // later version. FOSA is distributed in the hope that it will be
37 // useful, but WITHOUT ANY WARRANTY; without even the implied warranty
38 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39 // General Public License for more details. You should have received a
40 // copy of the GNU General Public License along with FOSA; see file
41 // COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,
42 // Cambridge, MA 02139, USA.
44 // As a special exception, including FOSA header files in a file,
45 // instantiating FOSA generics or templates, or linking other files
46 // with FOSA objects to produce an executable application, does not
47 // by itself cause the resulting executable application to be covered
48 // by the GNU General Public License. This exception does not
49 // however invalidate any other reasons why the executable file might be
50 // covered by the GNU Public License.
51 // -----------------------------------------------------------------------
52 //fosa_app_def_sched.h
53 //==============================================
54 // ******** ****** ******** **********
55 // **///// /** ** **////// /** /**
56 // ** /** ** /** /** /**
57 // ******* /** ** /********* /**********
58 // **//// /** ** ////////** /**//////**
59 // ** /** ** /** /** /**
60 // ** /** ** ******** /** /**
61 // // /******/ //////// // //
63 // FOSA(Frescor Operating System Adaptation layer)
64 //================================================
65 // 26-Jun-07 SANGORRIN: comment scheduler mutex because signal_set can only be
66 // set from the scheduler itself (don't delete because it might be useful in
69 // 25-Jun-07 SANGORRIN: when posix_appsched_execute_actions had an error code
70 // was wrong. Now we clear actions before (and added destroy operation!), then
71 // execute scheduler op and then go back to main loop (when error it continued
72 // executing the rest of actions)
74 // 10-Jul-07 SANGORRIN: in the new_thread callback we need to accept the thread
75 // before suspend or activate it.
76 // -----------------------------------------------------------------------
85 #include <sys/marte_sched_events_codes.h>
87 #include <misc/error_checks.h>
89 // Full error checking option
90 // --------------------------
91 // Uncomment the following definition if full error checking is desired
92 // Beware that this option will introduce overhead in each context switch
94 #define FULL_ERROR_CHECKING
96 /********************************
97 * Application-defined scheduling
98 ********************************/
101 * We make the following ASSUMPTIONS:
103 * - The ADS always executes in the user memory space, so we don't
104 * need to manage the memory space translation.
106 * - Only one application scheduler exists, so we don't need a
112 * Data structures for the scheduler thread
115 // data structure that is passed to the scheduler thread
116 struct scheduler_thread_data {
117 fosa_ads_scheduler_ops_t scheduler_ops; // entry points
118 size_t scheduler_data_size; // size of scheduler data
119 void * scheduler_data; // pointer to scheduler data
120 void * init_args; // pointer to init args
121 size_t init_args_size; // size of init args
122 sigset_t sch_signal_set; // set of signals used by the
124 // pthread_mutex_t sch_mutex; // mutex used to share info with
126 pthread_key_t clock_key; // key to thread-specific data where
127 // a clock id is stored
128 pthread_key_t msg_key; // key to thread-specific data with
129 // a pointer to the messages for
130 // explicit invoke operations
133 // data structure used in the explicit call with data operation
134 struct explicit_call_info {
142 static struct scheduler_thread_data schedthreaddata;
143 static pthread_t scheduler_thread_id;
146 * Code of application-defined thread. The current version of MaRTE OS
147 * requires a thread to perform the scheduler actions.
148 * In the future it is expected that this thread will not be necessary.
150 void * scheduler_thread_code(void *arg) {
151 fosa_ads_actions_t sched_actions;
152 struct posix_appsched_event event;
153 struct scheduler_thread_data *sch_thread_data=
154 (struct scheduler_thread_data *) arg;
155 void * scheduler_data = sch_thread_data->scheduler_data;
156 posix_appsched_eventset_t event_set;
157 struct timespec current_time;
158 struct explicit_call_info *call_info;
162 // set the clock to be used by the scheduler
163 CHK(posix_appschedattr_setclock(FOSA_CLOCK_REALTIME));
165 // set the timeouts to be used in the scheduler to be absolute
166 CHK(posix_appschedattr_setflags (POSIX_APPSCHED_ABSTIMEOUT));
168 // set the mask of events to mask all events except for those
169 // corresponding to non-null entry points
170 CHK(posix_appsched_fillset(&event_set));
172 if (sch_thread_data->scheduler_ops.new_thread!=NULL) {
173 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_NEW));
176 if (sch_thread_data->scheduler_ops.thread_terminate!=NULL) {
177 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_TERMINATE));
180 if (sch_thread_data->scheduler_ops.thread_ready!=NULL) {
181 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_READY));
184 if (sch_thread_data->scheduler_ops.thread_block!=NULL) {
185 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_BLOCK));
187 // change_sched_param_thread
188 if (sch_thread_data->scheduler_ops.change_sched_param_thread!=NULL) {
189 CHK(posix_appsched_delset(&event_set, POSIX_APPSCHED_CHANGE_SCHED_PARAM));
191 // explicit_call_with_data
192 if (sch_thread_data->scheduler_ops.explicit_call_with_data!=NULL) {
193 CHK(posix_appsched_delset(&event_set, POSIX_APPSCHED_EXPLICIT_CALL));
195 // notification_for_thread
196 if (sch_thread_data->scheduler_ops.notification_for_thread!=NULL) {
197 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_TASK_NOTIFICATION));
200 if (sch_thread_data->scheduler_ops.timeout!=NULL) {
201 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_TIMEOUT));
204 if (sch_thread_data->scheduler_ops.signal!=NULL) {
205 CHK(posix_appsched_delset(&event_set,POSIX_APPSCHED_SIGNAL));
207 // set the event mask
208 CHK(posix_appschedattr_seteventmask(&event_set));
210 // invoke the init entry point
211 sch_thread_data->scheduler_ops.init(scheduler_data,
212 sch_thread_data->init_args);
214 // clear the scheduling actions data structure
215 CHK(posix_appsched_actions_init(&(sched_actions.actions)));
216 sched_actions.timeout_ptr=NULL;
217 sched_actions.rejected=false;
218 sched_actions.activated=false;
219 sched_actions.suspended=false;
221 // lock the scheduler mutex
222 // CHK(pthread_mutex_lock(&(sch_thread_data->sch_mutex)));
224 // main scheduler loop
227 // NOTE: Put here code shared with app to be protected with the mutex
229 // unlock the scheduler mutex before waiting
230 // CHK(pthread_mutex_unlock(&(sch_thread_data->sch_mutex)));
232 // execute pending scheduling actions and wait for next event
233 err=posix_appsched_execute_actions
234 (&(sched_actions.actions),&(sch_thread_data->sch_signal_set),
235 sched_actions.timeout_ptr,¤t_time,&event);
237 // clear the scheduling actions data structure
238 CHK(posix_appsched_actions_destroy (&(sched_actions.actions)));
239 CHK(posix_appsched_actions_init(&(sched_actions.actions)));
240 sched_actions.timeout_ptr=NULL;
241 sched_actions.rejected=false;
242 sched_actions.activated=false;
243 sched_actions.suspended=false;
245 // lock the scheduler mutex to perform scheduler operations
246 // in mutual exclusion
247 // CHK(pthread_mutex_lock(&(sch_thread_data->sch_mutex)));
250 // determine which kind of event has arrived, and invoke appropriate
252 switch (event.event_code) {
253 case POSIX_APPSCHED_NEW:
254 sch_thread_data->scheduler_ops.new_thread
259 if (!sched_actions.rejected) {
260 // create a memory area for the explicit messages
261 call_info=(struct explicit_call_info *)
262 malloc(sizeof(struct explicit_call_info));
263 if (call_info==NULL) {
264 CHK(posix_appsched_actions_addreject
265 (&(sched_actions.actions),event.thread));
267 // clear actions, we need to accept the thread first
268 CHK(posix_appsched_actions_destroy (&(sched_actions.actions)));
269 CHK(posix_appsched_actions_init(&(sched_actions.actions)));
271 CHK(posix_appsched_actions_addaccept
272 (&(sched_actions.actions),event.thread));
273 // store the memory area in thread-specific data
274 CHK(pthread_setspecific_for
275 (schedthreaddata.msg_key,event.thread,call_info));
276 // and activate or suspend the thread
277 if (sched_actions.suspended) {
278 CHK(posix_appsched_actions_addsuspend
279 (&(sched_actions.actions),event.thread));
281 CHK(posix_appsched_actions_addactivate
282 (&(sched_actions.actions),event.thread));
287 case POSIX_APPSCHED_TERMINATE:
288 sch_thread_data->scheduler_ops.thread_terminate
294 case POSIX_APPSCHED_READY:
295 sch_thread_data->scheduler_ops.thread_ready
300 // activate the thread unless suspended or already activated
301 if (!sched_actions.suspended && !sched_actions.activated) {
302 CHK(posix_appsched_actions_addactivate
303 (&(sched_actions.actions),event.thread));
306 case POSIX_APPSCHED_BLOCK:
307 sch_thread_data->scheduler_ops.thread_block
313 case POSIX_APPSCHED_CHANGE_SCHED_PARAM:
314 sch_thread_data->scheduler_ops.change_sched_param_thread
320 //case POSIX_APPSCHED_EXPLICIT_CALL_WITH_DATA:
321 //sch_thread_data->scheduler_ops.explicit_call_with_data
324 // event.event_info.info,event.info_size,
325 // &reply, &reply_size,
328 case POSIX_APPSCHED_EXPLICIT_CALL:
329 CHK(pthread_getspecific_from
330 (schedthreaddata.msg_key,event.thread,(void **)(&call_info)));
331 sch_thread_data->scheduler_ops.explicit_call_with_data
335 call_info->info_size,
336 call_info->reply_ptr,
337 &(call_info->reply_size),
340 // activate the thread unless suspended or already activated
341 if (!sched_actions.suspended && !sched_actions.activated) {
342 CHK(posix_appsched_actions_addactivate
343 (&(sched_actions.actions),event.thread));
346 case POSIX_APPSCHED_TASK_NOTIFICATION:
347 clk=(clockid_t) pthread_getspecific(sch_thread_data->clock_key);
348 sch_thread_data->scheduler_ops.notification_for_thread
354 // t.b.d. check if state of thread is suspended by default
356 case POSIX_APPSCHED_TIMEOUT:
357 sch_thread_data->scheduler_ops.timeout
362 case POSIX_APPSCHED_SIGNAL:
363 sch_thread_data->scheduler_ops.signal
365 event.event_info.siginfo.si_signo,
366 *((fosa_signal_info_t *)(&(event.event_info.siginfo.si_value))),
367 // the above casting construct is used to overcome the compiler
368 // restriction that does not allow casts between unions
373 ASSERT_INFO(true,"Unexpected scheduling event received in scheduler");
374 } // end switch on event code
375 } else if (err==EINVAL) {
376 sch_thread_data->scheduler_ops.appsched_error
377 (scheduler_data, event.thread,
378 FOSA_ADS_THREAD_NOT_ATTACHED, &sched_actions);
379 } else if (err==ESRCH) {
380 sch_thread_data->scheduler_ops.appsched_error
381 (scheduler_data, event.thread,
382 FOSA_ADS_INVALID_ACTION, &sched_actions);
384 } // end of main scheduler loop
389 * fosa_ads_scheduler_create()
391 * Create the application defined scheduler
393 * The application defined scheduler is created with the primitive
394 * operations specified in the object pointed to by scheduler_ops.
396 * The clock used to read the time immediately before the invocation
397 * of each primitive operation, to be reported to the scheduler via
398 * the current_time parameter of each primitive operation is the
399 * FOSA_CLOCK_REALTIME clock.
401 * The scheduler_data_size parameter is used to request that a memory
402 * area of this size must be created and reserved for the scheduler to
403 * store its state. A pointer to this area is passed to the scheduler
404 * operations in the sched_data parameter.
406 * Parameter init_arg points to an area that contains configuration
407 * information for the scheduler. The function creates a memory area
408 * of init_arg_size bytes and copies into it the area pointed by
409 * arg. A pointer to this new created area will be passed to the
410 * primitive operation init() in its arg parameter.
412 * Returns 0 if successful; otherwise it returns an error code:
413 * EINVAL: The value of scheduler_ops was invalid
414 * EAGAIN: The system lacks enough resources to create the scheduler
416 * Alternatively, in case of error the implementation is allowed to
417 * notify it to the system console and then terminate the FRSH
418 * implementation and dependant applications
420 * The fosa_ads_scheduler_create function must be called before any
421 * other function in this header file
423 int fosa_ads_scheduler_create
424 (const fosa_ads_scheduler_ops_t * scheduler_ops,
425 size_t scheduler_data_size,
427 size_t init_args_size)
430 // pthread_mutexattr_t mattr;
432 struct sched_param param;
434 #ifdef FULL_ERROR_CHECKING
435 // check for NULL scheduler operations
436 if (scheduler_ops==NULL) {
439 #endif // end if FULL_ERROR_CHECKING
441 // copy arguments in scheduler data
442 schedthreaddata.scheduler_ops=*scheduler_ops;
443 schedthreaddata.scheduler_data_size=scheduler_data_size;
444 schedthreaddata.init_args_size=init_args_size;
446 // create scheduler memory area
447 schedthreaddata.scheduler_data=malloc(scheduler_data_size);
448 if (schedthreaddata.scheduler_data==NULL) {
452 // create init args memory area and copy the init args
453 schedthreaddata.init_args=malloc(init_args_size);
454 if (schedthreaddata.init_args==NULL) {
457 memcpy(schedthreaddata.init_args,init_args,init_args_size);
459 // initialize the set of signals used by the scheduler to none
460 CHKE(sigemptyset(&(schedthreaddata.sch_signal_set)));
462 // calculate the priority
463 param.sched_priority=sched_get_priority_max(SCHED_FIFO)-
464 FOSA_ADS_SCHEDULER_PRIO_DIFF;
466 // initialize the mutex used to share data with the scheduler
467 // CHK(pthread_mutexattr_init(&mattr));
468 // we use the priority protect protocol
469 // CHK(pthread_mutexattr_setprotocol(&mattr,PTHREAD_PRIO_PROTECT));
470 // set priority ceiling
471 // CHK(pthread_mutexattr_setprioceiling(&mattr,param.sched_priority));
473 // CHK(pthread_mutex_init(&(schedthreaddata.sch_mutex),&mattr));
474 // CHK(pthread_mutexattr_destroy(&mattr));
476 // create the thread-specific data key for the clock id
477 CHK(pthread_key_create(&schedthreaddata.clock_key,NULL));
479 // create the thread-specific data key for the message pointers
480 CHK(pthread_key_create(&schedthreaddata.msg_key,NULL));
482 // set the attributes for the scheduler thread
483 err=pthread_attr_init(&attr);
487 CHK(pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED));
488 CHK(pthread_attr_setinheritsched(&attr,PTHREAD_EXPLICIT_SCHED));
489 CHK(pthread_attr_setschedpolicy(&attr,SCHED_FIFO));
490 CHK(pthread_attr_setschedparam(&attr,¶m));
491 CHK(pthread_attr_setappschedulerstate(&attr,PTHREAD_APPSCHEDULER));
492 CHK(pthread_attr_setpreemptionlevel(&attr,FOSA_ADS_SCHEDULER_LEVEL));
494 // create the scheduler thread
495 return pthread_create(&scheduler_thread_id,&attr,
496 scheduler_thread_code, (void *) &schedthreaddata);
500 * fosa_thread_attr_set_appscheduled()
502 * Set the appscheduled attribute of a thread attributes object
504 * This function is used to set the appscheduled attribute in the
505 * object pointed to by attr. This attribute controls the kind of
506 * scheduling used for threads created with it. If true, the thread is
507 * scheduled by the application scheduler. If not, it is scheduled by
508 * the system under a fixed priority scheduler
510 * Returns 0 if successful; otherwise it returns an error code:
511 * EINVAL: The value of attr is invalid
513 * Alternatively, in case of error the implementation is allowed to
514 * notify it to the system console and then terminate the FRSH
515 * implementation and dependant applications
517 int fosa_thread_attr_set_appscheduled
518 (fosa_thread_attr_t *attr,
523 // set the application-defined scheduler thread
524 error_code=pthread_attr_setappscheduler(attr,scheduler_thread_id);
525 if (error_code!=0) return error_code;
528 return pthread_attr_setschedpolicy(attr,SCHED_APP);
530 return pthread_attr_setschedpolicy(attr,SCHED_FIFO);
535 * fosa_thread_attr_get_appscheduled()
537 * Get the appscheduled attribute of a thread attributes object
539 * This function is used to get the appscheduled attribute in the
540 * object pointed to by attr. This attribute controls the kind of
541 * scheduling used for threads created with it. If true, the thread is
542 * scheduled by the application scheduler. If not, it is scheduled by
543 * the system under a fixed priority scheduler.
545 * Returns 0 if successful; otherwise it returns an error code:
546 * EINVAL: The value of attr is invalid
548 * Alternatively, in case of error the implementation is allowed to
549 * notify it to the system console and then terminate the FRSH
550 * implementation and dependant applications
552 int fosa_thread_attr_get_appscheduled
553 (const fosa_thread_attr_t *attr,
556 int policy, ret_value;
558 ret_value=pthread_attr_getschedpolicy(attr,&policy);
560 if (policy==SCHED_APP) {
570 * fosa_thread_attr_set_appsched_params()
572 * Set the appsched_param attribute of a thread attributes object
574 * This function is used to set the appsched_param attribute in the
575 * object pointed to by attr. For those threads with appscheduled set
576 * to true, this attribute represents the application-specific
577 * scheduling parameters. If successful, the function shall set the
578 * size of the appsched_param attribute to the value specified by
579 * paramsize, and shall copy the scheduling parameters occupying
580 * paramsize bytes and pointed to by param into that attribute
582 * Returns 0 if successful; otherwise it returns an error code:
583 * EINVAL: The value of attr is invalid, or paramsize is less than
584 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
586 * Alternatively, in case of error the implementation is allowed to
587 * notify it to the system console and then terminate the FRSH
588 * implementation and dependant applications
590 int fosa_thread_attr_set_appsched_params
591 (fosa_thread_attr_t *attr,
595 return pthread_attr_setappschedparam(attr,param,paramsize);
599 * fosa_thread_attr_get_appsched_params()
601 * Get the appsched_param attribute of a thread attributes object
603 * This function is used to get the appsched_param attribute from the
604 * object pointed to by attr. For those threads with appscheduled set
605 * to true, this attribute represents the application-specific
606 * scheduling parameters. If successful, the function shall set the
607 * value pointed to by paramsize to the size of the appsched_param
608 * attribute, and shall copy the scheduling parameters occupying
609 * paramsize bytes into the variable pointed to by param. This
610 * variable should be capable of storing a number of bytes equal to
613 * Returns 0 if successful; otherwise it returns an error code:
614 * EINVAL: The value of attr is invalid
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_thread_attr_get_appsched_params
621 (const fosa_thread_attr_t *attr,
625 return pthread_attr_getappschedparam(attr,param,paramsize);
629 * fosa_ads_set_appscheduled()
631 * Dynamically set the appscheduled attribute of a thread
633 * This function is used to dynamically set the appscheduled attribute
634 * of the thread identified by thread. This attribute controls the
635 * kind of scheduling used for threads created with it. If true, the
636 * thread is scheduled by the application scheduler. If not, it is
637 * scheduled by the system under a fixed priority scheduler.
639 * Returns 0 if successful; otherwise it returns an error code:
640 * EINVAL: The value of thread is invalid
642 * EREJECT: the attachment of the thread to the frsh schehduler
643 * was rejected by the frsh scheduler possibly because of
644 * incorrect attributes, or because the requested minimum
645 * capacity cannot be guaranteed
647 * Alternatively, in case of error the implementation is allowed to
648 * notify it to the system console and then terminate the FRSH
649 * implementation and dependant applications
651 int fosa_ads_set_appscheduled
652 (fosa_thread_id_t thread,
656 int current_policy, new_policy;
657 struct sched_param param;
659 // switch to the appropriate scheduling policy
660 CHK(pthread_getschedparam(thread,¤t_policy,¶m));
661 if (((current_policy==SCHED_APP) && (!appscheduled)) ||
662 ((current_policy!=SCHED_APP) && appscheduled)) {
664 new_policy=SCHED_APP;
665 // set the application-defined scheduler thread
666 error_code=pthread_setappscheduler(thread,scheduler_thread_id);
667 if (error_code!=0) return error_code;
669 new_policy=SCHED_FIFO;
671 error_code=pthread_setschedparam(thread,new_policy,¶m);
677 * fosa_ads_getappscheduled()
679 * Dynamically get the appscheduled attribute of a thread
681 * This function is used to dynamically get the appscheduled attribute
682 * of the thread identified by thread. This attribute controls the
683 * kind of scheduling used for threads created with it. If true, the
684 * thread is scheduled by the application scheduler. If not, it is
685 * scheduled by the system under a fixed priority scheduler
687 * Returns 0 if successful; otherwise it returns an error code:
688 * EINVAL: The value of thread is invalid
690 * Alternatively, in case of error the implementation is allowed to
691 * notify it to the system console and then terminate the FRSH
692 * implementation and dependant applications
694 int fosa_ads_get_appscheduled
695 (fosa_thread_id_t thread,
698 int error_code, policy;
699 struct sched_param param;
701 error_code=pthread_getschedparam(thread,&policy,¶m);
705 *appscheduled = (policy==SCHED_APP);
712 * fosa_ads_setappschedparam()
714 * Dynamically set the appsched_param attribute of a thread
716 * This function is used to dynamically set the appsched_param
717 * attribute of the thread identified by thread. For those threads
718 * with appscheduled set to true, this attribute represents the
719 * application-specific scheduling parameters. If successful, the
720 * function shall set the size of the appsched_param attribute to the
721 * value specified by paramsize, and shall copy the scheduling
722 * parameters occupying paramsize bytes and pointed to by param into
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_set_appsched_params
734 (fosa_thread_id_t thread,
738 return pthread_setappschedparam(thread,param,paramsize);
742 * fosa_ads_get_appsched_params()
744 * Dynamically get the appsched_param attribute of a thread
746 * This function is used to dynamically get the appsched_param
747 * attribute of the thread identified by thread. For those threads
748 * with appscheduled set to true, this attribute represents the
749 * application-specific scheduling parameters. If successful, the
750 * function shall set the variable pointed to by paramsize to the size
751 * of the appsched_param attribute, and shall copy the scheduling
752 * parameters occupying paramsize bytes into the variable pointed to
753 * by param. This variable should be capable of storing a number of
754 * bytes equal to paramsize.
756 * Returns 0 if successful; otherwise it returns an error code:
757 * EINVAL: The value of thread is invalid, or paramsize is less than
758 * zero or larger than FOSA_ADS_SCHEDPARAM_MAX
760 * Alternatively, in case of error the implementation is allowed to
761 * notify it to the system console and then terminate the FRSH
762 * implementation and dependant applications.
764 int fosa_ads_get_appsched_params
765 (fosa_thread_id_t thread,
769 return pthread_getappschedparam(thread,param,paramsize);
773 /*********************************
776 * A scheduling actions object is used to specify a series of actions
777 * to be performed by the system at the end of a scheduler primitive
778 * operation. The order of the actions added to the object shall be
781 *********************************/
784 * fosa_adsactions_add_reject()
786 * Add a reject-thread action
788 * This function adds a thread-reject action to the object referenced
789 * by sched_actions, that will serve to notify that the thread
790 * identified by thread has not been accepted by the scheduler to be
791 * scheduled by it, possibly because the thread contained invalid
792 * application scheduling attributes, or because there are not enough
793 * resources for the new thread. At the end of the new_thread()
794 * scheduler primitive operation, the parent of the rejected thread
795 * waiting on a fosa_thread_create() or the rejected thread itself
796 * waiting on a fosa_ads_set_appscheduled() function shall complete the
797 * function with an error code of EREJECT. If no reject-thread action
798 * is added during the new_thread() scheduler primitive operation, the
799 * thread is accepted to be scheduled by the scheduler and the
800 * associated fosa_thread_create() or the fosa_ads_set_appscheduled()
801 * function shall be completed without error. For the function to
802 * succeed, it has to be called from the new_thread() primitive
803 * operation and for the thread that is requesting attachment to the
806 * Returns 0 if successful; otherwise it returns an error code:
807 * ENOMEM: There is insufficient memory to add this action
808 * FOSA_EPOLICY: The thread specified by thread is not the one requesting
809 * attachment to the scheduler, or the function is not being
810 * called from the new_thread primitive operation
811 * EINVAL: The value specified by sched_actions is invalid
813 * Alternatively, in case of error the implementation is allowed to
814 * notify it to the system console and then terminate the FRSH
815 * implementation and dependant applications
817 int fosa_adsactions_add_reject(
818 fosa_ads_actions_t *sched_actions,
819 fosa_thread_id_t thread)
821 #ifdef FULL_ERROR_CHECKING
823 if (!pthread_equal(pthread_self(),scheduler_thread_id)) {
826 #endif // end if FULL_ERROR_CHECKING
827 sched_actions->rejected=true;
828 return posix_appsched_actions_addreject(&(sched_actions->actions),thread);
832 * fosa_adsactions_add_activate()
834 * Add a thread-activate action
836 * This function adds a thread-activate action to the object
837 * referenced by sched_actions. In case the thread had been previously
838 * suspended via posix_appsched_actions_addsuspend(), it will be
839 * activated at the end of the primitive operation.
841 * In those implementations that do not support urgency scheduling,
842 * the urgencu value is ignored. These implementations cannot support
843 * the frsh hierarchical scheduling module.
845 * In those implementations supporting urgency-scheduling, the action
846 * will cause the change of the urgency of the thread to the value
847 * specified in the urgency argument. Besides, if the thread was
848 * already active at the time the thread-activate action is executed,
849 * the change or urgency will imply a reordering of the thread in its
850 * priority queue, so that for threads of the same priority, those
851 * with more urgency will be scheduled before those of less urgency.
853 * Returns 0 if successful; otherwise it returns an error code:
854 * ENOMEM: There is insufficient memory to add this action
855 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
856 * attribute set to false,
857 * EINVAL: The value specified by sched_actions is invalid
859 * Alternatively, in case of error the implementation is allowed to
860 * notify it to the system console and then terminate the FRSH
861 * implementation and dependant applications
863 int fosa_adsactions_add_activate(
864 fosa_ads_actions_t *sched_actions,
865 fosa_thread_id_t thread,
866 fosa_ads_urgency_t urgency)
868 #ifdef FULL_ERROR_CHECKING
870 struct sched_param param;
873 CHK(pthread_getschedparam(thread,&policy,¶m));
874 if (policy!=SCHED_APP) {
877 #endif // end if FULL_ERROR_CHECKING
879 sched_actions->activated=true;
880 return posix_appsched_actions_addactivate(&(sched_actions->actions),thread);
884 * fosa_adsactions_add_suspend()
886 * Add a thread-suspend action
888 * This function adds a thread-suspend action to the object referenced
889 * by sched_actions, that will cause the thread identified by thread
890 * to be suspended waiting for a thread-activate action at the end of
891 * the scheduler operation. If the thread was already waiting for a
892 * thread-activate action the thread-suspend action has no effect. It
893 * is an error trying to suspend a thread that is blocked by the
896 * Returns 0 if successful; otherwise it returns an error code:
897 * ENOMEM: There is insufficient memory to add this action
898 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
899 * attribute set to false,
900 * EINVAL: The value specified by sched_actions is invalid
902 * Alternatively, in case of error the implementation is allowed to
903 * notify it to the system console and then terminate the FRSH
904 * implementation and dependant applications
906 int fosa_adsactions_add_suspend(
907 fosa_ads_actions_t *sched_actions,
908 fosa_thread_id_t thread)
910 #ifdef FULL_ERROR_CHECKING
912 struct sched_param param;
915 CHK(pthread_getschedparam(thread,&policy,¶m));
916 if (policy!=SCHED_APP) {
919 #endif // end if FULL_ERROR_CHECKING
920 sched_actions->suspended=true;
921 return posix_appsched_actions_addsuspend(&(sched_actions->actions),thread);
925 * fosa_adsactions_add_timeout()
927 * Add a timeout action
929 * This function adds a timeout action to the object referenced by
930 * sched_actions, that will cause the timeout() scheduler operation to
931 * be invoked if no other scheduler operation is invoked before
932 * timeout expires. The timeout shall expire when the clock specified by
933 * clock_id reaches the absolute time specified by the at_time
936 * Returns 0 if successful; otherwise it returns an error code:
937 * ENOMEM: There is insufficient memory to add this action
938 * EINVAL: The value specified by sched_actions is invalid
940 * Alternatively, in case of error the implementation is allowed to
941 * notify it to the system console and then terminate the FRSH
942 * implementation and dependant applications
944 int fosa_adsactions_add_timeout(
945 fosa_ads_actions_t *sched_actions,
946 fosa_clock_id_t clock_id,
947 const struct timespec *at_time)
949 sched_actions->timeout=*at_time;
950 sched_actions->timeout_ptr=&(sched_actions->timeout);
955 * fosa_adsactions_add_thread_notification()
957 * Add a timed-thread-notification action
959 * This function adds a thread-notification action associated with the
960 * thread specified in the thread argument that will cause the
961 * notification_for_thread() scheduler operation to be invoked at the
962 * time specified by at_time. This operation shall be invoked when the
963 * clock specified by clock_id reaches the absolute time specified by
964 * the at_time argument. In particular, a cpu-time clock may be used
965 * for parameter clock_id.Only one thread-notification can be active
966 * for each thread and clock. Calling the function shall remove the
967 * former thread-notification, if any, that had been programmed for
968 * the same thread and clock. A value of NULL for parameter at_time is
969 * used to cancel a previous thread-notification, if any, for the
970 * thread specified by thread and the clock specified by clock_id.
972 * Returns 0 if successful; otherwise it returns an error code:
973 * ENOMEM: There is insufficient memory to add this action
974 * FOSA_EPOLICY: The thread specified by thread has its appscheduled
975 * attribute set to false,
976 * EINVAL: The value specified by sched_actions is invalid
978 * Alternatively, in case of error the implementation is allowed to
979 * notify it to the system console and then terminate the FRSH
980 * implementation and dependant applications
982 int fosa_adsactions_add_thread_notification(
983 fosa_ads_actions_t *sched_actions,
984 fosa_thread_id_t thread,
985 fosa_clock_id_t clock_id,
986 const struct timespec *at_time)
988 #ifdef FULL_ERROR_CHECKING
990 struct sched_param param;
993 CHK(pthread_getschedparam(thread,&policy,¶m));
994 if (policy!=SCHED_APP) {
997 #endif // end if FULL_ERROR_CHECKING
999 // the implementation uses a timer that generates a signal
1000 // with the thread id encoded in the signal info
1001 // the clock id is stored in thread-specific data
1003 // store the clock id in thread-specific data
1004 CHK(pthread_setspecific(schedthreaddata.clock_key,(void *) clock_id));
1006 // t.b.d. this function is currently not used,
1007 // therefore we don't implement it yet
1013 * fosa_ads_set_handled_signal_set()
1015 * Specifiy the set of signals that will be handled by the application
1018 * This function is used to dynamically set the set of signals that
1019 * are handled by the application scheduler. When a signal included
1020 * in this set is generated, the signal() primitive operation of the
1021 * application scheduler shall be executed. When a signal in tis set
1022 * is generated, it shall always imply the execution of the signal()
1023 * primitive operation, regardless of whether that signal could be
1024 * accepted by some other thread. Once the signal() primitive
1025 * operation is executed the signal is consumed, so no signal handlers
1026 * shall be executed and no threads using a sigwait operation shall
1027 * return for that particular signal instance. For this function to
1028 * succeed, it has to be called from a primitive operation of a
1031 * Returns 0 if successful; otherwise it returns an error code:
1032 * FOSA_EPOLICY: The function has not been called from a scheduler
1033 * primitive operation
1034 * EINVAL: The value specified by set is invalid
1036 * Alternatively, in case of error the implementation is allowed to
1037 * notify it to the system console and then terminate the FRSH
1038 * implementation and dependant applications
1040 int fosa_ads_set_handled_signal_set(fosa_signal_t set[], int size)
1044 #ifdef FULL_ERROR_CHECKING
1046 if (!pthread_equal(pthread_self(),scheduler_thread_id)) {
1047 return FOSA_EPOLICY;
1049 #endif // end if FULL_ERROR_CHECKING
1050 // empty the signal set
1051 CHKE(sigemptyset(&(schedthreaddata.sch_signal_set)));
1052 // loop for all signals in set, to add them to the set of signals used
1054 for(i=0;i<size;i++) {
1055 CHKE(sigaddset(&(schedthreaddata.sch_signal_set),set[i]));
1062 * fosa_signal_queue_scheduler()
1064 * Queue a signal destinated to the scheduler
1066 * This is a special case of fosa_signal_queue() in which the
1067 * destinator is the scheduler itself. It is needed by the service
1068 * thread to notify the results to the scheduler.
1070 * The problem with this case is that, depending on the implementation,
1071 * this call would be translated to a true signal or to a scheduler
1072 * notification message.
1074 * Besides for the scheduler we don't have always a destinator
1075 * thread_id needed in fosa_signal_queue for OSE.
1077 * So the fosa implementation will solve this issue internally.
1079 * Returns 0 if successful; otherwise it returns an error code:
1080 * FOSA_EINVAL: the signal specified by signal is not
1081 * between FOSA_SIGNAL_MIN and FOSA_SIGNAL_MAX
1083 * FOSA_EAGAIN: no resources are available to queue the signal; the
1084 * maximum number of queued signals has been reached, or a
1085 * systemwide resource limit has been exceeded
1087 * Alternatively, in case of error the implementation is allowed to
1088 * notify it to the system console and then terminate the FRSH
1089 * implementation and dependant applications
1091 int fosa_signal_queue_scheduler(fosa_signal_t signal, fosa_signal_info_t info)
1093 // In MaRTE OS this function is completely equivalent to
1094 // fosa_signal_queue, because there is no notion of receiver.
1095 fosa_thread_id_t receiver = 0; // Dummy value, not used by MaRTE OS
1096 return fosa_signal_queue(signal, info, receiver);
1100 * fosa_ads_invoke_withdata()
1102 * Explicitly invoke the scheduler, with data
1104 * This function can be used by any thread in the process to invoke
1105 * the ads scheduler or to share data with it.
1107 * If successful, the function shall cause the execution of the
1108 * primitive operation explicit_call_with_data() of the ads scheduler
1109 * with its thread parameter equal to the thread ID of the calling
1110 * thread, and its msg_size parameter equal to msg_size. In addition,
1111 * if msg_size is larger than zero, the function shall make available
1112 * to the scheduler a memory area whose contents are identical to the
1113 * memory area pointed to by msg in the msg parameter of the
1114 * explicit_call_with_data() primitive operation (note that copying
1115 * the information is not needed).
1117 * The function shall not return until the system has finished
1118 * execution of the explicit_call_with_data() primitive operation. If
1119 * the reply argument is non NULL, the memory area pointed to by the
1120 * reply parameter of explicit_call_with_data() primitive operation is
1121 * copied into the memory area pointed to by reply, and its size is
1122 * copied into the variable pointed to by reply_size. The size of the
1123 * reply information is limited to the value FOSA_ADS_SCHEDINFO_MAX.
1125 * The function shall fail if the size specified by msg_size is larger
1126 * than FOSA_ADS_SCHEDINFO_MAX. The function shall fail if primitive
1127 * operation explicit_call_with_data() is set to NULL for the ads
1130 * Returns 0 if successful; otherwise it returns an error code:
1131 * FOSA_EPOLICY: The function been called from inside a scheduler
1132 * primitive operation
1133 * EINVAL: The value of msg_size is less than zero or larger than
1134 * FOSA_ADS_SCHEDINFO_MAX
1135 * FOSA_EMASKED: The operation cannot be executed because the primitive
1136 * operation explicit_call_with_data() is set to NULL
1138 * Alternatively, in case of error the implementation is allowed to
1139 * notify it to the system console and then terminate the FRSH
1140 * implementation and dependant applications
1142 int fosa_ads_invoke_withdata
1143 (const void *msg, size_t msg_size, void *reply, size_t *reply_size)
1145 // The corresponding function in MaRTE OS is not yet implemented
1146 // We implement this function by creating a memory area for each thread
1147 // and using the invoke with no data function
1148 struct explicit_call_info * call_info;
1151 #ifdef FULL_ERROR_CHECKING
1153 if (pthread_equal(pthread_self(),scheduler_thread_id)) {
1154 return FOSA_EPOLICY;
1156 if (msg_size>FOSA_ADS_SCHEDINFO_MAX) {
1159 if (schedthreaddata.scheduler_ops.explicit_call_with_data==NULL) {
1160 return FOSA_EMASKED;
1162 #endif // end if FULL_ERROR_CHECKING
1164 call_info = (struct explicit_call_info *)
1165 pthread_getspecific(schedthreaddata.msg_key);
1166 ASSERT_INFO(call_info!=NULL,
1167 "Error in access to specific data for explicit call");
1168 if (call_info==NULL) return EINVAL;
1169 call_info->info_size=msg_size;
1170 // the following type cast is to avoid warnings, but should be OK
1171 call_info->info_ptr=(void *)msg;
1172 call_info->reply_ptr=reply;
1173 error_code=posix_appsched_invoke_scheduler(0);
1174 if (reply != NULL) {
1175 *reply_size=call_info->reply_size;