[PATCH 19/45] score: Add Thread_queue_Operations

Sebastian Huber sebastian.huber at embedded-brains.de
Fri May 15 11:41:19 UTC 2015


Replace the Thread_Priority_control with more general
Thread_queue_Operations which will be used for generic priority change,
timeout, signal and wait queue operations in the future.

Update #2273.
---
 cpukit/score/Makefile.am                       |  1 +
 cpukit/score/include/rtems/score/thread.h      | 86 +++++++++----------------
 cpukit/score/include/rtems/score/threadimpl.h  | 88 ++++++++++++++++----------
 cpukit/score/include/rtems/score/threadq.h     | 49 +++++++++++++-
 cpukit/score/include/rtems/score/threadqimpl.h |  6 ++
 cpukit/score/src/thread.c                      |  2 +-
 cpukit/score/src/threadchangepriority.c        | 10 +--
 cpukit/score/src/threadinitialize.c            | 13 +---
 cpukit/score/src/threadqenqueue.c              | 30 ++-------
 cpukit/score/src/threadqops.c                  | 56 ++++++++++++++++
 testsuites/sptests/spintrcritical23/init.c     |  4 +-
 11 files changed, 207 insertions(+), 138 deletions(-)
 create mode 100644 cpukit/score/src/threadqops.c

diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index 3547097..18becdb 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -302,6 +302,7 @@ libscore_a_SOURCES += src/threadq.c \
     src/threadqenqueue.c \
     src/threadqextractwithproxy.c src/threadqfirst.c \
     src/threadqflush.c src/threadqprocesstimeout.c src/threadqtimeout.c
+libscore_a_SOURCES += src/threadqops.c
 
 ## TIMESPEC_C_FILES
 libscore_a_SOURCES += src/timespecaddto.c src/timespecfromticks.c \
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index 1a73fda..bce6f56 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -249,56 +249,6 @@ typedef struct {
 } Thread_Start_information;
 
 /**
- * @brief Priority change handler.
- *
- * @param[in] the_thread The thread.
- * @param[in] new_priority The new priority value.
- * @param[in] context The handler context.
- *
- * @see _Thread_Priority_set_change_handler().
- */
-typedef void (*Thread_Priority_change_handler)(
-  Thread_Control   *the_thread,
-  Priority_Control  new_priority,
-  void             *context
-);
-
-/**
- * @brief Thread priority control.
- */
-typedef struct {
-  /**
-   * @brief Generation of the current priority value.
-   *
-   * It is used in _Thread_Change_priority() to serialize the update of
-   * priority related data structures.
-   */
-  uint32_t generation;
-
-  /**
-   * @brief Priority change handler.
-   *
-   * Called by _Thread_Change_priority() to notify a thread about a priority
-   * change.  In case this thread waits currently for a resource the handler
-   * may adjust its data structures according to the new priority value.  This
-   * handler must not be NULL, instead the default handler
-   * _Thread_Priority_change_do_nothing() should be used in case nothing needs
-   * to be done during a priority change.
-   *
-   * @see _Thread_Priority_set_change_handler() and
-   * _Thread_Priority_restore_default_change_handler().
-   */
-  Thread_Priority_change_handler change_handler;
-
-  /**
-   * @brief Context for priority change handler.
-   *
-   * @see _Thread_Priority_set_change_handler().
-   */
-  void *change_handler_context;
-} Thread_Priority_control;
-
-/**
  *  @brief Union type to hold a pointer to an immutable or a mutable object.
  *
  *  The main purpose is to enable passing of pointers to read-only send buffers
@@ -359,7 +309,14 @@ typedef struct {
    */
   uint32_t timeout_code;
 
-  /** This field points to the thread queue on which this thread is blocked. */
+  /**
+   * @brief The current thread queue.
+   *
+   * In case this field is @c NULL, then the thread is not blocked on a thread
+   * queue.  This field is protected by the thread lock.
+   *
+   * @see _Thread_Lock_set() and _Thread_Wait_set_queue().
+   */
   Thread_queue_Control *queue;
 
   /**
@@ -371,6 +328,15 @@ typedef struct {
 #else
   Thread_Wait_flags     flags;
 #endif
+
+  /**
+   * @brief The current thread queue operations.
+   *
+   * This field is protected by the thread lock.
+   *
+   * @see _Thread_Lock_set() and _Thread_Wait_set_operations().
+   */
+  const Thread_queue_Operations *operations;
 }   Thread_Wait_information;
 
 /**
@@ -393,9 +359,12 @@ typedef struct {
   Priority_Control         real_priority;
 
   /**
-   * @brief Thread priority control.
+   * @brief Generation of the current priority value.
+   *
+   * It is used in _Thread_Change_priority() to serialize the update of
+   * priority related data structures.
    */
