diff options
author | Joel Sherrill <joel@rtems.org> | 2017-12-05 09:54:56 -0600 |
---|---|---|
committer | Joel Sherrill <joel@rtems.org> | 2017-12-06 12:48:45 -0600 |
commit | d2711c37f1f189863bd679064cd37a7b0f700494 (patch) | |
tree | 9de0996bf13494274a61cf200a51edb1dbee154b /cpukit | |
parent | confdefs: Replace RTEMS 4.12 with 5.1 (diff) | |
download | rtems-d2711c37f1f189863bd679064cd37a7b0f700494.tar.bz2 |
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.
Diffstat (limited to 'cpukit')
-rw-r--r-- | cpukit/rtems/src/taskmode.c | 34 |
1 files 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 |