[PATCH] score: Add thread priority change notification

Sebastian Huber sebastian.huber at embedded-brains.de
Tue Mar 17 16:23:15 UTC 2015


Since the thread priority change is now performed atomically in one
critical section it is possible to simplify the thread queue update
procedure.  Add a thread queue agnostic thread priority change
notification handler so that we are able to use alternative thread queue
implementations.

Update #2273.
---
 cpukit/score/Makefile.am                       |  2 +-
 cpukit/score/include/rtems/score/thread.h      | 16 ++++++++++++++++
 cpukit/score/include/rtems/score/threadimpl.h  |  5 +++++
 cpukit/score/include/rtems/score/threadqimpl.h | 17 -----------------
 cpukit/score/src/threadchangepriority.c        |  2 +-
 cpukit/score/src/threadinitialize.c            | 19 ++++++++++++++-----
 cpukit/score/src/threadqdequeue.c              |  2 ++
 cpukit/score/src/threadqenqueue.c              | 19 +++++++++++++++++++
 cpukit/score/src/threadqextract.c              |  2 ++
 9 files changed, 60 insertions(+), 24 deletions(-)

diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index 509a243..ae407fe 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -299,7 +299,7 @@ endif
 
 ## THREADQ_C_FILES
 libscore_a_SOURCES += src/threadq.c src/threadqdequeue.c \
-    src/threadqenqueue.c src/threadqextract.c src/threadqrequeue.c \
+    src/threadqenqueue.c src/threadqextract.c \
     src/threadqextractwithproxy.c src/threadqfirst.c \
     src/threadqflush.c src/threadqprocesstimeout.c src/threadqtimeout.c
 
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index cea88f4..9b1d8d9 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -263,6 +263,17 @@ typedef union {
 } Thread_Wait_information_Object_argument_type;
 
 /**
+ * @brief Priority change notification handler.
+ *
+ * @param[in] the_thread The thread.
+ * @param[in] new_priority The new priority value.
+ */
+typedef void (*Thread_Wait_priority_change)(
+  Thread_Control   *the_thread,
+  Priority_Control  new_priority
+);
+
+/**
  * @brief This type is able to contain several flags used to control the wait
  * class and state of a thread.
  *
@@ -310,6 +321,11 @@ typedef struct {
   Thread_queue_Control *queue;
 
   /**
+   * @brief Priority change notification handler.
+   */
+  Thread_Wait_priority_change priority_change;
+
+  /**
    * @brief This field contains several flags used to control the wait class
    * and state of a thread in case fine-grained locking is used.
    */
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index 9d98fe8..a31ff9f 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -925,6 +925,11 @@ RTEMS_INLINE_ROUTINE bool _Thread_Owns_resources(
   return owns_resources;
 }
 
+void _Thread_Wait_priority_change_do_nothing(
+  Thread_Control   *the_thread,
+  Priority_Control  new_priority
+);
+
 /**
  * @brief The initial thread wait flags value set by _Thread_Initialize().
  */
diff --git a/cpukit/score/include/rtems/score/threadqimpl.h b/cpukit/score/include/rtems/score/threadqimpl.h
index 4a1084d..4c8d22e 100644
--- a/cpukit/score/include/rtems/score/threadqimpl.h
+++ b/cpukit/score/include/rtems/score/threadqimpl.h
@@ -266,23 +266,6 @@ RBTree_Compare_result _Thread_queue_Compare_priority(
 );
 
 /**
- *  @brief Invoked when a thread changes priority and is blocked.
- *
- *  This routine is invoked when a thread changes priority and is
- *  blocked on a thread queue.  If the queue is priority ordered,
- *  the_thread is removed from the_thread_queue and reinserted using
- *  its new priority.  This method has no impact on the state of the_thread
- *  or of any timeouts associated with this blocking.
- *
- *  @param[in] the_thread_queue pointer to a threadq header
- *  @param[in] the_thread pointer to a thread control block
- */
-void _Thread_queue_Requeue(
-  Thread_queue_Control *the_thread_queue,
-  Thread_Control       *the_thread
-);
-
-/**
  * This routine is invoked to indicate that the specified thread queue is
  * entering a critical section.
  */
