summaryrefslogtreecommitdiffstats
path: root/cpukit/score/include/rtems/score
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-05-27 14:43:19 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-05-30 16:16:21 +0200
commit93306058c0417b1c6e950b44ef279e096062dfba (patch)
tree1a3326d052169d2aec4c4acdd894589d5d84614c /cpukit/score/include/rtems/score
parentscore: Add _Thread_queue_Context_set_MP_callout() (diff)
downloadrtems-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.h33
-rw-r--r--cpukit/score/include/rtems/score/coresemimpl.h3
-rw-r--r--cpukit/score/include/rtems/score/interr.h2
-rw-r--r--cpukit/score/include/rtems/score/threadimpl.h8
-rw-r--r--cpukit/score/include/rtems/score/threadq.h9
-rw-r--r--cpukit/score/include/rtems/score/threadqimpl.h50
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
);
}