summaryrefslogtreecommitdiffstats
path: root/cpukit/score/include/rtems/score/threadqimpl.h
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-07-25 16:35:37 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-07-27 10:55:30 +0200
commit1fcac5adc5ed38fb88ce4c6d24b2ca2e27e3cd10 (patch)
tree7d2fed265befa680902ff146acb3305a360f9116 /cpukit/score/include/rtems/score/threadqimpl.h
parentscore: Priority inherit thread queue operations (diff)
downloadrtems-1fcac5adc5ed38fb88ce4c6d24b2ca2e27e3cd10.tar.bz2
score: Turn thread lock into thread wait lock
The _Thread_Lock_acquire() function had a potentially infinite run-time due to the lack of fairness at atomic operations level. Update #2412. Update #2556. Update #2765.
Diffstat (limited to 'cpukit/score/include/rtems/score/threadqimpl.h')
-rw-r--r--cpukit/score/include/rtems/score/threadqimpl.h148
1 files changed, 145 insertions, 3 deletions
diff --git a/cpukit/score/include/rtems/score/threadqimpl.h b/cpukit/score/include/rtems/score/threadqimpl.h
index 1f17f1a4f1..3d4f6136f6 100644
--- a/cpukit/score/include/rtems/score/threadqimpl.h
+++ b/cpukit/score/include/rtems/score/threadqimpl.h
@@ -26,6 +26,10 @@
#include <rtems/score/smp.h>
#include <rtems/score/thread.h>
+#if defined(RTEMS_DEBUG)
+#include <string.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -46,6 +50,13 @@ extern "C" {
* relationships.
*/
struct Thread_queue_Path {
+#if defined(RTEMS_SMP)
+ /**
+ * @brief The start of a thread queue path.
+ */
+ Thread_queue_Link Start;
+#endif
+
/**
* @brief A potential thread to update the priority via
* _Thread_Update_priority().
@@ -84,10 +95,8 @@ RTEMS_INLINE_ROUTINE void _Thread_queue_Context_initialize(
)
{
#if defined(RTEMS_DEBUG)
+ memset( queue_context, 0, sizeof( *queue_context ) );
queue_context->expected_thread_dispatch_disable_level = 0xdeadbeef;
-#if defined(RTEMS_MULTIPROCESSING)
- queue_context->mp_callout = NULL;
-#endif
#else
(void) queue_context;
#endif
@@ -187,6 +196,135 @@ RTEMS_INLINE_ROUTINE void _Thread_queue_Context_set_MP_callout(
} while ( 0 )
#endif
+/**
+ * @brief Gets the thread wait queue of the thread queue context.
+ *
+ * On SMP configurations, the value is stored in the thread queue context,
+ * otherwise in the thread itself.
+ *
+ * @param queue_context The thread queue context.
+ * @param the_thread The thread.
+ */
+#if defined(RTEMS_SMP)
+#define _Thread_queue_Context_get_queue( queue_context, the_thread ) \
+ ( queue_context )->Wait.queue
+#else
+#define _Thread_queue_Context_get_queue( queue_context, the_thread ) \
+ ( the_thread )->Wait.queue
+#endif
+
+/**
+ * @brief Gets the thread wait operations of the thread queue context.
+ *
+ * On SMP configurations, the value is stored in the thread queue context,
+ * otherwise in the thread itself.
+ *
+ * @param queue_context The thread queue context.
+ * @param the_thread The thread.
+ */
+#if defined(RTEMS_SMP)
+#define _Thread_queue_Context_get_operations( queue_context, the_thread ) \
+ ( queue_context )->Wait.operations
+#else
+#define _Thread_queue_Context_get_operations( queue_context, the_thread ) \
+ ( the_thread )->Wait.operations
+#endif
+
+/**
+ * @brief Thread priority change by means of the thread queue context.
+ *
+ * On SMP configurations, the used data is stored in the thread queue context,
+ * otherwise in the thread itself.
+ *
+ * @param queue_context The thread queue context.
+ * @param the_thread The thread.
+ * @param new_priority The new thread priority.
+ * @param prepend_it Prepend it to its priority group or not.
+ */
+#if defined(RTEMS_SMP)
+#define _Thread_queue_Context_priority_change( \
+ queue_context, \
+ the_thread, \
+ new_priority, \
+ prepend_it \
+ ) \
+ ( *( queue_context )->Wait.operations->priority_change )( \
+ the_thread, \
+ new_priority, \
+ prepend_it, \
+ ( queue_context )->Wait.queue \
+ )
+#else
+#define _Thread_queue_Context_priority_change( \
+ queue_context, \
+ the_thread, \
+ new_priority, \
+ prepend_it \
+ ) \
+ ( *( the_thread )->Wait.operations->priority_change )( \
+ the_thread, \
+ new_priority, \
+ prepend_it, \
+ ( the_thread )->Wait.queue \
+ )
+#endif
+
+/**
+ * @brief Thread queue extract by means of the thread queue context.
+ *
+ * On SMP configurations, the used data is stored in the thread queue context,
+ * otherwise in the thread itself.
+ *
+ * @param queue_context The thread queue context.
+ * @param the_thread The thread.
+ */
+#if defined(RTEMS_SMP)
+#define _Thread_queue_Context_extract( \
+ queue_context, \
+ the_thread \
+ ) \
+ ( *( queue_context )->Wait.operations->extract )( \
+ ( queue_context )->Wait.queue, \
+ the_thread \
+ )
+#else
+#define _Thread_queue_Context_extract( \
+ queue_context, \
+ the_thread \
+ ) \
+ ( *( the_thread )->Wait.operations->extract )( \
+ ( the_thread )->Wait.queue, \
+ the_thread \
+ )
+#endif
+
+#if defined(RTEMS_SMP)
+RTEMS_INLINE_ROUTINE void _Thread_queue_Gate_add(
+ Chain_Control *chain,
+ Thread_queue_Gate *gate
+)
+{
+ _Atomic_Store_uint( &gate->go_ahead, 0, ATOMIC_ORDER_RELAXED );
+ _Chain_Append_unprotected( chain, &gate->Node );
+}
+
+RTEMS_INLINE_ROUTINE void _Thread_queue_Gate_open(
+ Thread_queue_Gate *gate
+)
+{
+ _Atomic_Store_uint( &gate->go_ahead, 1, ATOMIC_ORDER_RELAXED );
+}
+
+RTEMS_INLINE_ROUTINE void _Thread_queue_Gate_wait(
+ Thread_queue_Gate *gate
+)
+{
+ while ( _Atomic_Load_uint( &gate->go_ahead, ATOMIC_ORDER_RELAXED ) == 0 ) {
+ /* Wait */
+ }
+}
+#endif
+
RTEMS_INLINE_ROUTINE void _Thread_queue_Heads_initialize(
Thread_queue_Heads *heads
)
@@ -911,6 +1049,10 @@ extern const Thread_queue_Operations _Thread_queue_Operations_priority;
extern const Thread_queue_Operations _Thread_queue_Operations_priority_inherit;
+#if defined(RTEMS_SMP)
+extern const Thread_queue_Operations _Thread_queue_Operations_stale_queue;
+#endif
+
/**@}*/
#ifdef __cplusplus