diff --git a/cpukit/score/src/threadchangepriority.c b/cpukit/score/src/threadchangepriority.c
index 34a5a14..c209dbd 100644
--- a/cpukit/score/src/threadchangepriority.c
+++ b/cpukit/score/src/threadchangepriority.c
@@ -50,7 +50,7 @@ void _Thread_Change_priority(
       _Scheduler_Update_priority( the_thread, new_priority );
     }
 
-    _Thread_queue_Requeue( the_thread->Wait.queue, the_thread );
+    (*the_thread->Wait.priority_change)( the_thread, new_priority );
   }
 
   _ISR_Enable( level );
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index 934fea9..b0ce0e3 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -29,6 +29,14 @@
 #include <rtems/score/cpusetimpl.h>
 #include <rtems/config.h>
 
+void _Thread_Wait_priority_change_do_nothing(
+  Thread_Control   *the_thread,
+  Priority_Control  new_priority
+)
+{
+  /* Do nothing */
+}
+
 bool _Thread_Initialize(
   Objects_Information                  *information,
   Thread_Control                       *the_thread,
@@ -194,11 +202,12 @@ bool _Thread_Initialize(
   /* Initialize the CPU for the non-SMP schedulers */
   _Thread_Set_CPU( the_thread, cpu );
 
-  the_thread->current_state           = STATES_DORMANT;
-  the_thread->Wait.queue              = NULL;
-  the_thread->resource_count          = 0;
-  the_thread->real_priority           = priority;
-  the_thread->Start.initial_priority  = priority;
+  the_thread->current_state          = STATES_DORMANT;
+  the_thread->Wait.queue             = NULL;
+  the_thread->Wait.priority_change   = _Thread_Wait_priority_change_do_nothing;
+  the_thread->resource_count         = 0;
+  the_thread->real_priority          = priority;
+  the_thread->Start.initial_priority = priority;
 
   _Thread_Wait_flags_set( the_thread, THREAD_WAIT_FLAGS_INITIAL );
 
diff --git a/cpukit/score/src/threadqdequeue.c b/cpukit/score/src/threadqdequeue.c
index 52ba009..c8d355e 100644
--- a/cpukit/score/src/threadqdequeue.c
+++ b/cpukit/score/src/threadqdequeue.c
@@ -70,6 +70,8 @@ Thread_Control *_Thread_queue_Dequeue(
     }
   }
 
+  the_thread->Wait.priority_change = _Thread_Wait_priority_change_do_nothing;
+
   /*
    * We found a thread to unblock.
    *
diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c
index 0fa5fa6..bc0dc02 100644
--- a/cpukit/score/src/threadqenqueue.c
+++ b/cpukit/score/src/threadqenqueue.c
@@ -23,6 +23,23 @@
 #include <rtems/score/threadimpl.h>
 #include <rtems/score/watchdogimpl.h>
 
+static void _Thread_queue_Requeue_priority(
+  Thread_Control   *the_thread,
+  Priority_Control  new_priority
+)
+{
+  Thread_queue_Control *tq = the_thread->Wait.queue;
+
+  _Thread_queue_Enter_critical_section( tq );
+  _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_with_handler(
   Thread_queue_Control         *the_thread_queue,
   Thread_Control               *the_thread,
@@ -83,6 +100,8 @@ void _Thread_queue_Enqueue_with_handler(
         _Thread_queue_Compare_priority,
         false
       );
+
+      the_thread->Wait.priority_change = _Thread_queue_Requeue_priority;
     }
 
     the_thread->Wait.queue = the_thread_queue;
diff --git a/cpukit/score/src/threadqextract.c b/cpukit/score/src/threadqextract.c
index d12d3c8..b7772b9 100644
--- a/cpukit/score/src/threadqextract.c
+++ b/cpukit/score/src/threadqextract.c
@@ -46,6 +46,8 @@ void _Thread_queue_Extract_with_return_code(
       &the_thread->Wait.queue->Queues.Priority,
       &the_thread->RBNode
     );
+
+    the_thread->Wait.priority_change = _Thread_Wait_priority_change_do_nothing;
   }
 
   the_thread->Wait.return_code = return_code;
-- 
2.1.4



More information about the devel mailing list