[PATCH 4/8] score: Use a plain ticket lock for thread locks

Sebastian Huber sebastian.huber at embedded-brains.de
Thu Jul 23 12:54:44 UTC 2015


This enables external libraries to use thread locks since they are
independent of the actual RTEMS build configuration, e.g. profiling
enabled or disabled.
---
 cpukit/score/include/rtems/score/thread.h      | 20 ++++++-
 cpukit/score/include/rtems/score/threadimpl.h  | 80 ++++++++++++++++----------
 cpukit/score/include/rtems/score/threadq.h     |  8 ++-
 cpukit/score/include/rtems/score/threadqimpl.h | 46 +++++++++++++--
 cpukit/score/src/threadinitialize.c            |  3 +-
 cpukit/score/src/threadq.c                     |  3 +
 cpukit/score/src/threadqenqueue.c              |  2 +-
 cpukit/score/src/threadrestart.c               |  3 +-
 cpukit/score/src/threadtimeout.c               |  2 +-
 9 files changed, 125 insertions(+), 42 deletions(-)

diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index ac908e2..94ce31e 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -651,14 +651,30 @@ typedef struct  {
 typedef struct {
   /**
    * @brief The current thread lock.
+   *
+   * This is a plain ticket lock without SMP lock statistics support.  This
+   * enables external libraries to use thread locks since they are independent
+   * of the actual RTEMS build configuration, e.g. profiling enabled or
+   * disabled.
    */
-  ISR_lock_Control *current;
+  SMP_ticket_lock_Control *current;
 
   /**
    * @brief The default thread lock in case the thread is not blocked on a
    * resource.
    */
-  ISR_lock_Control Default;
+  SMP_ticket_lock_Control Default;
+
+#if defined(RTEMS_PROFILING)
+  /**
+   * @brief The thread lock statistics.
+   *
+   * These statistics are used by the executing thread in case it acquires a
+   * thread lock.  Thus the statistics are an aggregation of acquire and
+   * release operations of diffent locks.
+   */
+  SMP_lock_Stats Stats;
+#endif
 
   /**
    * @brief Generation number to invalidate stale locks.
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index 7b8f89c..0bf5cf4 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -970,45 +970,54 @@ RTEMS_INLINE_ROUTINE bool _Thread_Owns_resources(
 }
 
 /**
- * @brief Acquires the default thread lock and returns the executing thread.
+ * @brief Acquires the default thread lock inside a critical section
+ * (interrupts disabled).
  *
+ * @param[in] the_thread The thread.
  * @param[in] lock_context The lock context used for the corresponding lock
  * release.
  *
- * @return The executing thread.
- *
  * @see _Thread_Lock_release_default().
  */
-RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Lock_acquire_default_for_executing(
+RTEMS_INLINE_ROUTINE void _Thread_Lock_acquire_default_critical(
+  Thread_Control   *the_thread,
   ISR_lock_Context *lock_context
 )
 {
-  Thread_Control *executing;
-
-  _ISR_lock_ISR_disable( lock_context );
-  executing = _Thread_Executing;
-  _ISR_lock_Acquire( &executing->Lock.Default, lock_context );
-
-  return executing;
+  _Assert( _ISR_Get_level() != 0 );
+#if defined(RTEMS_SMP)
+  _SMP_ticket_lock_Acquire(
+    &the_thread->Lock.Default,
+    &_Thread_Executing->Lock.Stats,
+    &lock_context->Lock_context.Stats_context
+  );
+#else
+  (void) the_thread;
+  (void) lock_context;
+#endif
 }
 
 /**
- * @brief Acquires the default thread lock inside a critical section
- * (interrupts disabled).
+ * @brief Acquires the default thread lock and returns the executing thread.
  *
- * @param[in] the_thread The thread.
  * @param[in] lock_context The lock context used for the corresponding lock
  * release.
  *
+ * @return The executing thread.
+ *
  * @see _Thread_Lock_release_default().
  */
-RTEMS_INLINE_ROUTINE void _Thread_Lock_acquire_default_critical(
-  Thread_Control   *the_thread,
+RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Lock_acquire_default_for_executing(
   ISR_lock_Context *lock_context
 )
 {
-  _Assert( _ISR_Get_level() != 0 );
-  _ISR_lock_Acquire( &the_thread->Lock.Default, lock_context );
+  Thread_Control *executing;
+
+  _ISR_lock_ISR_disable( lock_context );
+  executing = _Thread_Executing;
+  _Thread_Lock_acquire_default_critical( executing, lock_context );
+
+  return executing;
 }
 
 /**
@@ -1025,7 +1034,8 @@ RTEMS_INLINE_ROUTINE void _Thread_Lock_acquire_default(
   ISR_lock_Context *lock_context
 )
 {
-  _ISR_lock_ISR_disable_and_acquire( &the_thread->Lock.Default, lock_context );
+  _ISR_lock_ISR_disable( lock_context );
+  _Thread_Lock_acquire_default_critical( the_thread, lock_context );
 }
 
 /**
@@ -1039,11 +1049,19 @@ RTEMS_INLINE_ROUTINE void _Thread_Lock_acquire_default(
  * acquire.
  */
 RTEMS_INLINE_ROUTINE void _Thread_Lock_release_critical(
-  ISR_lock_Control *lock,
+  void             *lock,
   ISR_lock_Context *lock_context
 )
 {
-  _ISR_lock_Release( lock, lock_context );
+#if defined(RTEMS_SMP)
+  _SMP_ticket_lock_Release(
+    lock,
+    &lock_context->Lock_context.Stats_context
+  );
+#else
+  (void) lock;
+  (void) lock_context;
+#endif
 }
 
 /**
@@ -1053,7 +1071,7 @@ RTEMS_INLINE_ROUTINE void _Thread_Lock_release_critical(
  * @param[in] lock_context The lock context used for _Thread_Lock_acquire().
  */
 RTEMS_INLINE_ROUTINE void _Thread_Lock_release(
-  ISR_lock_Control *lock,
+  void             *lock,
   ISR_lock_Context *lock_context
 )
 {
@@ -1110,13 +1128,13 @@ RTEMS_INLINE_ROUTINE void _Thread_Lock_release_default(
  *
  * @return The lock required by _Thread_Lock_release().
  */
-RTEMS_INLINE_ROUTINE ISR_lock_Control *_Thread_Lock_acquire(
+RTEMS_INLINE_ROUTINE void *_Thread_Lock_acquire(
   Thread_Control   *the_thread,
   ISR_lock_Context *lock_context
 )
 {
 #if defined(RTEMS_SMP)
-  ISR_lock_Control *lock;
+  SMP_ticket_lock_Control *lock;
 
   while ( true ) {
     uint32_t my_generation;
@@ -1131,7 +1149,11 @@ RTEMS_INLINE_ROUTINE ISR_lock_Control *_Thread_Lock_acquire(
     _Atomic_Fence( ATOMIC_ORDER_ACQUIRE );
 
     lock = the_thread->Lock.current;
-    _ISR_lock_Acquire( lock, lock_context );
+    _SMP_ticket_lock_Acquire(
+      lock,
+      &_Thread_Executing->Lock.Stats,
+      &lock_context->Lock_context.Stats_context
+    );
 
     /*
      * Ensure that we read the second lock generation after we obtained our
@@ -1160,8 +1182,8 @@ RTEMS_INLINE_ROUTINE ISR_lock_Control *_Thread_Lock_acquire(
  * instead.
  */
 RTEMS_INLINE_ROUTINE void _Thread_Lock_set_unprotected(
-  Thread_Control   *the_thread,
-  ISR_lock_Control *new_lock
+  Thread_Control          *the_thread,
+  SMP_ticket_lock_Control *new_lock
 )
 {
   the_thread->Lock.current = new_lock;
@@ -1196,8 +1218,8 @@ RTEMS_INLINE_ROUTINE void _Thread_Lock_set_unprotected(
  */
 #if defined(RTEMS_SMP)
 RTEMS_INLINE_ROUTINE void _Thread_Lock_set(
-  Thread_Control   *the_thread,
-  ISR_lock_Control *new_lock
+  Thread_Control          *the_thread,
+  SMP_ticket_lock_Control *new_lock
 )
 {
   ISR_lock_Context lock_context;
diff --git a/cpukit/score/include/rtems/score/threadq.h b/cpukit/score/include/rtems/score/threadq.h
index 7622551..8f2b138 100644
--- a/cpukit/score/include/rtems/score/threadq.h
+++ b/cpukit/score/include/rtems/score/threadq.h
@@ -75,7 +75,9 @@ typedef struct {
    * @see _Thread_queue_Acquire(), _Thread_queue_Acquire_critical() and
    * _Thread_queue_Release().
    */
-  ISR_LOCK_MEMBER( Lock )
+#if defined(RTEMS_SMP)
+  SMP_ticket_lock_Control Lock;
+#endif
 } Thread_queue_Queue;
 
 /**
@@ -191,6 +193,10 @@ typedef struct {
    */
   Thread_queue_Queue Queue;
 
+#if defined(RTEMS_SMP) && defined(RTEMS_PROFILING)
+  SMP_lock_Stats Lock_stats;
+#endif
+
   /**
    * @brief The operations for the actual thread queue.
    */
diff --git a/cpukit/score/include/rtems/score/threadqimpl.h b/cpukit/score/include/rtems/score/threadqimpl.h
index cf3aeed..05c3d7d 100644
--- a/cpukit/score/include/rtems/score/threadqimpl.h
+++ b/cpukit/score/include/rtems/score/threadqimpl.h
@@ -38,23 +38,50 @@ RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_initialize(
 )
 {
   queue->heads = NULL;
-  _ISR_lock_Initialize( &queue->Lock, "Thread Queue" );
+#if defined(RTEMS_SMP)
+  _SMP_ticket_lock_Initialize( &queue->Lock );
+#endif
 }
 
-RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_acquire_critical(
+RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_do_acquire_critical(
   Thread_queue_Queue *queue,
+#if defined(RTEMS_PROFILING)
+  SMP_lock_Stats     *lock_stats,
+#endif
   ISR_lock_Context   *lock_context
 )
 {
-  _ISR_lock_Acquire( &queue->Lock, lock_context );
+#if defined(RTEMS_SMP)
+  _SMP_ticket_lock_Acquire(
+    &queue->Lock,
+    lock_stats,
+    &lock_context->Lock_context.Stats_context
+  );
+#endif
 }
 
+#if defined( RTEMS_PROFILING )
+  #define \
+    _Thread_queue_Queue_acquire_critical( queue, lock_stats, lock_context ) \
+    _Thread_queue_Queue_do_acquire_critical( queue, lock_stats, lock_context )
+#else
+  #define \
+    _Thread_queue_Queue_acquire_critical( queue, lock_stats, lock_context ) \
+    _Thread_queue_Queue_do_acquire_critical( queue, lock_context )
+#endif
+
 RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_release(
   Thread_queue_Queue *queue,
   ISR_lock_Context   *lock_context
 )
 {
-  _ISR_lock_Release_and_ISR_enable( &queue->Lock, lock_context );
+#if defined(RTEMS_SMP)
+  _SMP_ticket_lock_Release(
+    &queue->Lock,
+    &lock_context->Lock_context.Stats_context
+  );
+#endif
+  _ISR_lock_ISR_enable( lock_context );
 }
 
 RTEMS_INLINE_ROUTINE void _Thread_queue_Acquire_critical(
@@ -64,6 +91,7 @@ RTEMS_INLINE_ROUTINE void _Thread_queue_Acquire_critical(
 {
   _Thread_queue_Queue_acquire_critical(
     &the_thread_queue->Queue,
+    &the_thread_queue->Lock_stats,
     lock_context
   );
 }
@@ -82,7 +110,10 @@ RTEMS_INLINE_ROUTINE void _Thread_queue_Release(
   ISR_lock_Context     *lock_context
 )
 {
-  _Thread_queue_Queue_release( &the_thread_queue->Queue, lock_context );
+  _Thread_queue_Queue_release(
+    &the_thread_queue->Queue,
+    lock_context
+  );
 }
 
 /**
@@ -429,7 +460,10 @@ RTEMS_INLINE_ROUTINE void _Thread_queue_Destroy(
   Thread_queue_Control *the_thread_queue
 )
 {
-  _ISR_lock_Destroy( &the_thread_queue->Queue.Lock );
+#if defined(RTEMS_SMP)
+  _SMP_ticket_lock_Destroy( &the_thread_queue->Queue.Lock );
+  _SMP_lock_Stats_destroy( &the_thread_queue->Lock_stats );
+#endif
 }
 
 /**
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index 7452c93..9a796e9 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -204,7 +204,8 @@ bool _Thread_Initialize(
   _Resource_Node_initialize( &the_thread->Resource_node );
   _CPU_Context_Set_is_executing( &the_thread->Registers, false );
   the_thread->Lock.current = &the_thread->Lock.Default;
-  _ISR_lock_Initialize( &the_thread->Lock.Default, "Thread Lock Default");
+  _SMP_ticket_lock_Initialize( &the_thread->Lock.Default );
+  _SMP_lock_Stats_initialize( &the_thread->Lock.Stats, "Thread Lock" );
   _SMP_lock_Stats_initialize( &the_thread->Potpourri_stats, "Thread Potpourri" );
   _Atomic_Init_uint(&the_thread->Lock.generation, 0);
 #endif
diff --git a/cpukit/score/src/threadq.c b/cpukit/score/src/threadq.c
index 27d4d58..fc81409 100644
--- a/cpukit/score/src/threadq.c
+++ b/cpukit/score/src/threadq.c
@@ -60,4 +60,7 @@ void _Thread_queue_Initialize(
   the_thread_queue->operations = operations;
 
   _Thread_queue_Queue_initialize( &the_thread_queue->Queue );
+#if defined(RTEMS_SMP)
+  _SMP_lock_Stats_initialize( &the_thread_queue->Lock_stats, "Thread Queue" );
+#endif
 }
diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c
index 1d1581a..960783c 100644
--- a/cpukit/score/src/threadqenqueue.c
+++ b/cpukit/score/src/threadqenqueue.c
@@ -168,7 +168,7 @@ void _Thread_queue_Extract_critical(
 void _Thread_queue_Extract( Thread_Control *the_thread )
 {
   ISR_lock_Context    lock_context;
-  ISR_lock_Control   *lock;
+  void               *lock;
   Thread_queue_Queue *queue;
 
   lock = _Thread_Lock_acquire( the_thread, &lock_context );
diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c
index 5d80beb..6d90587 100644
--- a/cpukit/score/src/threadrestart.c
+++ b/cpukit/score/src/threadrestart.c
@@ -129,7 +129,8 @@ static void _Thread_Free( Thread_Control *the_thread )
   _Workspace_Free( the_thread->Start.tls_area );
 
 #if defined(RTEMS_SMP)
-  _ISR_lock_Destroy( &the_thread->Lock.Default );
+  _SMP_ticket_lock_Destroy( &the_thread->Lock.Default );
+  _SMP_lock_Stats_destroy( &the_thread->Lock.Stats );
   _SMP_lock_Stats_destroy( &the_thread->Potpourri_stats );
 #endif
 
diff --git a/cpukit/score/src/threadtimeout.c b/cpukit/score/src/threadtimeout.c
index f69bc35..0e04998 100644
--- a/cpukit/score/src/threadtimeout.c
+++ b/cpukit/score/src/threadtimeout.c
@@ -36,7 +36,7 @@ static void _Thread_Do_timeout( Thread_Control *the_thread )
 void _Thread_Timeout( Objects_Id id, void *arg )
 {
   Thread_Control    *the_thread;
-  ISR_lock_Control  *thread_lock;
+  void              *thread_lock;
   ISR_lock_Context   lock_context;
   Thread_Wait_flags  wait_flags;
   Thread_Wait_flags  wait_class;
-- 
1.8.4.5



More information about the devel mailing list