diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-03-21 15:01:57 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-03-22 07:05:05 +0100 |
commit | 90960bd11a91259d9aace3870692dbe2e227de0f (patch) | |
tree | 3d88f8bc3d1fe17252e8290cadae2afb4a38ce4b /cpukit/rtems/src/ratemontimeout.c | |
parent | rtems: Avoid __RTEMS_USE_TICKS_FOR_STATISTICS__ (diff) | |
download | rtems-90960bd11a91259d9aace3870692dbe2e227de0f.tar.bz2 |
rtems: Rework rate-monotonic scheduler
Use the default thread lock to protect rate-monotonic state changes.
This avoids use of the Giant lock. Split rtems_rate_monotonic_period()
body into several static functions. Introduce a new thread wait class
THREAD_WAIT_CLASS_PERIOD for period objects to synchronize the blocking
operation.
Close #2631.
Diffstat (limited to 'cpukit/rtems/src/ratemontimeout.c')
-rw-r--r-- | cpukit/rtems/src/ratemontimeout.c | 63 |
1 files changed, 40 insertions, 23 deletions
diff --git a/cpukit/rtems/src/ratemontimeout.c b/cpukit/rtems/src/ratemontimeout.c index 7c25595a16..78c78e2a7f 100644 --- a/cpukit/rtems/src/ratemontimeout.c +++ b/cpukit/rtems/src/ratemontimeout.c @@ -19,33 +19,50 @@ #endif #include <rtems/rtems/ratemonimpl.h> -#include <rtems/score/threadimpl.h> -#include <rtems/score/watchdogimpl.h> -void _Rate_monotonic_Timeout( Watchdog_Control *watchdog ) +void _Rate_monotonic_Timeout( Watchdog_Control *the_watchdog ) { Rate_monotonic_Control *the_period; - Thread_Control *the_thread; - - /* - * When we get here, the Timer is already off the chain so we do not - * have to worry about that -- hence no _Watchdog_Remove(). - */ - the_period = RTEMS_CONTAINER_OF( watchdog, Rate_monotonic_Control, Timer ); - the_thread = the_period->owner; - - _Thread_Disable_dispatch(); - - if ( _States_Is_waiting_for_period( the_thread->current_state ) && - the_thread->Wait.id == the_period->Object.id ) { - _Thread_Unblock( the_thread ); - _Rate_monotonic_Restart( the_period ); - } else if ( the_period->state == RATE_MONOTONIC_OWNER_IS_BLOCKING ) { - the_period->state = RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING; - _Rate_monotonic_Restart( the_period ); + Thread_Control *owner; + ISR_lock_Context lock_context; + Thread_Wait_flags wait_flags; + + the_period = RTEMS_CONTAINER_OF( the_watchdog, Rate_monotonic_Control, Timer ); + owner = the_period->owner; + + _ISR_lock_ISR_disable( &lock_context ); + _Rate_monotonic_Acquire_critical( owner, &lock_context ); + wait_flags = _Thread_Wait_flags_get( owner ); + + if ( + ( wait_flags & THREAD_WAIT_CLASS_PERIOD ) != 0 + && owner->Wait.return_argument == the_period + ) { + bool unblock; + bool success; + + owner->Wait.return_argument = NULL; + + success = _Thread_Wait_flags_try_change_critical( + owner, + RATE_MONOTONIC_INTEND_TO_BLOCK, + RATE_MONOTONIC_READY_AGAIN + ); + if ( success ) { + unblock = false; + } else { + _Assert( _Thread_Wait_flags_get( owner ) == RATE_MONOTONIC_BLOCKED ); + _Thread_Wait_flags_set( owner, RATE_MONOTONIC_READY_AGAIN ); + unblock = true; + } + + _Rate_monotonic_Restart( the_period, owner, &lock_context ); + + if ( unblock ) { + _Thread_Unblock( owner ); + } } else { the_period->state = RATE_MONOTONIC_EXPIRED; + _Rate_monotonic_Release( owner, &lock_context ); } - - _Thread_Unnest_dispatch(); } |