summaryrefslogtreecommitdiffstats
path: root/cpukit/posix/src
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-06-15 06:59:57 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-06-22 14:00:28 +0200
commiteec08efc9048111f47f42142c30a92683bf6756c (patch)
treecad083e49ab757b47487f8489ed48c9204b65c38 /cpukit/posix/src
parentposix: Delete POSIX_API_Control::schedparam (diff)
downloadrtems-eec08efc9048111f47f42142c30a92683bf6756c.tar.bz2
posix: Rework sporadic server scheduling policy
Instead of lowering the priority in case the initial budget is consumed raise the priority for each new period. Restore the normal priority once the initial budget is consumed. This makes it later easier to combine the high priority phase with temporary priority boosts (e.g. via priority ceiling and inheritance). Use the thread lock to protect the POSIX thread attributes instead of the thread state lock. This makes it easier to change the thread priority and keep the POSIX attributes consistent. Fixes a false positive use of uninitialized variable warning.
Diffstat (limited to 'cpukit/posix/src')
-rw-r--r--cpukit/posix/src/psxtransschedparam.c8
-rw-r--r--cpukit/posix/src/pthread.c105
-rw-r--r--cpukit/posix/src/pthreadcreate.c48
-rw-r--r--cpukit/posix/src/pthreadgetschedparam.c7
-rw-r--r--cpukit/posix/src/pthreadsetschedparam.c163
-rw-r--r--cpukit/posix/src/pthreadsetschedprio.c71
6 files changed, 232 insertions, 170 deletions
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( &param->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;
}