[PATCH 18/32] score: Avoid Giant lock for _Thread_Start()

Sebastian Huber sebastian.huber at embedded-brains.de
Wed May 18 09:20:37 UTC 2016


Update #2555.
---
 cpukit/posix/src/pthreadcreate.c              |  8 +---
 cpukit/rtems/src/taskstart.c                  | 58 +++++++--------------------
 cpukit/score/include/rtems/score/statesimpl.h |  2 +-
 cpukit/score/include/rtems/score/threadimpl.h | 18 +--------
 cpukit/score/src/mpci.c                       |  6 ++-
 cpukit/score/src/threadstart.c                | 27 +++++++++----
 testsuites/tmtests/tm26/task1.c               |  6 +--
 7 files changed, 45 insertions(+), 80 deletions(-)

diff --git a/cpukit/posix/src/pthreadcreate.c b/cpukit/posix/src/pthreadcreate.c
index 1fe3fe4..33fae37 100644
--- a/cpukit/posix/src/pthreadcreate.c
+++ b/cpukit/posix/src/pthreadcreate.c
@@ -229,12 +229,11 @@ int pthread_create(
   api->schedpolicy = schedpolicy;
   api->schedparam  = schedparam;
 
-  _Thread_Disable_dispatch();
-
   /*
    *  POSIX threads are allocated and started in one operation.
    */
-  status = _Thread_Start( the_thread, &entry );
+  _ISR_lock_ISR_disable( &lock_context );
+  status = _Thread_Start( the_thread, &entry, &lock_context );
 
   #if defined(RTEMS_DEBUG)
     /*
@@ -244,7 +243,6 @@ int pthread_create(
      *        thread while we are creating it.
      */
     if ( !status ) {
-      _Thread_Enable_dispatch();
       _POSIX_Threads_Free( the_thread );
       _Objects_Allocator_unlock();
       return EINVAL;
@@ -261,8 +259,6 @@ int pthread_create(
     _ISR_lock_ISR_enable( &lock_context );
   }
 
-  _Thread_Enable_dispatch();
-
   /*
    *  Return the id and indicate we successfully created the thread
    */
diff --git a/cpukit/rtems/src/taskstart.c b/cpukit/rtems/src/taskstart.c
index 416c2df..172979b 100644
--- a/cpukit/rtems/src/taskstart.c
+++ b/cpukit/rtems/src/taskstart.c
@@ -21,27 +21,10 @@
 #include <rtems/rtems/tasks.h>
 #include <rtems/score/threadimpl.h>
 
-/*
- *  rtems_task_start
- *
- *  This directive readies the thread identified by the "id"
- *  based on its current priorty, to await execution.  A thread
- *  can be started only from the dormant state.
- *
- *  Input parameters:
- *    id          - thread id
- *    entry_point - start execution address of thread
- *    argument    - thread argument
- *
- *  Output parameters:
- *    RTEMS_SUCCESSFUL - if successful
- *    error code        - if unsuccessful
- */
-
 rtems_status_code rtems_task_start(
-  rtems_id         	id,
-  rtems_task_entry 	entry_point,
-  rtems_task_argument	argument
+  rtems_id            id,
+  rtems_task_entry    entry_point,
+  rtems_task_argument argument
 )
 {
   Thread_Entry_information entry = {
@@ -53,36 +36,23 @@ rtems_status_code rtems_task_start(
       }
     }
   };
-  Thread_Control    *the_thread;
-  Objects_Locations  location;
-  bool               successfully_started;
-
-  if ( entry_point == NULL )
-    return RTEMS_INVALID_ADDRESS;
+  Thread_Control   *the_thread;
+  ISR_lock_Context  lock_context;
+  bool              ok;
 
-  the_thread = _Thread_Get( id, &location );
-  switch ( location ) {
-
-    case OBJECTS_LOCAL:
-      successfully_started = _Thread_Start( the_thread, &entry );
-
-      _Objects_Put( &the_thread->Object );
-
-      if ( successfully_started ) {
-        return RTEMS_SUCCESSFUL;
-      } else {
-        return RTEMS_INCORRECT_STATE;
-      }
+  the_thread = _Thread_Get_interrupt_disable( id, &lock_context );
 
+  if ( the_thread == NULL ) {
 #if defined(RTEMS_MULTIPROCESSING)
-    case OBJECTS_REMOTE:
-      _Thread_Dispatch();
+    if ( _Thread_MP_Is_remote( id ) ) {
       return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
+    }
 #endif
 
-    case OBJECTS_ERROR:
-      break;
+    return RTEMS_INVALID_ID;
   }
 
-  return RTEMS_INVALID_ID;
+  ok = _Thread_Start( the_thread, &entry, &lock_context );
+
+  return ok ? RTEMS_SUCCESSFUL : RTEMS_INCORRECT_STATE;
 }
diff --git a/cpukit/score/include/rtems/score/statesimpl.h b/cpukit/score/include/rtems/score/statesimpl.h
index 54052e2..596246c 100644
--- a/cpukit/score/include/rtems/score/statesimpl.h
+++ b/cpukit/score/include/rtems/score/statesimpl.h
@@ -123,7 +123,7 @@ extern "C" {
                                  STATES_WAITING_FOR_SYSTEM_EVENT | \
                                  STATES_INTERRUPTIBLE_BY_SIGNAL )
 
-/** All state bits set to one (provided for _Thread_Ready()) */
+/** All state bits set to one (provided for _Thread_Start()) */
 #define STATES_ALL_SET 0xffffffff
 
 /**
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index 749d488..3e64055 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -187,7 +187,8 @@ bool _Thread_Initialize(
  */
 bool _Thread_Start(
   Thread_Control                 *the_thread,
-  const Thread_Entry_information *entry
+  const Thread_Entry_information *entry,
+  ISR_lock_Context               *lock_context
 );
 
 void _Thread_Restart_self(
@@ -288,21 +289,6 @@ States_Control _Thread_Set_state(
 );
 
 /**
- * @brief Clears all thread states.
- *
- * In case the previous state is a non-ready state, then the thread is
- * unblocked by the scheduler.
- *
- * @param[in] the_thread The thread.
- */
-RTEMS_INLINE_ROUTINE void _Thread_Ready(
-  Thread_Control *the_thread
-)
-{
-  _Thread_Clear_state( the_thread, STATES_ALL_SET );
-}
-
-/**
  *  @brief Initializes enviroment for a thread.
  *
  *  This routine initializes the context of @a the_thread to its
diff --git a/cpukit/score/src/mpci.c b/cpukit/score/src/mpci.c
index 57eb5f3..8eec278 100644
--- a/cpukit/score/src/mpci.c
+++ b/cpukit/score/src/mpci.c
@@ -134,7 +134,8 @@ static void _MPCI_Create_server( void )
       }
     }
   };
-  Objects_Name name;
+  ISR_lock_Context lock_context;
+  Objects_Name     name;
 
 
   if ( !_System_state_Is_multiprocessing )
@@ -164,7 +165,8 @@ static void _MPCI_Create_server( void )
     name
   );
 
-  _Thread_Start( _MPCI_Receive_server_tcb, &entry );
+  _ISR_lock_ISR_disable( &lock_context );
+  _Thread_Start( _MPCI_Receive_server_tcb, &entry, &lock_context );
 }
 
 static void _MPCI_Initialization( void )
diff --git a/cpukit/score/src/threadstart.c b/cpukit/score/src/threadstart.c
index 0cdf2bc..676e34d 100644
--- a/cpukit/score/src/threadstart.c
+++ b/cpukit/score/src/threadstart.c
@@ -25,17 +25,28 @@
 
 bool _Thread_Start(
   Thread_Control                 *the_thread,
-  const Thread_Entry_information *entry
+  const Thread_Entry_information *entry,
+  ISR_lock_Context               *lock_context
 )
 {
-  if ( _States_Is_dormant( the_thread->current_state ) ) {
-    the_thread->Start.Entry = *entry;
-    _Thread_Load_environment( the_thread );
-    _Thread_Ready( the_thread );
-    _User_extensions_Thread_start( the_thread );
+  Per_CPU_Control *cpu_self;
 
-    return true;
+  _Thread_State_acquire_critical( the_thread, lock_context );
+
+  if ( !_States_Is_dormant( the_thread->current_state ) ) {
+    _Thread_State_release( the_thread, lock_context );
+    return false;
   }
 
-  return false;
+  the_thread->Start.Entry = *entry;
+  _Thread_Load_environment( the_thread );
+  _Thread_Clear_state_locked( the_thread, STATES_ALL_SET );
+
+  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
+  _Thread_State_release( the_thread, lock_context );
+
+  _User_extensions_Thread_start( the_thread );
+
+  _Thread_Dispatch_enable( cpu_self );
+  return true;
 }
diff --git a/testsuites/tmtests/tm26/task1.c b/testsuites/tmtests/tm26/task1.c
index a46f042..66bd409 100644
--- a/testsuites/tmtests/tm26/task1.c
+++ b/testsuites/tmtests/tm26/task1.c
@@ -194,13 +194,13 @@ static void thread_unblock( Thread_Control *thread )
 #endif
 }
 
-static void thread_ready( Thread_Control *thread )
+static void thread_clear_state( Thread_Control *thread, States_Control state  )
 {
 #if defined( PREVENT_SMP_ASSERT_FAILURES )
   _Thread_Disable_dispatch();
 #endif
 
-  _Thread_Ready( thread );
+  _Thread_Clear_state( thread, state );
 
 #if defined( PREVENT_SMP_ASSERT_FAILURES )
   _Thread_Unnest_dispatch();
@@ -559,7 +559,7 @@ void complete_test( void )
   thread_set_state( Middle_tcb, STATES_WAITING_FOR_MESSAGE );
 
   benchmark_timer_initialize();
-    thread_ready( Middle_tcb );
+    thread_clear_state( Middle_tcb, STATES_WAITING_FOR_MESSAGE );
   thread_ready_time = benchmark_timer_read();
 
   benchmark_timer_initialize();
-- 
1.8.4.5




More information about the devel mailing list