/*! * Change scheduling parameters * \param thread User level thread descriptor * \param policy Thread scheduling policy * \param param Additional scheduling parameters (when policy != SCHED_FIFO) * \return 0 */ int sys__pthread_setschedparam ( pthread_t *thread, int policy, sched_param_t *param ) { kthread_t *kthread; int retval; SYS_ENTRY(); kthread = thread->ptr; ASSERT_ERRNO_AND_EXIT ( kthread, EINVAL ); ASSERT_ERRNO_AND_EXIT ( kthread_get_id (kthread) == thread->id, ESRCH ); ASSERT_ERRNO_AND_EXIT ( kthread_is_alive (kthread), ESRCH ); ASSERT_ERRNO_AND_EXIT ( policy == SCHED_FIFO, ENOTSUP ); if ( param ) { ASSERT_ERRNO_AND_EXIT ( param->sched_priority >= THREAD_MIN_PRIO && param->sched_priority <= THREAD_MAX_PRIO, EINVAL ); } retval = kthread_setschedparam ( kthread, policy, param ); if ( retval == EXIT_SUCCESS ) SYS_EXIT ( EXIT_SUCCESS, retval ); else SYS_EXIT ( retval, EXIT_FAILURE ); }
/*! * Change scheduling parameters * \param thread User level thread descriptor * \param policy Thread scheduling policy * \param param Additional scheduling parameters (when policy != SCHED_FIFO) * \return 0 */ int sys__pthread_setschedparam ( void *p ) { pthread_t *thread; int policy; sched_param_t *param; kthread_t *kthread; thread = *( (pthread_t **) p ); p += sizeof (pthread_t *); policy = *( (int *) p ); p += sizeof (int); param = *( (sched_param_t **) p ); kthread = thread->ptr; ASSERT_ERRNO_AND_EXIT ( kthread, EINVAL ); ASSERT_ERRNO_AND_EXIT ( kthread_get_id (kthread) == thread->id, ESRCH ); ASSERT_ERRNO_AND_EXIT ( kthread_is_alive (kthread), ESRCH ); ASSERT_ERRNO_AND_EXIT ( policy >= 0 && policy < SCHED_NUM, EINVAL ); if ( param ) { ASSERT_ERRNO_AND_EXIT ( param->sched_priority >= THREAD_MIN_PRIO && param->sched_priority <= THREAD_MAX_PRIO, EINVAL ); } return kthread_setschedparam ( kthread, policy, param ); }
static int edf_set_thread_sched_parameters ( ksched_t *ksched, kthread_t *kthread, sched_supp_t *params ) { timespec_t now; itimerspec_t alarm; kthread_sched2_t *tsched = kthread_get_sched2_param ( kthread ); if ( ksched->params.edf.active == kthread ) ksched->params.edf.active = NULL; kclock_gettime ( CLOCK_REALTIME, &now ); if ( params->edf.flags & EDF_SET ) { tsched->params.edf.period = params->edf.period; tsched->params.edf.relative_deadline = params->edf.deadline; tsched->params.edf.flags = params->edf.flags ^ EDF_SET; /* create and set periodic alarm */ edf_create_alarm ( kthread, edf_period_alarm, &tsched->params.edf.period_alarm ); tsched->params.edf.next_run = now; time_add ( &tsched->params.edf.next_run, ¶ms->edf.period ); alarm.it_interval = tsched->params.edf.period; alarm.it_value = tsched->params.edf.next_run; ktimer_settime ( tsched->params.edf.period_alarm, TIMER_ABSTIME, &alarm, NULL ); /* adjust "next_run" and "deadline" for "0" period * first "edf_wait" will set correct values for first period */ tsched->params.edf.next_run = now; time_sub ( &tsched->params.edf.next_run, ¶ms->edf.period ); /* create and set deadline alarm */ edf_create_alarm ( kthread, edf_deadline_alarm, &tsched->params.edf.deadline_alarm ); tsched->params.edf.active_deadline = now; time_add ( &tsched->params.edf.active_deadline, ¶ms->edf.deadline ); TIME_RESET ( &alarm.it_interval ); alarm.it_value = tsched->params.edf.active_deadline; ktimer_settime ( tsched->params.edf.deadline_alarm, TIMER_ABSTIME, &alarm, NULL ); /* move thread to edf scheduler */ kthread_enqueue ( kthread, &ksched->params.edf.ready ); edf_schedule (ksched); } else if ( params->edf.flags & EDF_WAIT ) { if ( edf_check_deadline ( kthread ) ) return EXIT_FAILURE; /* set times for next period */ if ( time_cmp ( &now, &tsched->params.edf.next_run ) > 0 ) { time_add ( &tsched->params.edf.next_run, &tsched->params.edf.period ); tsched->params.edf.active_deadline = tsched->params.edf.next_run; time_add ( &tsched->params.edf.active_deadline, &tsched->params.edf.relative_deadline ); if ( kthread == ksched->params.edf.active ) ksched->params.edf.active = NULL; /* set (separate) alarm for deadline * (periodic alarm is set only once as periodic) */ TIME_RESET ( &alarm.it_interval ); alarm.it_value = tsched->params.edf.active_deadline; ktimer_settime ( tsched->params.edf.deadline_alarm, TIMER_ABSTIME, &alarm, NULL ); } /* is task ready for execution, or must wait until next period*/ if ( time_cmp ( &tsched->params.edf.next_run, &now ) > 0 ) { /* wait till "next_run" */ EDF_LOG ( "%x [EDF WAIT]", kthread ); kthread_enqueue ( kthread, &ksched->params.edf.wait ); edf_schedule (ksched); } else { /* "next_run" has already come, * activate task => move it to "EDF ready tasks" */ EDF_LOG ( "%x [EDF READY]", kthread ); kthread_enqueue ( kthread, &ksched->params.edf.ready ); edf_schedule (ksched); } } else if ( params->edf.flags & EDF_EXIT ) { if ( kthread == ksched->params.edf.active ) ksched->params.edf.active = NULL; if ( edf_check_deadline ( kthread ) ) { EDF_LOG ( "%x [EXIT-error]", kthread ); return EXIT_FAILURE; } EDF_LOG ( "%x [EXIT-normal]", kthread ); if ( tsched->params.edf.period_alarm ) { /* disarm timer */ TIME_RESET ( &alarm.it_interval ); TIME_RESET ( &alarm.it_value ); ktimer_settime ( tsched->params.edf.period_alarm, 0, &alarm, NULL ); } if ( tsched->params.edf.deadline_alarm ) { /* disarm timer */ TIME_RESET ( &alarm.it_interval ); TIME_RESET ( &alarm.it_value ); ktimer_settime ( tsched->params.edf.deadline_alarm, 0, &alarm, NULL ); } kthread_setschedparam ( kthread, SCHED_FIFO, NULL ); } return 0; }