From 0ea6d07a030916ff1034e0152c7b56e652ee94f3 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Wed, 9 Jul 2014 13:22:28 -0500 Subject: Use Shared Method for Thread Unblock Cleanup When a thread is removed from a thread queue or is unblocked by receiving an event, the same actions are required. + timeout watchdog canceled, + thread must be unblocked, and + (MP only) proxy cleaned up This patch makes sure there is only one copy of this code. --- cpukit/score/include/rtems/score/threadimpl.h | 18 +++++++ cpukit/score/src/threadblockingoperationcancel.c | 65 +++++++++++++----------- cpukit/score/src/threadqdequeue.c | 18 ++----- cpukit/score/src/threadqextract.c | 22 +++----- 4 files changed, 63 insertions(+), 60 deletions(-) diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h index cb7d5fe8d2..a527c8beca 100644 --- a/cpukit/score/include/rtems/score/threadimpl.h +++ b/cpukit/score/include/rtems/score/threadimpl.h @@ -403,6 +403,24 @@ void _Thread_blocking_operation_Cancel( ISR_Level level ); +/** + * @brief Finalize a blocking operation. + * + * This method is used to finalize a blocking operation that was + * satisfied. It may be used with thread queues or any other synchronization + * object that uses the blocking states and watchdog times for timeout. + * + * This method will restore the previous ISR disable level during the cancel + * operation. Thus it is an implicit _ISR_Enable(). + * + * @param[in] the_thread is the thread whose blocking is canceled + * @param[in] level is the previous ISR disable level + */ +void _Thread_blocking_operation_Finalize( + Thread_Control *the_thread, + ISR_Level level +); + RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_Get_CPU( const Thread_Control *thread ) diff --git a/cpukit/score/src/threadblockingoperationcancel.c b/cpukit/score/src/threadblockingoperationcancel.c index 127d852de2..b4967964b7 100644 --- a/cpukit/score/src/threadblockingoperationcancel.c +++ b/cpukit/score/src/threadblockingoperationcancel.c @@ -24,6 +24,41 @@ #endif #include +void _Thread_blocking_operation_Finalize( + Thread_Control *the_thread, + ISR_Level level +) +{ + /* + * The thread is not waiting on anything after this completes. + */ + the_thread->Wait.queue = NULL; + + /* + * If the sync state is timed out, this is very likely not needed. + * But better safe than sorry when it comes to critical sections. + */ + if ( _Watchdog_Is_active( &the_thread->Timer ) ) { + _Watchdog_Deactivate( &the_thread->Timer ); + _ISR_Enable( level ); + (void) _Watchdog_Remove( &the_thread->Timer ); + } else + _ISR_Enable( level ); + + /* + * Global objects with thread queue's should not be operated on from an + * ISR. But the sync code still must allow short timeouts to be processed + * correctly. + */ + + _Thread_Unblock( the_thread ); + +#if defined(RTEMS_MULTIPROCESSING) + if ( !_Objects_Is_local_id( the_thread->Object.id ) ) + _Thread_MP_Free_proxy( the_thread ); +#endif +} + void _Thread_blocking_operation_Cancel( #if defined(RTEMS_DEBUG) Thread_blocking_operation_States sync_state, @@ -59,33 +94,5 @@ void _Thread_blocking_operation_Cancel( } #endif - /* - * The thread is not waiting on anything after this completes. - */ - the_thread->Wait.queue = NULL; - - /* - * If the sync state is timed out, this is very likely not needed. - * But better safe than sorry when it comes to critical sections. - */ - if ( _Watchdog_Is_active( &the_thread->Timer ) ) { - _Watchdog_Deactivate( &the_thread->Timer ); - _ISR_Enable( level ); - (void) _Watchdog_Remove( &the_thread->Timer ); - } else - _ISR_Enable( level ); - - /* - * Global objects with thread queue's should not be operated on from an - * ISR. But the sync code still must allow short timeouts to be processed - * correctly. - */ - - _Thread_Unblock( the_thread ); - -#if defined(RTEMS_MULTIPROCESSING) - if ( !_Objects_Is_local_id( the_thread->Object.id ) ) - _Thread_MP_Free_proxy( the_thread ); -#endif - + _Thread_blocking_operation_Finalize( the_thread, level ); } diff --git a/cpukit/score/src/threadqdequeue.c b/cpukit/score/src/threadqdequeue.c index 3b55e52e83..d745ef29e3 100644 --- a/cpukit/score/src/threadqdequeue.c +++ b/cpukit/score/src/threadqdequeue.c @@ -70,22 +70,10 @@ Thread_Control *_Thread_queue_Dequeue( /* * We found a thread to unblock. + * + * NOTE: This is invoked with interrupts still disabled. */ - the_thread->Wait.queue = NULL; - if ( !_Watchdog_Is_active( &the_thread->Timer ) ) { - _ISR_Enable( level ); - } else { - _Watchdog_Deactivate( &the_thread->Timer ); - _ISR_Enable( level ); - (void) _Watchdog_Remove( &the_thread->Timer ); - } - - _Thread_Unblock( the_thread ); - -#if defined(RTEMS_MULTIPROCESSING) - if ( !_Objects_Is_local_id( the_thread->Object.id ) ) - _Thread_MP_Free_proxy( the_thread ); -#endif + _Thread_blocking_operation_Finalize( the_thread, level ); return the_thread; } diff --git a/cpukit/score/src/threadqextract.c b/cpukit/score/src/threadqextract.c index bc7d34686a..d12d3c889a 100644 --- a/cpukit/score/src/threadqextract.c +++ b/cpukit/score/src/threadqextract.c @@ -48,24 +48,14 @@ void _Thread_queue_Extract_with_return_code( ); } - the_thread->Wait.queue = NULL; the_thread->Wait.return_code = return_code; - if ( !_Watchdog_Is_active( &the_thread->Timer ) ) { - _ISR_Enable( level ); - } else { - _Watchdog_Deactivate( &the_thread->Timer ); - _ISR_Enable( level ); - (void) _Watchdog_Remove( &the_thread->Timer ); - } - - _Thread_Unblock( the_thread ); - -#if defined(RTEMS_MULTIPROCESSING) - if ( !_Objects_Is_local_id( the_thread->Object.id ) ) - _Thread_MP_Free_proxy( the_thread ); -#endif - + /* + * We found a thread to unblock. + * + * NOTE: This is invoked with interrupts still disabled. + */ + _Thread_blocking_operation_Finalize( the_thread, level ); } void _Thread_queue_Extract( -- cgit v1.2.3