rtems: Avoid Giant lock for some task operations

Avoid Giant lock for rtems_task_set_priority(), rtems_task_suspend() and
rtems_task_resume().

Update #2555.
This commit is contained in:
Sebastian Huber
2016-05-11 10:21:57 +02:00
parent 105b4e6fa5
commit 4d76300ae5
5 changed files with 164 additions and 137 deletions

View File

@@ -56,17 +56,6 @@ typedef enum {
RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE = 7, RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE = 7,
} RTEMS_tasks_MP_Remote_operations; } RTEMS_tasks_MP_Remote_operations;
/**
* The following data structure defines the packet used to perform
* remote task operations.
*/
typedef struct {
rtems_packet_prefix Prefix;
RTEMS_tasks_MP_Remote_operations operation;
rtems_name name;
rtems_task_priority the_priority;
} RTEMS_tasks_MP_Packet;
/** /**
* @brief RTEMS Tasks MP Send Process Packet * @brief RTEMS Tasks MP Send Process Packet
* *
@@ -82,17 +71,24 @@ void _RTEMS_tasks_MP_Send_process_packet (
); );
/** /**
* @brief _RTEMS_tasks_MP_Send_request_packet * @brief Issues a remote rtems_task_set_priority() request.
*
* This routine performs a remote procedure call so that a
* directive operation can be initiated on another node.
*/ */
rtems_status_code _RTEMS_tasks_MP_Send_request_packet ( rtems_status_code _RTEMS_tasks_MP_Set_priority(
RTEMS_tasks_MP_Remote_operations operation, rtems_id id,
Objects_Id task_id, rtems_task_priority new_priority,
rtems_task_priority the_priority rtems_task_priority *old_priority
); );
/**
* @brief Issues a remote rtems_task_suspend() request.
*/
rtems_status_code _RTEMS_tasks_MP_Suspend( rtems_id id );
/**
* @brief Issues a remote rtems_task_resume() request.
*/
rtems_status_code _RTEMS_tasks_MP_Resume( rtems_id id );
/** /**
* @brief _RTEMS_tasks_MP_Process_packet * @brief _RTEMS_tasks_MP_Process_packet
* *

View File

@@ -24,6 +24,17 @@
#include <rtems/score/threadimpl.h> #include <rtems/score/threadimpl.h>
#include <rtems/score/threadqimpl.h> #include <rtems/score/threadqimpl.h>
/**
* The following data structure defines the packet used to perform
* remote task operations.
*/
typedef struct {
rtems_packet_prefix Prefix;
RTEMS_tasks_MP_Remote_operations operation;
rtems_name name;
rtems_task_priority the_priority;
} RTEMS_tasks_MP_Packet;
RTEMS_STATIC_ASSERT( RTEMS_STATIC_ASSERT(
sizeof(RTEMS_tasks_MP_Packet) <= MP_PACKET_MINIMUM_PACKET_SIZE, sizeof(RTEMS_tasks_MP_Packet) <= MP_PACKET_MINIMUM_PACKET_SIZE,
RTEMS_tasks_MP_Packet RTEMS_tasks_MP_Packet
@@ -34,6 +45,17 @@ static RTEMS_tasks_MP_Packet *_RTEMS_tasks_MP_Get_packet( void )
return (RTEMS_tasks_MP_Packet *) _MPCI_Get_packet(); return (RTEMS_tasks_MP_Packet *) _MPCI_Get_packet();
} }
static RTEMS_tasks_MP_Packet *_RTEMS_tasks_MP_Get_request_packet(
Objects_Id id
)
{
if ( !_Thread_MP_Is_remote( id ) ) {
return NULL;
}
return _RTEMS_tasks_MP_Get_packet();
}
/* /*
* _RTEMS_tasks_MP_Send_process_packet * _RTEMS_tasks_MP_Send_process_packet
* *
@@ -73,54 +95,78 @@ void _RTEMS_tasks_MP_Send_process_packet (
} }
} }
/* static rtems_status_code _RTEMS_tasks_MP_Send_request_packet(
* _RTEMS_tasks_MP_Send_request_packet RTEMS_tasks_MP_Packet *the_packet,
* Objects_Id id,
*/ RTEMS_tasks_MP_Remote_operations operation
rtems_status_code _RTEMS_tasks_MP_Send_request_packet (
RTEMS_tasks_MP_Remote_operations operation,
Objects_Id task_id,
rtems_task_priority new_priority
) )
{ {
RTEMS_tasks_MP_Packet *the_packet;
switch ( operation ) {
case RTEMS_TASKS_MP_SUSPEND_REQUEST:
case RTEMS_TASKS_MP_RESUME_REQUEST:
case RTEMS_TASKS_MP_SET_PRIORITY_REQUEST:
the_packet = _RTEMS_tasks_MP_Get_packet();
the_packet->Prefix.the_class = MP_PACKET_TASKS; the_packet->Prefix.the_class = MP_PACKET_TASKS;
the_packet->Prefix.length = sizeof ( RTEMS_tasks_MP_Packet ); the_packet->Prefix.length = sizeof( *the_packet );
the_packet->Prefix.to_convert = sizeof ( RTEMS_tasks_MP_Packet ); the_packet->Prefix.to_convert = sizeof( *the_packet );
the_packet->Prefix.id = id;
the_packet->operation = operation; the_packet->operation = operation;
the_packet->Prefix.id = task_id;
the_packet->the_priority = new_priority;
return _MPCI_Send_request_packet( return _MPCI_Send_request_packet(
_Objects_Get_node( task_id ), _Objects_Get_node( id ),
&the_packet->Prefix, &the_packet->Prefix,
STATES_READY, /* Not used */ STATES_READY, /* Not used */
RTEMS_TIMEOUT RTEMS_TIMEOUT
); );
break; }
case RTEMS_TASKS_MP_ANNOUNCE_CREATE: rtems_status_code _RTEMS_tasks_MP_Set_priority(
case RTEMS_TASKS_MP_ANNOUNCE_DELETE: rtems_id id,
case RTEMS_TASKS_MP_SUSPEND_RESPONSE: rtems_task_priority new_priority,
case RTEMS_TASKS_MP_RESUME_RESPONSE: rtems_task_priority *old_priority
case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE: )
break; {
RTEMS_tasks_MP_Packet *the_packet;
the_packet = _RTEMS_tasks_MP_Get_request_packet( id );
if ( the_packet == NULL ) {
return RTEMS_INVALID_ID;
} }
/*
* The following line is included to satisfy compilers which the_packet->the_priority = new_priority;
* produce warnings when a function does not end with a return. _Thread_Executing->Wait.return_argument = old_priority;
*/ return _RTEMS_tasks_MP_Send_request_packet(
return RTEMS_SUCCESSFUL; the_packet,
id,
RTEMS_TASKS_MP_SET_PRIORITY_REQUEST
);
}
rtems_status_code _RTEMS_tasks_MP_Suspend( rtems_id id )
{
RTEMS_tasks_MP_Packet *the_packet;
the_packet = _RTEMS_tasks_MP_Get_request_packet( id );
if ( the_packet == NULL ) {
return RTEMS_INVALID_ID;
}
return _RTEMS_tasks_MP_Send_request_packet(
the_packet,
id,
RTEMS_TASKS_MP_SUSPEND_REQUEST
);
}
rtems_status_code _RTEMS_tasks_MP_Resume( rtems_id id )
{
RTEMS_tasks_MP_Packet *the_packet;
the_packet = _RTEMS_tasks_MP_Get_request_packet( id );
if ( the_packet == NULL ) {
return RTEMS_INVALID_ID;
}
return _RTEMS_tasks_MP_Send_request_packet(
the_packet,
id,
RTEMS_TASKS_MP_RESUME_REQUEST
);
} }
/* /*

View File

@@ -26,31 +26,26 @@ rtems_status_code rtems_task_resume(
) )
{ {
Thread_Control *the_thread; Thread_Control *the_thread;
Objects_Locations location; ISR_lock_Context lock_context;
Per_CPU_Control *cpu_self;
States_Control previous_state; States_Control previous_state;
the_thread = _Thread_Get( id, &location ); the_thread = _Thread_Get_interrupt_disable( id, &lock_context );
switch ( location ) {
case OBJECTS_LOCAL:
previous_state = _Thread_Clear_state( the_thread, STATES_SUSPENDED );
_Objects_Put( &the_thread->Object );
return _States_Is_suspended( previous_state ) ?
RTEMS_SUCCESSFUL : RTEMS_INCORRECT_STATE;
if ( the_thread == NULL ) {
#if defined(RTEMS_MULTIPROCESSING) #if defined(RTEMS_MULTIPROCESSING)
case OBJECTS_REMOTE: return _RTEMS_tasks_MP_Resume( id );
return _RTEMS_tasks_MP_Send_request_packet( #else
RTEMS_TASKS_MP_RESUME_REQUEST, return RTEMS_INVALID_ID;
id,
0 /* Not used */
);
#endif #endif
case OBJECTS_ERROR:
break;
} }
return RTEMS_INVALID_ID; cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
_ISR_lock_ISR_enable( &lock_context );
previous_state = _Thread_Clear_state( the_thread, STATES_SUSPENDED );
_Thread_Dispatch_enable( cpu_self );
return _States_Is_suspended( previous_state ) ?
RTEMS_SUCCESSFUL : RTEMS_INCORRECT_STATE;
} }