-  Thread_Priority_control  Priority;
+  uint32_t                 priority_generation;
 
   /** This field is the number of mutexes currently held by this proxy. */
   uint32_t                 resource_count;
@@ -638,8 +607,8 @@ typedef struct  {
  *
  * The thread lock protects the following thread variables
  *  - Thread_Control::current_priority,
- *  - Thread_Control::Priority::change_handler, and
- *  - Thread_Control::Priority::change_handler_context.
+ *  - Thread_Control::Wait::queue, and
+ *  - Thread_Control::Wait::operations.
  *
  * @see _Thread_Lock_acquire(), _Thread_Lock_release(), _Thread_Lock_set() and
  * _Thread_Lock_restore_default().
@@ -679,9 +648,12 @@ struct Thread_Control_struct {
   Priority_Control         real_priority;
 
   /**
-   * @brief Thread priority control.
+   * @brief Generation of the current priority value.
+   *
+   * It is used in _Thread_Change_priority() to serialize the update of
+   * priority related data structures.
    */
-  Thread_Priority_control  Priority;
+  uint32_t                 priority_generation;
 
   /** This field is the number of mutexes currently held by this thread. */
   uint32_t                 resource_count;
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index c266a9c..953b88b 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -30,6 +30,7 @@
 #include <rtems/score/resourceimpl.h>
 #include <rtems/score/statesimpl.h>
 #include <rtems/score/sysstate.h>
+#include <rtems/score/threadqimpl.h>
 #include <rtems/score/todimpl.h>
 #include <rtems/config.h>
 
@@ -1078,41 +1079,6 @@ RTEMS_INLINE_ROUTINE void _Thread_Lock_restore_default(
   do { } while ( 0 )
 #endif
 
-void _Thread_Priority_change_do_nothing(
-  Thread_Control   *the_thread,
-  Priority_Control  new_priority,
-  void             *context
-);
-
-/**
- * @brief Sets the thread priority change handler and its context.
- *
- * @param[in] the_thread The thread.
- * @param[in] new_handler The new handler.
- * @param[in] new_context The new handler context.
- */
-RTEMS_INLINE_ROUTINE void _Thread_Priority_set_change_handler(
-  Thread_Control                 *the_thread,
-  Thread_Priority_change_handler  new_handler,
-  void                           *new_context
-)
-{
-  the_thread->Priority.change_handler = new_handler;
-  the_thread->Priority.change_handler_context = new_context;
-}
-
-/**
- * @brief Restores the thread priority change default handler and its context.
- *
- * @param[in] the_thread The thread.
- */
-RTEMS_INLINE_ROUTINE void _Thread_Priority_restore_default_change_handler(
-  Thread_Control *the_thread
-)
-{
-  the_thread->Priority.change_handler = _Thread_Priority_change_do_nothing;
-}
-
 /**
  * @brief The initial thread wait flags value set by _Thread_Initialize().
  */
@@ -1258,6 +1224,58 @@ RTEMS_INLINE_ROUTINE bool _Thread_Wait_flags_try_change(
 }
 
 /**
+ * @brief Sets the thread queue.
+ *
+ * The caller must be the owner of the thread lock.
+ *
+ * @param[in] the_thread The thread.
+ * @param[in] new_queue The new queue.
+ *
+ * @see _Thread_Lock_set().
+ */
+RTEMS_INLINE_ROUTINE void _Thread_Wait_set_queue(
+  Thread_Control       *the_thread,
+  Thread_queue_Control *new_queue
+)
+{
+  the_thread->Wait.queue = new_queue;
+}
+
+/**
+ * @brief Sets the thread queue operations.
+ *
+ * The caller must be the owner of the thread lock.
+ *
+ * @param[in] the_thread The thread.
+ * @param[in] new_operations The new queue operations.
+ *
+ * @see _Thread_Lock_set() and _Thread_Wait_restore_default_operations().
+ */
+RTEMS_INLINE_ROUTINE void _Thread_Wait_set_operations(
+  Thread_Control                *the_thread,
+  const Thread_queue_Operations *new_operations
+)
+{
+  the_thread->Wait.operations = new_operations;
+}
+
+/**
+ * @brief Restores the default thread queue operations.
+ *
+ * The caller must be the owner of the thread lock.
+ *
+ * @param[in] the_thread The thread.
+ *
+ * @see _Thread_Wait_set_operations().
+ */
+RTEMS_INLINE_ROUTINE void _Thread_Wait_restore_default_operations(
+  Thread_Control *the_thread
+)
+{
+  the_thread->Wait.operations = &_Thread_queue_Operations_default;
+}
+
+/**
  * @brief Sets the thread wait timeout code.
  *
  * @param[in] the_thread The thread.
diff --git a/cpukit/score/include/rtems/score/threadq.h b/cpukit/score/include/rtems/score/threadq.h
index 1f99ffd..c483b87 100644
--- a/cpukit/score/include/rtems/score/threadq.h
+++ b/cpukit/score/include/rtems/score/threadq.h
@@ -21,9 +21,11 @@
 
 #include <rtems/score/chain.h>
 #include <rtems/score/isrlock.h>
+#include <rtems/score/percpu.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/rbtree.h>
 #include <rtems/score/states.h>
 #include <rtems/score/threadsync.h>
-#include <rtems/score/rbtree.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -40,6 +42,42 @@ extern "C" {
  */
 /**@{*/
 
+typedef struct Thread_queue_Control Thread_queue_Control;
+
+/**
+ * @brief Thread queue priority change operation.
+ *
+ * @param[in] the_thread The thread.
+ * @param[in] new_priority The new priority value.
+ * @param[in] queue The thread queue.
+ *
+ * @see Thread_queue_Operations.
+ */
+typedef void ( *Thread_queue_Priority_change_operation )(
+  Thread_Control       *the_thread,
+  Priority_Control      new_priority,
+  Thread_queue_Control *queue
+);
+
+/**
+ * @brief Thread queue operations.
+ *
+ * @see _Thread_wait_Set_operations().
+ */
+typedef struct {
+  /**
+   * @brief Thread queue priority change operation.
+   *
+   * Called by _Thread_Change_priority() to notify a thread about a priority
+   * change.  In case this thread waits currently for a resource the handler
+   * may adjust its data structures according to the new priority value.  This
+   * handler must not be NULL, instead the default handler
+   * _Thread_Do_nothing_priority_change() should be used in case nothing needs
+   * to be done during a priority change.
+   */
+  Thread_queue_Priority_change_operation priority_change;
+} Thread_queue_Operations;
+
 /**
  *  The following enumerated type details all of the disciplines
  *  supported by the Thread Queue Handler.
@@ -53,7 +91,7 @@ typedef enum {
  *  This is the structure used to manage sets of tasks which are blocked
  *  waiting to acquire a resource.
  */
-typedef struct {
+struct Thread_queue_Control {
   /** This union contains the data structures used to manage the blocked
    *  set of tasks which varies based upon the discipline.
    */
@@ -65,6 +103,11 @@ typedef struct {
   } Queues;
 
   /**
+   * @brief The operations for this thread queue.
+   */
+  const Thread_queue_Operations *operations;
+
+  /**
    * @brief Lock to protect this thread queue.
    *
    * It may be used to protect additional state of the object embedding this
@@ -83,7 +126,7 @@ typedef struct {
    *  waiting on this thread queue.
    */
   uint32_t                 timeout_status;
-}   Thread_queue_Control;
+};
 
 /**@}*/
 
diff --git a/cpukit/score/include/rtems/score/threadqimpl.h b/cpukit/score/include/rtems/score/threadqimpl.h
index ac018b1..2f484c3 100644
--- a/cpukit/score/include/rtems/score/threadqimpl.h
+++ b/cpukit/score/include/rtems/score/threadqimpl.h
@@ -280,6 +280,12 @@ RBTree_Compare_result _Thread_queue_Compare_priority(
   const RBTree_Node *right
 );
 
+extern const Thread_queue_Operations _Thread_queue_Operations_default;
+
+extern const Thread_queue_Operations _Thread_queue_Operations_FIFO;
+
+extern const Thread_queue_Operations _Thread_queue_Operations_priority;
+
 /**@}*/
 
 #ifdef __cplusplus
diff --git a/cpukit/score/src/thread.c b/cpukit/score/src/thread.c
index 88b3272..f4c5307 100644
--- a/cpukit/score/src/thread.c
+++ b/cpukit/score/src/thread.c
@@ -32,7 +32,7 @@ THREAD_OFFSET_ASSERT( RBNode );
 THREAD_OFFSET_ASSERT( current_state );
 THREAD_OFFSET_ASSERT( current_priority );
 THREAD_OFFSET_ASSERT( real_priority );
-THREAD_OFFSET_ASSERT( Priority );
+THREAD_OFFSET_ASSERT( priority_generation );
 THREAD_OFFSET_ASSERT( resource_count );
 THREAD_OFFSET_ASSERT( Wait );
 THREAD_OFFSET_ASSERT( Timer );
diff --git a/cpukit/score/src/threadchangepriority.c b/cpukit/score/src/threadchangepriority.c
index a011a8f..3223544 100644
--- a/cpukit/score/src/threadchangepriority.c
+++ b/cpukit/score/src/threadchangepriority.c
@@ -41,21 +41,21 @@ void _Thread_Change_priority(
   if ( the_thread->current_priority != new_priority ) {
     uint32_t my_generation;
 
-    my_generation = the_thread->Priority.generation + 1;
+    my_generation = the_thread->priority_generation + 1;
     the_thread->current_priority = new_priority;
-    the_thread->Priority.generation = my_generation;
+    the_thread->priority_generation = my_generation;
 
-    (*the_thread->Priority.change_handler)(
+    ( *the_thread->Wait.operations->priority_change )(
       the_thread,
       new_priority,
-      the_thread->Priority.change_handler_context
+      the_thread->Wait.queue
     );
 
     _Thread_Lock_release( lock, &lock_context );
 
     _Scheduler_Acquire( the_thread, &lock_context );
 
-    if ( the_thread->Priority.generation == my_generation ) {
+    if ( the_thread->priority_generation == my_generation ) {
       if ( _States_Is_ready( the_thread->current_state ) ) {
         _Scheduler_Change_priority(
           the_thread,
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index 27c3f06..9f5df25 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -29,15 +29,6 @@
 #include <rtems/score/cpusetimpl.h>
 #include <rtems/config.h>
 
-void _Thread_Priority_change_do_nothing(
-  Thread_Control   *the_thread,
-  Priority_Control  new_priority,
-  void             *context
-)
-{
-  /* Do nothing */
-}
-
 bool _Thread_Initialize(
   Objects_Information                  *information,
   Thread_Control                       *the_thread,
@@ -208,10 +199,10 @@ bool _Thread_Initialize(
 
   the_thread->current_state           = STATES_DORMANT;
   the_thread->Wait.queue              = NULL;
+  the_thread->Wait.operations         = &_Thread_queue_Operations_default;
   the_thread->resource_count          = 0;
   the_thread->real_priority           = priority;
-  the_thread->Priority.generation     = 0;
-  the_thread->Priority.change_handler = _Thread_Priority_change_do_nothing;
+  the_thread->priority_generation     = 0;
   the_thread->Start.initial_priority  = priority;
 
   _Thread_Wait_flags_set( the_thread, THREAD_WAIT_FLAGS_INITIAL );
diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c
index 76eaa30..6cc731e 100644
--- a/cpukit/score/src/threadqenqueue.c
+++ b/cpukit/score/src/threadqenqueue.c
@@ -46,7 +46,7 @@ static void _Thread_blocking_operation_Finalize(
   /*
    * The thread is not waiting on anything after this completes.
    */
-  the_thread->Wait.queue = NULL;
+  _Thread_Wait_set_queue( the_thread, NULL );
 
   _Thread_Lock_restore_default( the_thread );
 
@@ -75,23 +75,6 @@ static void _Thread_blocking_operation_Finalize(
 #endif
 }
 
-static void _Thread_queue_Requeue_priority(
-  Thread_Control   *the_thread,
-  Priority_Control  new_priority,
-  void             *context
-)
-{
-  Thread_queue_Control *tq = context;
-
-  _RBTree_Extract( &tq->Queues.Priority, &the_thread->RBNode );
-  _RBTree_Insert(
-    &tq->Queues.Priority,
-    &the_thread->RBNode,
-    _Thread_queue_Compare_priority,
-    false
-  );
-}
-
 void _Thread_queue_Enqueue_critical(
   Thread_queue_Control *the_thread_queue,
   Thread_Control       *the_thread,
@@ -105,7 +88,7 @@ void _Thread_queue_Enqueue_critical(
   _Thread_Lock_set( the_thread, &the_thread_queue->Lock );
 
   the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
-  the_thread->Wait.queue = the_thread_queue;
+  _Thread_Wait_set_queue( the_thread, the_thread_queue );
 
   _Thread_queue_Release( the_thread_queue, lock_context );
 
@@ -153,10 +136,9 @@ void _Thread_queue_Enqueue_critical(
         &the_thread->Object.Node
       );
     } else { /* must be THREAD_QUEUE_DISCIPLINE_PRIORITY */
-      _Thread_Priority_set_change_handler(
+      _Thread_Wait_set_operations(
         the_thread,
-        _Thread_queue_Requeue_priority,
-        the_thread_queue
+        &_Thread_queue_Operations_priority
       );
       _RBTree_Insert(
         &the_thread_queue->Queues.Priority,
@@ -206,7 +188,7 @@ void _Thread_queue_Extract_with_return_code(
       &the_thread->Wait.queue->Queues.Priority,
       &the_thread->RBNode
     );
-    _Thread_Priority_restore_default_change_handler( the_thread );
+    _Thread_Wait_restore_default_operations( the_thread );
   }
 
   the_thread->Wait.return_code = return_code;
@@ -252,7 +234,7 @@ Thread_Control *_Thread_queue_Dequeue(
     first = _RBTree_Get( &the_thread_queue->Queues.Priority, RBT_LEFT );
     if ( first ) {
       the_thread = THREAD_RBTREE_NODE_TO_THREAD( first );
-      _Thread_Priority_restore_default_change_handler( the_thread );
+      _Thread_Wait_restore_default_operations( the_thread );
     }
   }
 
diff --git a/cpukit/score/src/threadqops.c b/cpukit/score/src/threadqops.c
new file mode 100644
index 0000000..5614801
--- /dev/null
+++ b/cpukit/score/src/threadqops.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include <rtems/score/threadimpl.h>
+#include <rtems/score/rbtreeimpl.h>
+
+static void _Thread_queue_Do_nothing_priority_change(
+  Thread_Control       *the_thread,
+  Priority_Control      new_priority,
+  Thread_queue_Control *queue
+)
+{
+  /* Do nothing */
+}
+
+static void _Thread_queue_Priority_priority_change(
+  Thread_Control       *the_thread,
+  Priority_Control      new_priority,
+  Thread_queue_Control *queue
+)
+{
+  _RBTree_Extract( &queue->Queues.Priority, &the_thread->RBNode );
+  _RBTree_Insert(
+    &queue->Queues.Priority,
+    &the_thread->RBNode,
+    _Thread_queue_Compare_priority,
+    false
+  );
+}
+
+const Thread_queue_Operations _Thread_queue_Operations_default = {
+  .priority_change = _Thread_queue_Do_nothing_priority_change
+};
+
+const Thread_queue_Operations _Thread_queue_Operations_FIFO = {
+  .priority_change = _Thread_queue_Do_nothing_priority_change
+};
+
+const Thread_queue_Operations _Thread_queue_Operations_priority = {
+  .priority_change = _Thread_queue_Priority_priority_change
+};
diff --git a/testsuites/sptests/spintrcritical23/init.c b/testsuites/sptests/spintrcritical23/init.c
index 8536489..89fea25 100644
--- a/testsuites/sptests/spintrcritical23/init.c
+++ b/testsuites/sptests/spintrcritical23/init.c
@@ -70,7 +70,7 @@ static void change_priority(rtems_id timer, void *arg)
 
   rtems_interrupt_lock_acquire(&ctx->lock, &lock_context);
   if (
-    ctx->priority_generation != ctx->tcb->Priority.generation
+    ctx->priority_generation != ctx->tcb->priority_generation
       && scheduler_node_unchanged(ctx)
   ) {
     rtems_task_priority priority_interrupt;
@@ -113,7 +113,7 @@ static bool test_body(void *arg)
   priority_interrupt = 1 + (priority_task + 1) % 3;
   ctx->priority_task = priority_task;
   ctx->priority_interrupt = priority_interrupt;
-  ctx->priority_generation = ctx->tcb->Priority.generation;
+  ctx->priority_generation = ctx->tcb->priority_generation;
   memcpy(
     &ctx->scheduler_node,
     ctx->tcb->Scheduler.node,
-- 
1.8.4.5




More information about the devel mailing list