diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-05-27 14:43:19 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-05-30 16:16:21 +0200 |
commit | 93306058c0417b1c6e950b44ef279e096062dfba (patch) | |
tree | 1a3326d052169d2aec4c4acdd894589d5d84614c /cpukit/score/include/rtems/score | |
parent | score: Add _Thread_queue_Context_set_MP_callout() (diff) | |
download | rtems-93306058c0417b1c6e950b44ef279e096062dfba.tar.bz2 |
score: _CORE_mutex_Check_dispatch_for_seize()
Move the safety check performed by
_CORE_mutex_Check_dispatch_for_seize() out of the performance critical
path and generalize it. Blocking on a thread queue with an unexpected
thread dispatch disabled level is illegal in all system states.
Add the expected thread dispatch disable level (which may be 1 or 2
depending on the operation) to Thread_queue_Context and use it in
_Thread_queue_Enqueue_critical().
Diffstat (limited to 'cpukit/score/include/rtems/score')
-rw-r--r-- | cpukit/score/include/rtems/score/coremuteximpl.h | 33 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/coresemimpl.h | 3 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/interr.h | 2 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/threadimpl.h | 8 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/threadq.h | 9 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/threadqimpl.h | 50 |
6 files changed, 59 insertions, 46 deletions
diff --git a/cpukit/score/include/rtems/score/coremuteximpl.h b/cpukit/score/include/rtems/score/coremuteximpl.h index f5faf9517a..e29d4b7f5d 100644 --- a/cpukit/score/include/rtems/score/coremuteximpl.h +++ b/cpukit/score/include/rtems/score/coremuteximpl.h @@ -21,7 +21,6 @@ #include <rtems/score/coremutex.h> #include <rtems/score/chainimpl.h> #include <rtems/score/status.h> -#include <rtems/score/sysstate.h> #include <rtems/score/threadimpl.h> #include <rtems/score/threadqimpl.h> @@ -95,27 +94,13 @@ RTEMS_INLINE_ROUTINE void _CORE_mutex_Release( * @param[in] lock_context is the interrupt level */ Status_Control _CORE_mutex_Seize_interrupt_blocking( - CORE_mutex_Control *the_mutex, - Thread_Control *executing, - Watchdog_Interval timeout, - ISR_lock_Context *lock_context + CORE_mutex_Control *the_mutex, + Thread_Control *executing, + Watchdog_Interval timeout, + Thread_queue_Context *queue_context ); /** - * @brief Verifies that a mutex blocking seize is performed safely. - * - * This macro is to verify that a mutex blocking seize is - * performed from a safe system state. For example, one - * cannot block inside an isr. - * - * @retval this method returns true if dispatch is in an unsafe state. - */ -#define _CORE_mutex_Check_dispatch_for_seize(_wait) \ - (!_Thread_Dispatch_is_enabled() \ - && (_wait) \ - && (_System_state_Get() >= SYSTEM_STATE_UP)) - -/** * @brief Is mutex locked. * * This routine returns true if the mutex specified is locked and false @@ -301,14 +286,6 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_mutex_Seize( { Status_Control status; - if ( _CORE_mutex_Check_dispatch_for_seize( wait ) ) { - _Terminate( - INTERNAL_ERROR_CORE, - false, - INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE - ); - } - _CORE_mutex_Acquire_critical( the_mutex, queue_context ); status = _CORE_mutex_Seize_interrupt_trylock( @@ -330,7 +307,7 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_mutex_Seize( the_mutex, executing, timeout, - &queue_context->Lock_context + queue_context ); } diff --git a/cpukit/score/include/rtems/score/coresemimpl.h b/cpukit/score/include/rtems/score/coresemimpl.h index ac90f20b7d..a55089e399 100644 --- a/cpukit/score/include/rtems/score/coresemimpl.h +++ b/cpukit/score/include/rtems/score/coresemimpl.h @@ -204,13 +204,14 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_semaphore_Seize( return STATUS_UNSATISFIED; } + _Thread_queue_Context_set_expected_level( queue_context, 1 ); _Thread_queue_Enqueue_critical( &the_semaphore->Wait_queue.Queue, the_semaphore->operations, executing, STATES_WAITING_FOR_SEMAPHORE, timeout, - &queue_context->Lock_context + queue_context ); return _Thread_Wait_get_status( executing ); } diff --git a/cpukit/score/include/rtems/score/interr.h b/cpukit/score/include/rtems/score/interr.h index ea468e035e..ca48db2c06 100644 --- a/cpukit/score/include/rtems/score/interr.h +++ b/cpukit/score/include/rtems/score/interr.h @@ -154,7 +154,7 @@ typedef enum { INTERNAL_ERROR_BAD_ATTRIBUTES, INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY, OBSOLETE_INTERNAL_ERROR_IMPLEMENTATION_BLOCKING_OPERATION_CANCEL, - INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE, + INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_FROM_BAD_STATE, INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0, OBSOLETE_INTERNAL_ERROR_SHUTDOWN_WHEN_NOT_UP, INTERNAL_ERROR_GXX_KEY_ADD_FAILED, diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h index 10811088c9..d10221234c 100644 --- a/cpukit/score/include/rtems/score/threadimpl.h +++ b/cpukit/score/include/rtems/score/threadimpl.h @@ -232,10 +232,10 @@ void _Thread_Exit( ); void _Thread_Join( - Thread_Control *the_thread, - States_Control waiting_for_join, - Thread_Control *executing, - ISR_lock_Context *lock_context + Thread_Control *the_thread, + States_Control waiting_for_join, + Thread_Control *executing, + Thread_queue_Context *queue_context ); void _Thread_Cancel( diff --git a/cpukit/score/include/rtems/score/threadq.h b/cpukit/score/include/rtems/score/threadq.h index 5f2ffe49a9..a4e5292f34 100644 --- a/cpukit/score/include/rtems/score/threadq.h +++ b/cpukit/score/include/rtems/score/threadq.h @@ -70,6 +70,15 @@ typedef struct { ISR_lock_Context Lock_context; /** + * @brief The expected thread dispatch disable level for + * _Thread_queue_Enqueue_critical(). + * + * In case the actual thread dispatch disable level is not equal to the + * expected level, then a fatal error occurs. + */ + uint32_t expected_thread_dispatch_disable_level; + + /** * @brief Callout to unblock the thread in case it is actually a thread * proxy. * diff --git a/cpukit/score/include/rtems/score/threadqimpl.h b/cpukit/score/include/rtems/score/threadqimpl.h index 4f5b48b6eb..73d4de2032 100644 --- a/cpukit/score/include/rtems/score/threadqimpl.h +++ b/cpukit/score/include/rtems/score/threadqimpl.h @@ -62,14 +62,35 @@ RTEMS_INLINE_ROUTINE void _Thread_queue_Context_initialize( Thread_queue_Context *queue_context ) { -#if defined(RTEMS_MULTIPROCESSING) && defined(RTEMS_DEBUG) +#if defined(RTEMS_DEBUG) + queue_context->expected_thread_dispatch_disable_level = 0xdeadbeef; +#if defined(RTEMS_MULTIPROCESSING) queue_context->mp_callout = NULL; +#endif #else (void) queue_context; #endif } /** + * @brief Sets the expected thread dispatch disable level in the thread queue + * context. + * + * @param queue_context The thread queue context. + * @param expected_level The expected thread dispatch disable level. + * + * @see _Thread_queue_Enqueue_critical(). + */ +RTEMS_INLINE_ROUTINE void +_Thread_queue_Context_set_expected_level( + Thread_queue_Context *queue_context, + uint32_t expected_level +) +{ + queue_context->expected_thread_dispatch_disable_level = expected_level; +} + +/** * @brief Sets the MP callout in the thread queue context. * * @param queue_context The thread queue context. @@ -309,17 +330,19 @@ Thread_Control *_Thread_queue_Do_dequeue( * * void _Mutex_Obtain( Mutex *mutex ) * { - * ISR_lock_Context lock_context; - * Thread_Control *executing; + * Thread_queue_Context queue_context; + * Thread_Control *executing; * - * _Thread_queue_Acquire( &mutex->Queue, &lock_context ); + * _Thread_queue_Context_initialize( &queue_context ); + * _Thread_queue_Acquire( &mutex->Queue, &queue_context.Lock_context ); * * executing = _Thread_Executing; * * if ( mutex->owner == NULL ) { * mutex->owner = executing; - * _Thread_queue_Release( &mutex->Queue, &lock_context ); + * _Thread_queue_Release( &mutex->Queue, &queue_context.Lock_context ); * } else { + * _Thread_queue_Context_set_expected_level( &queue_context, 1 ); * _Thread_queue_Enqueue_critical( * &mutex->Queue.Queue, * MUTEX_TQ_OPERATIONS, @@ -327,7 +350,7 @@ Thread_Control *_Thread_queue_Do_dequeue( * STATES_WAITING_FOR_MUTEX, * WATCHDOG_NO_TIMEOUT, * 0, - * &lock_context + * &queue_context * ); * } * } @@ -339,7 +362,7 @@ Thread_Control *_Thread_queue_Do_dequeue( * @param[in] state The new state of the thread. * @param[in] timeout Interval to wait. Use WATCHDOG_NO_TIMEOUT to block * potentially forever. - * @param[in] lock_context The lock context of the lock acquire. + * @param[in] queue_context The thread queue context of the lock acquire. */ void _Thread_queue_Enqueue_critical( Thread_queue_Queue *queue, @@ -347,7 +370,7 @@ void _Thread_queue_Enqueue_critical( Thread_Control *the_thread, States_Control state, Watchdog_Interval timeout, - ISR_lock_Context *lock_context + Thread_queue_Context *queue_context ); /** @@ -359,19 +382,22 @@ RTEMS_INLINE_ROUTINE void _Thread_queue_Enqueue( const Thread_queue_Operations *operations, Thread_Control *the_thread, States_Control state, - Watchdog_Interval timeout + Watchdog_Interval timeout, + uint32_t expected_level ) { - ISR_lock_Context lock_context; + Thread_queue_Context queue_context; - _Thread_queue_Acquire( the_thread_queue, &lock_context ); + _Thread_queue_Context_initialize( &queue_context ); + _Thread_queue_Acquire( the_thread_queue, &queue_context.Lock_context ); + _Thread_queue_Context_set_expected_level( &queue_context, expected_level ); _Thread_queue_Enqueue_critical( &the_thread_queue->Queue, operations, the_thread, state, timeout, - &lock_context + &queue_context ); } |