diff options
-rw-r--r-- | cpukit/posix/include/rtems/posix/pthreadimpl.h | 17 | ||||
-rw-r--r-- | cpukit/posix/include/rtems/posix/threadsup.h | 26 | ||||
-rw-r--r-- | cpukit/posix/src/psxtransschedparam.c | 8 | ||||
-rw-r--r-- | cpukit/posix/src/pthread.c | 105 | ||||
-rw-r--r-- | cpukit/posix/src/pthreadcreate.c | 48 | ||||
-rw-r--r-- | cpukit/posix/src/pthreadgetschedparam.c | 7 | ||||
-rw-r--r-- | cpukit/posix/src/pthreadsetschedparam.c | 163 | ||||
-rw-r--r-- | cpukit/posix/src/pthreadsetschedprio.c | 71 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/thread.h | 2 |
9 files changed, 254 insertions, 193 deletions
diff --git a/cpukit/posix/include/rtems/posix/pthreadimpl.h b/cpukit/posix/include/rtems/posix/pthreadimpl.h index ba99392574..988246ed53 100644 --- a/cpukit/posix/include/rtems/posix/pthreadimpl.h +++ b/cpukit/posix/include/rtems/posix/pthreadimpl.h @@ -62,7 +62,7 @@ RTEMS_INLINE_ROUTINE void _POSIX_Threads_Sporadic_timer_insert( _Timespec_To_ticks( &api->Attributes.schedparam.sched_ss_init_budget ); _Watchdog_Per_CPU_insert_relative( - &api->Sporadic_timer, + &api->Sporadic.Timer, _Per_CPU_Get(), _Timespec_To_ticks( &api->Attributes.schedparam.sched_ss_repl_period ) ); @@ -81,21 +81,6 @@ void _POSIX_Threads_Sporadic_budget_callout( ); /** - * This routine supports the sporadic scheduling algorithm. It - * is scheduled to be executed at the end of each replenishment - * period. In sporadic scheduling a thread will execute at a - * high priority for a user specified amount of CPU time. When - * it exceeds that amount of CPU time, its priority is automatically - * lowered. This TSR is executed when it is time to replenish - * the thread's processor budget and raise its priority. - * - * @param[in] id is ignored - * @param[in] argument is a pointer to the Thread_Control structure - * for the thread being replenished. - */ -void _POSIX_Threads_Sporadic_budget_TSR( Watchdog_Control *watchdog ); - -/** * @brief Translate sched_param into SuperCore terms. * * This method translates the POSIX API sched_param into the corresponding diff --git a/cpukit/posix/include/rtems/posix/threadsup.h b/cpukit/posix/include/rtems/posix/threadsup.h index e18a42995a..21977be210 100644 --- a/cpukit/posix/include/rtems/posix/threadsup.h +++ b/cpukit/posix/include/rtems/posix/threadsup.h @@ -18,10 +18,7 @@ #ifndef _RTEMS_POSIX_THREADSUP_H #define _RTEMS_POSIX_THREADSUP_H -#include <rtems/score/coresem.h> -#include <rtems/score/isrlock.h> #include <rtems/score/thread.h> -#include <rtems/score/threadq.h> #include <rtems/score/watchdog.h> #include <pthread.h> @@ -50,10 +47,27 @@ typedef struct { pthread_attr_t Attributes; /** - * This is the timer which controls when the thread executes at - * high and low priority when using the sporadic scheduler. + * @brief Control block for the sporadic server scheduling policy. */ - Watchdog_Control Sporadic_timer; + struct { + /** + * @brief This is the timer which controls when the thread executes at high + * and low priority when using the sporadic server scheduling policy. + */ + Watchdog_Control Timer; + + /** + * @brief The low priority when using the sporadic server scheduling + * policy. + */ + Priority_Control low_priority; + + /** + * @brief The high priority when using the sporadic server scheduling + * policy. + */ + Priority_Control high_priority; + } Sporadic; /** This is the set of signals which are currently unblocked. */ sigset_t signals_unblocked; diff --git a/cpukit/posix/src/psxtransschedparam.c b/cpukit/posix/src/psxtransschedparam.c index 89fadde253..fb501b0717 100644 --- a/cpukit/posix/src/psxtransschedparam.c +++ b/cpukit/posix/src/psxtransschedparam.c @@ -21,9 +21,7 @@ #include <pthread.h> #include <errno.h> -#include <rtems/system.h> #include <rtems/posix/pthreadimpl.h> -#include <rtems/posix/priorityimpl.h> int _POSIX_Thread_Translate_sched_param( int policy, @@ -32,9 +30,6 @@ int _POSIX_Thread_Translate_sched_param( Thread_CPU_budget_algorithm_callout *budget_callout ) { - if ( !_POSIX_Priority_Is_valid( param->sched_priority ) ) - return EINVAL; - *budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE; *budget_callout = NULL; @@ -66,9 +61,6 @@ int _POSIX_Thread_Translate_sched_param( _Timespec_To_ticks( ¶m->sched_ss_init_budget ) ) return EINVAL; - if ( !_POSIX_Priority_Is_valid( param->sched_ss_low_priority ) ) - return EINVAL; - *budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT; *budget_callout = _POSIX_Threads_Sporadic_budget_callout; return 0; diff --git a/cpukit/posix/src/pthread.c b/cpukit/posix/src/pthread.c index ead24cf4f7..ca7efa9c7d 100644 --- a/cpukit/posix/src/pthread.c +++ b/cpukit/posix/src/pthread.c @@ -81,83 +81,57 @@ pthread_attr_t _POSIX_Threads_Default_attributes = { #endif }; -static bool _POSIX_Threads_Sporadic_budget_TSR_filter( +static bool _POSIX_Threads_Sporadic_timer_filter( Thread_Control *the_thread, - Priority_Control *new_priority, + Priority_Control *new_priority_p, void *arg ) { - the_thread->real_priority = *new_priority; + POSIX_API_Control *api; + Priority_Control current_priority; + Priority_Control new_priority; - /* - * If holding a resource, then do not change it. - * - * If this would make them less important, then do not change it. - */ - return !_Thread_Owns_resources( the_thread ) && - _Thread_Priority_less_than( the_thread->current_priority, *new_priority ); -} + api = arg; -/* - * _POSIX_Threads_Sporadic_budget_TSR - */ -void _POSIX_Threads_Sporadic_budget_TSR( Watchdog_Control *watchdog ) -{ - POSIX_API_Control *api; - Thread_Control *the_thread; - ISR_lock_Context lock_context; - Priority_Control new_priority; + new_priority = api->Sporadic.high_priority; + *new_priority_p = new_priority; - api = RTEMS_CONTAINER_OF( watchdog, POSIX_API_Control, Sporadic_timer ); - the_thread = api->thread; + current_priority = the_thread->current_priority; + the_thread->real_priority = new_priority; - _Thread_State_acquire( the_thread, &lock_context ); - - _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer ); + _Watchdog_Per_CPU_remove_relative( &api->Sporadic.Timer ); _POSIX_Threads_Sporadic_timer_insert( the_thread, api ); - new_priority = _POSIX_Priority_To_core( - api->Attributes.schedparam.sched_priority - ); + return _Thread_Priority_less_than( current_priority, new_priority ) + || !_Thread_Owns_resources( the_thread ); +} + +static void _POSIX_Threads_Sporadic_timer( Watchdog_Control *watchdog ) +{ + POSIX_API_Control *api; + Thread_Control *the_thread; - _Thread_State_release( the_thread, &lock_context ); + api = RTEMS_CONTAINER_OF( watchdog, POSIX_API_Control, Sporadic.Timer ); + the_thread = api->thread; _Thread_Change_priority( the_thread, - new_priority, - NULL, - _POSIX_Threads_Sporadic_budget_TSR_filter, + 0, + api, + _POSIX_Threads_Sporadic_timer_filter, true ); } static bool _POSIX_Threads_Sporadic_budget_callout_filter( Thread_Control *the_thread, - Priority_Control *new_priority, + Priority_Control *new_priority_p, void *arg ) { - the_thread->real_priority = *new_priority; - - /* - * If holding a resource, then do not change it. - * - * Make sure we are actually lowering it. If they have lowered it - * to logically lower than sched_ss_low_priority, then we do not want to - * change it. - */ - return !_Thread_Owns_resources( the_thread ) && - _Thread_Priority_less_than( *new_priority, the_thread->current_priority ); -} - -/* - * _POSIX_Threads_Sporadic_budget_callout - */ -void _POSIX_Threads_Sporadic_budget_callout( - Thread_Control *the_thread -) -{ POSIX_API_Control *api; + Priority_Control current_priority; + Priority_Control new_priority; api = the_thread->API_Extensions[ THREAD_API_POSIX ]; @@ -167,11 +141,21 @@ void _POSIX_Threads_Sporadic_budget_callout( */ the_thread->cpu_time_budget = UINT32_MAX; + new_priority = api->Sporadic.low_priority; + *new_priority_p = new_priority; + + current_priority = the_thread->current_priority; + the_thread->real_priority = new_priority; + + return _Thread_Priority_less_than( current_priority, new_priority ) + || !_Thread_Owns_resources( the_thread ); +} + +void _POSIX_Threads_Sporadic_budget_callout( Thread_Control *the_thread ) +{ _Thread_Change_priority( the_thread, - _POSIX_Priority_To_core( - api->Attributes.schedparam.sched_ss_low_priority - ), + 0, NULL, _POSIX_Threads_Sporadic_budget_callout_filter, true @@ -217,11 +201,8 @@ static bool _POSIX_Threads_Create_extension( api->signals_unblocked = executing_api->signals_unblocked; } - _Watchdog_Preinitialize( &api->Sporadic_timer, _Per_CPU_Get_by_index( 0 ) ); - _Watchdog_Initialize( - &api->Sporadic_timer, - _POSIX_Threads_Sporadic_budget_TSR - ); + _Watchdog_Preinitialize( &api->Sporadic.Timer, _Per_CPU_Get_by_index( 0 ) ); + _Watchdog_Initialize( &api->Sporadic.Timer, _POSIX_Threads_Sporadic_timer ); return true; } @@ -236,7 +217,7 @@ static void _POSIX_Threads_Terminate_extension( Thread_Control *executing ) _Thread_State_acquire( executing, &lock_context ); if ( api->Attributes.schedpolicy == SCHED_SPORADIC ) { - _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer ); + _Watchdog_Per_CPU_remove_relative( &api->Sporadic.Timer ); } _Thread_State_release( executing, &lock_context ); diff --git a/cpukit/posix/src/pthreadcreate.c b/cpukit/posix/src/pthreadcreate.c index c7c233857a..f2fc1ca68e 100644 --- a/cpukit/posix/src/pthreadcreate.c +++ b/cpukit/posix/src/pthreadcreate.c @@ -60,7 +60,10 @@ int pthread_create( } }; const pthread_attr_t *the_attr; - Priority_Control core_priority; + int low_prio; + int high_prio; + Priority_Control core_low_prio; + Priority_Control core_high_prio; Thread_CPU_budget_algorithms budget_algorithm; Thread_CPU_budget_algorithm_callout budget_callout; bool is_fp; @@ -71,7 +74,7 @@ int pthread_create( int schedpolicy = SCHED_RR; struct sched_param schedparam; Objects_Name name; - int rc; + int error; ISR_lock_Context lock_context; if ( !start_routine ) @@ -130,25 +133,34 @@ int pthread_create( if ( the_attr->contentionscope != PTHREAD_SCOPE_PROCESS ) return ENOTSUP; - /* - * Interpret the scheduling parameters. - */ - if ( !_POSIX_Priority_Is_valid( schedparam.sched_priority ) ) - return EINVAL; - - core_priority = _POSIX_Priority_To_core( schedparam.sched_priority ); - - /* - * Set the core scheduling policy information. - */ - rc = _POSIX_Thread_Translate_sched_param( + error = _POSIX_Thread_Translate_sched_param( schedpolicy, &schedparam, &budget_algorithm, &budget_callout ); - if ( rc ) - return rc; + if ( error != 0 ) { + return error; + } + + if ( schedpolicy == SCHED_SPORADIC ) { + low_prio = schedparam.sched_ss_low_priority; + high_prio = schedparam.sched_priority; + } else { + low_prio = schedparam.sched_priority; + high_prio = low_prio; + } + + if ( !_POSIX_Priority_Is_valid( low_prio ) ) { + return EINVAL; + } + + if ( !_POSIX_Priority_Is_valid( high_prio ) ) { + return EINVAL; + } + + core_low_prio = _POSIX_Priority_To_core( low_prio ); + core_high_prio = _POSIX_Priority_To_core( high_prio ); #if defined(RTEMS_SMP) #if __RTEMS_HAVE_SYS_CPUSET_H__ @@ -186,7 +198,7 @@ int pthread_create( the_attr->stackaddr, _POSIX_Threads_Ensure_minimum_stack(the_attr->stacksize), is_fp, - core_priority, + core_high_prio, true, /* preemptible */ budget_algorithm, budget_callout, @@ -226,6 +238,8 @@ int pthread_create( api = the_thread->API_Extensions[ THREAD_API_POSIX ]; _POSIX_Threads_Copy_attributes( &api->Attributes, the_attr ); + api->Sporadic.low_priority = core_low_prio; + api->Sporadic.high_priority = core_high_prio; if ( schedpolicy == SCHED_SPORADIC ) { _ISR_lock_ISR_disable( &lock_context ); diff --git a/cpukit/posix/src/pthreadgetschedparam.c b/cpukit/posix/src/pthreadgetschedparam.c index ed149f2e2b..6751c647d7 100644 --- a/cpukit/posix/src/pthreadgetschedparam.c +++ b/cpukit/posix/src/pthreadgetschedparam.c @@ -48,15 +48,16 @@ int pthread_getschedparam( return ESRCH; } - _Thread_State_acquire_critical( the_thread, &lock_context ); - api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + _Thread_Lock_acquire_default_critical( the_thread, &lock_context ); + *policy = api->Attributes.schedpolicy; *param = api->Attributes.schedparam; param->sched_priority = _POSIX_Priority_From_core( the_thread->real_priority ); - _Thread_State_release( the_thread, &lock_context ); + _Thread_Lock_release_default( the_thread, &lock_context ); return 0; } diff --git a/cpukit/posix/src/pthreadsetschedparam.c b/cpukit/posix/src/pthreadsetschedparam.c index a2e13a0f17..15d016fce7 100644 --- a/cpukit/posix/src/pthreadsetschedparam.c +++ b/cpukit/posix/src/pthreadsetschedparam.c @@ -28,8 +28,82 @@ #include <rtems/posix/pthreadimpl.h> #include <rtems/posix/priorityimpl.h> #include <rtems/score/threadimpl.h> -#include <rtems/score/watchdogimpl.h> -#include <rtems/config.h> + +typedef struct { + int policy; + const struct sched_param *param; + Thread_CPU_budget_algorithms budget_algorithm; + Thread_CPU_budget_algorithm_callout budget_callout; + int error; +} POSIX_Set_sched_param_context; + +static bool _POSIX_Set_sched_param_filter( + Thread_Control *the_thread, + Priority_Control *new_priority_p, + void *arg +) +{ + POSIX_Set_sched_param_context *context; + const struct sched_param *param; + POSIX_API_Control *api; + int low_prio; + int high_prio; + Priority_Control core_low_prio; + Priority_Control core_high_prio; + Priority_Control current_priority; + + context = arg; + param = context->param; + + if ( context->policy == SCHED_SPORADIC ) { + low_prio = param->sched_ss_low_priority; + high_prio = param->sched_priority; + } else { + low_prio = param->sched_priority; + high_prio = low_prio; + } + + if ( !_POSIX_Priority_Is_valid( low_prio ) ) { + context->error = EINVAL; + return false; + } + + if ( !_POSIX_Priority_Is_valid( high_prio ) ) { + context->error = EINVAL; + return false; + } + + core_low_prio = _POSIX_Priority_To_core( low_prio ); + core_high_prio = _POSIX_Priority_To_core( high_prio ); + + *new_priority_p = core_high_prio; + + current_priority = the_thread->current_priority; + the_thread->real_priority = core_high_prio; + + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + _Watchdog_Per_CPU_remove_relative( &api->Sporadic.Timer ); + + api->Attributes.schedpolicy = context->policy; + api->Attributes.schedparam = *param; + api->Sporadic.low_priority = core_low_prio; + api->Sporadic.high_priority = core_high_prio; + + the_thread->budget_algorithm = context->budget_algorithm; + the_thread->budget_callout = context->budget_callout; + + if ( context->policy == SCHED_SPORADIC ) { + _POSIX_Threads_Sporadic_timer_insert( the_thread, api ); + } else { + the_thread->cpu_time_budget = + rtems_configuration_get_ticks_per_timeslice(); + } + + context->error = 0; + return _Thread_Priority_less_than( current_priority, core_high_prio ) + || !_Thread_Owns_resources( the_thread ); +} int pthread_setschedparam( pthread_t thread, @@ -37,85 +111,46 @@ int pthread_setschedparam( struct sched_param *param ) { - Thread_Control *the_thread; - Per_CPU_Control *cpu_self; - POSIX_API_Control *api; - Thread_CPU_budget_algorithms budget_algorithm; - Thread_CPU_budget_algorithm_callout budget_callout; - int eno; - Priority_Control unused; - ISR_lock_Context lock_context; - Priority_Control new_priority; - - /* - * Check all the parameters - */ + Thread_Control *the_thread; + Per_CPU_Control *cpu_self; + POSIX_Set_sched_param_context context; + ISR_lock_Context lock_context; + int error; if ( param == NULL ) { return EINVAL; } - eno = _POSIX_Thread_Translate_sched_param( + error = _POSIX_Thread_Translate_sched_param( policy, param, - &budget_algorithm, - &budget_callout + &context.budget_algorithm, + &context.budget_callout ); - if ( eno != 0 ) { - return eno; + if ( error != 0 ) { + return error; } + context.policy = policy; + context.param = param; + the_thread = _Thread_Get( thread, &lock_context ); if ( the_thread == NULL ) { return ESRCH; } - /* - * Actually change the scheduling policy and parameters - */ - cpu_self = _Thread_Dispatch_disable_critical( &lock_context ); - _Thread_State_acquire_critical( the_thread, &lock_context ); - - api = the_thread->API_Extensions[ THREAD_API_POSIX ]; - - if ( api->Attributes.schedpolicy == SCHED_SPORADIC ) { - _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer ); - } - - api->Attributes.schedpolicy = policy; - api->Attributes.schedparam = *param; - - the_thread->budget_algorithm = budget_algorithm; - the_thread->budget_callout = budget_callout; - - switch ( policy ) { - case SCHED_OTHER: - case SCHED_FIFO: - case SCHED_RR: - the_thread->cpu_time_budget = - rtems_configuration_get_ticks_per_timeslice(); - new_priority = _POSIX_Priority_To_core( - api->Attributes.schedparam.sched_priority - ); - break; - } - - _Thread_State_release( the_thread, &lock_context ); - - switch ( policy ) { - case SCHED_OTHER: - case SCHED_FIFO: - case SCHED_RR: - _Thread_Set_priority( the_thread, new_priority, &unused, false ); - break; - - case SCHED_SPORADIC: - _POSIX_Threads_Sporadic_budget_TSR( &api->Sporadic_timer ); - break; - } + _ISR_lock_ISR_enable( &lock_context ); + + _Thread_Change_priority( + the_thread, + 0, + &context, + _POSIX_Set_sched_param_filter, + false + ); _Thread_Dispatch_enable( cpu_self ); - return 0; + return context.error; } diff --git a/cpukit/posix/src/pthreadsetschedprio.c b/cpukit/posix/src/pthreadsetschedprio.c index b7166bc8c8..25dc59fb11 100644 --- a/cpukit/posix/src/pthreadsetschedprio.c +++ b/cpukit/posix/src/pthreadsetschedprio.c @@ -17,20 +17,58 @@ #include <rtems/posix/threadsup.h> #include <rtems/score/threadimpl.h> -int pthread_setschedprio( pthread_t thread, int prio ) +typedef struct { + int prio; + int error; +} POSIX_Set_sched_prio_context; + +static bool _POSIX_Set_sched_prio_filter( + Thread_Control *the_thread, + Priority_Control *new_priority_p, + void *arg +) { - Thread_Control *the_thread; - Per_CPU_Control *cpu_self; - POSIX_API_Control *api; - Priority_Control unused; - ISR_lock_Context lock_context; - Priority_Control new_priority; + POSIX_Set_sched_prio_context *context; + int prio; + POSIX_API_Control *api; + Priority_Control current_priority; + Priority_Control new_priority; + + context = arg; + prio = context->prio; if ( !_POSIX_Priority_Is_valid( prio ) ) { - return EINVAL; + context->error = EINVAL; + return false; } new_priority = _POSIX_Priority_To_core( prio ); + *new_priority_p = new_priority; + + current_priority = the_thread->current_priority; + the_thread->real_priority = new_priority; + + api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + + api->Sporadic.high_priority = new_priority; + + if ( api->Sporadic.low_priority < new_priority ) { + api->Sporadic.low_priority = new_priority; + } + + context->error = 0; + return _Thread_Priority_less_than( current_priority, new_priority ) + || !_Thread_Owns_resources( the_thread ); +} + +int pthread_setschedprio( pthread_t thread, int prio ) +{ + Thread_Control *the_thread; + Per_CPU_Control *cpu_self; + POSIX_Set_sched_prio_context context; + ISR_lock_Context lock_context; + + context.prio = prio; the_thread = _Thread_Get( thread, &lock_context ); @@ -38,16 +76,17 @@ int pthread_setschedprio( pthread_t thread, int prio ) return ESRCH; } - api = the_thread->API_Extensions[ THREAD_API_POSIX ]; - cpu_self = _Thread_Dispatch_disable_critical( &lock_context ); + _ISR_lock_ISR_enable( &lock_context ); - _Thread_State_acquire_critical( the_thread, &lock_context ); - api->Attributes.schedparam.sched_priority = prio; - _Thread_State_release( the_thread, &lock_context ); - - _Thread_Set_priority( the_thread, new_priority, &unused, true ); + _Thread_Change_priority( + the_thread, + 0, + &context, + _POSIX_Set_sched_prio_filter, + true + ); _Thread_Dispatch_enable( cpu_self ); - return 0; + return context.error; } diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h index 7c5f0793c3..cde31b48c1 100644 --- a/cpukit/score/include/rtems/score/thread.h +++ b/cpukit/score/include/rtems/score/thread.h @@ -657,6 +657,7 @@ typedef struct { * provide their own lock. * * The thread lock protects the following thread variables + * - POSIX_API_Control::Attributes, * - Thread_Control::current_priority, * - Thread_Control::Wait::queue, and * - Thread_Control::Wait::operations. @@ -710,7 +711,6 @@ struct _Thread_Control { * The lock of this thread queue is used for various purposes. It protects * the following fields * - * - POSIX_API_Control::Attributes, * - RTEMS_API_Control::Signal, * - Thread_Control::budget_algorithm, * - Thread_Control::budget_callout, |