View File

@@ -28,7 +28,8 @@ rtems_status_code rtems_task_set_priority(
) )
{ {
Thread_Control *the_thread; Thread_Control *the_thread;
Objects_Locations location; ISR_lock_Context lock_context;
Per_CPU_Control *cpu_self;
if ( new_priority != RTEMS_CURRENT_PRIORITY && if ( new_priority != RTEMS_CURRENT_PRIORITY &&
!_RTEMS_tasks_Priority_is_valid( new_priority ) ) !_RTEMS_tasks_Priority_is_valid( new_priority ) )
@@ -37,10 +38,19 @@ rtems_status_code rtems_task_set_priority(
if ( !old_priority ) if ( !old_priority )
return RTEMS_INVALID_ADDRESS; return RTEMS_INVALID_ADDRESS;
the_thread = _Thread_Get( id, &location ); the_thread = _Thread_Get_interrupt_disable( id, &lock_context );
switch ( location ) {
if ( the_thread == NULL ) {
#if defined(RTEMS_MULTIPROCESSING)
return _RTEMS_tasks_MP_Set_priority( id, new_priority, old_priority );
#else
return RTEMS_INVALID_ID;
#endif
}
cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
_ISR_lock_ISR_enable( &lock_context );
case OBJECTS_LOCAL:
if ( new_priority != RTEMS_CURRENT_PRIORITY ) { if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
_Thread_Set_priority( _Thread_Set_priority(
the_thread, the_thread,
@@ -54,22 +64,7 @@ rtems_status_code rtems_task_set_priority(
the_thread->current_priority the_thread->current_priority
); );
} }
_Objects_Put( &the_thread->Object );
_Thread_Dispatch_enable( cpu_self );
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
#if defined(RTEMS_MULTIPROCESSING)
case OBJECTS_REMOTE:
_Thread_Executing->Wait.return_argument = old_priority;
return _RTEMS_tasks_MP_Send_request_packet(
RTEMS_TASKS_MP_SET_PRIORITY_REQUEST,
id,
new_priority
);
#endif
case OBJECTS_ERROR:
break;
}
return RTEMS_INVALID_ID;
} }

View File

@@ -26,31 +26,26 @@ rtems_status_code rtems_task_suspend(
) )
{ {
Thread_Control *the_thread; Thread_Control *the_thread;
Objects_Locations location; ISR_lock_Context lock_context;
Per_CPU_Control *cpu_self;
States_Control previous_state; States_Control previous_state;
the_thread = _Thread_Get( id, &location ); the_thread = _Thread_Get_interrupt_disable( id, &lock_context );
switch ( location ) {
case OBJECTS_LOCAL:
previous_state = _Thread_Set_state( the_thread, STATES_SUSPENDED );
_Objects_Put( &the_thread->Object );
return _States_Is_suspended( previous_state ) ?
RTEMS_ALREADY_SUSPENDED : RTEMS_SUCCESSFUL;
if ( the_thread == NULL ) {
#if defined(RTEMS_MULTIPROCESSING) #if defined(RTEMS_MULTIPROCESSING)
case OBJECTS_REMOTE: return _RTEMS_tasks_MP_Suspend( id );
return _RTEMS_tasks_MP_Send_request_packet( #else
RTEMS_TASKS_MP_SUSPEND_REQUEST, return RTEMS_INVALID_ID;
id,
0 /* Not used */
);
#endif #endif
case OBJECTS_ERROR:
break;
} }
return RTEMS_INVALID_ID; cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
_ISR_lock_ISR_enable( &lock_context );
previous_state = _Thread_Set_state( the_thread, STATES_SUSPENDED );
_Thread_Dispatch_enable( cpu_self );
return _States_Is_suspended( previous_state ) ?
RTEMS_ALREADY_SUSPENDED : RTEMS_SUCCESSFUL;
} }