score: Avoid Giant lock for _Thread_Start()

Update #2555.
This commit is contained in:
Sebastian Huber
2016-05-13 14:07:23 +02:00
parent 54550e048d
commit 33829ce155
7 changed files with 45 additions and 80 deletions

View File

@@ -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
*/

View File

@@ -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;
Thread_Control *the_thread;
ISR_lock_Context lock_context;
bool ok;
if ( entry_point == NULL )
return RTEMS_INVALID_ADDRESS;
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;
}

View File

@@ -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
/**

View File

@@ -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.
*

View File

@@ -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 )

View File

@@ -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;
}

View File

@@ -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();