From d2711c37f1f189863bd679064cd37a7b0f700494 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Tue, 5 Dec 2017 09:54:56 -0600 Subject: taskmode.c: Ensure all error checking is done before modifying executing Also use single conditional expressions to simplify error checking. Combined, this all resulted in a block of SMP enabled error checking. Updates #3000. --- cpukit/rtems/src/taskmode.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/cpukit/rtems/src/taskmode.c b/cpukit/rtems/src/taskmode.c index a345409f2a..91b16a565e 100644 --- a/cpukit/rtems/src/taskmode.c +++ b/cpukit/rtems/src/taskmode.c @@ -43,6 +43,31 @@ rtems_status_code rtems_task_mode( if ( !previous_mode_set ) return RTEMS_INVALID_ADDRESS; +#if defined( RTEMS_SMP ) + /* + * When in SMP, you cannot disable preemption for a thread or + * alter its interrupt level. It must be fully preemptible with + * all interrupts enabled. + */ + if ( rtems_configuration_is_smp_enabled() ) { + if ( mask & RTEMS_PREEMPT_MASK ) { + if ( !_Modes_Is_preempt( mode_set ) ) { + return RTEMS_NOT_IMPLEMENTED; + } + } + + if ( mask & RTEMS_INTERRUPT_MASK ) { + return RTEMS_NOT_IMPLEMENTED; + } + } +#endif + + /* + * Complete all error checking before doing any operations which + * impact the executing thread. There should be no errors returned + * past this point. + */ + executing = _Thread_Get_executing(); api = executing->API_Extensions[ THREAD_API_RTEMS ]; asr = &api->Signal; @@ -63,18 +88,18 @@ rtems_status_code rtems_task_mode( * These are generic thread scheduling characteristics. */ preempt_enabled = false; +#if !defined( RTEMS_SMP ) if ( mask & RTEMS_PREEMPT_MASK ) { -#if defined( RTEMS_SMP ) if ( rtems_configuration_is_smp_enabled() && !_Modes_Is_preempt( mode_set ) ) { return RTEMS_NOT_IMPLEMENTED; } -#endif bool is_preempt_enabled = _Modes_Is_preempt( mode_set ); preempt_enabled = !executing->is_preemptible && is_preempt_enabled; executing->is_preemptible = is_preempt_enabled; } +#endif if ( mask & RTEMS_TIMESLICE_MASK ) { if ( _Modes_Is_timeslice(mode_set) ) { @@ -88,8 +113,11 @@ rtems_status_code rtems_task_mode( /* * Set the new interrupt level */ - if ( mask & RTEMS_INTERRUPT_MASK ) +#if !defined( RTEMS_SMP ) + if ( mask & RTEMS_INTERRUPT_MASK ) { _Modes_Set_interrupt_level( mode_set ); + } +#endif /* * This is specific to the RTEMS API -- cgit v1.2.3