[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