From 33829ce155069462ba410d396da431386369ed08 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 13 May 2016 14:07:23 +0200 Subject: score: Avoid Giant lock for _Thread_Start() 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 1fe3fe4465..33fae37776 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 416c2dfad2..172979bde3 100644 --- a/cpukit/rtems/src/taskstart.c +++ b/cpukit/rtems/src/taskstart.c @@ -21,27 +21,10 @@ #include #include -/* - * 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 54052e2b74..596246c422 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 cdd7f9b300..6f97ca9866 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( @@ -287,21 +288,6 @@ States_Control _Thread_Set_state( States_Control 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. * diff --git a/cpukit/score/src/mpci.c b/cpukit/score/src/mpci.c index 57eb5f3991..8eec2782c0 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 0cdf2bc85a..676e34da49 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 a46f042ac6..66bd4091b8 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(); -- cgit v1.2.3