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_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
*
@@ -82,17 +71,24 @@ void _RTEMS_tasks_MP_Send_process_packet (
);
/**
* @brief _RTEMS_tasks_MP_Send_request_packet
*
* This routine performs a remote procedure call so that a
* directive operation can be initiated on another node.
* @brief Issues a remote rtems_task_set_priority() request.
*/
rtems_status_code _RTEMS_tasks_MP_Send_request_packet (
RTEMS_tasks_MP_Remote_operations operation,
Objects_Id task_id,
rtems_task_priority the_priority
rtems_status_code _RTEMS_tasks_MP_Set_priority(
rtems_id id,
rtems_task_priority new_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
*

View File

@@ -24,6 +24,17 @@
#include <rtems/score/threadimpl.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(
sizeof(RTEMS_tasks_MP_Packet) <= MP_PACKET_MINIMUM_PACKET_SIZE,
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();
}
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
*
@@ -73,54 +95,78 @@ void _RTEMS_tasks_MP_Send_process_packet (
}
}
/*
* _RTEMS_tasks_MP_Send_request_packet
*
*/
static rtems_status_code _RTEMS_tasks_MP_Send_request_packet(
RTEMS_tasks_MP_Packet *the_packet,
Objects_Id id,
RTEMS_tasks_MP_Remote_operations operation
)
{
the_packet->Prefix.the_class = MP_PACKET_TASKS;
the_packet->Prefix.length = sizeof( *the_packet );
the_packet->Prefix.to_convert = sizeof( *the_packet );
the_packet->Prefix.id = id;
the_packet->operation = 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
return _MPCI_Send_request_packet(
_Objects_Get_node( id ),
&the_packet->Prefix,
STATES_READY, /* Not used */
RTEMS_TIMEOUT
);
}
rtems_status_code _RTEMS_tasks_MP_Set_priority(
rtems_id id,
rtems_task_priority new_priority,
rtems_task_priority *old_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.length = sizeof ( RTEMS_tasks_MP_Packet );
the_packet->Prefix.to_convert = sizeof ( RTEMS_tasks_MP_Packet );
the_packet->operation = operation;
the_packet->Prefix.id = task_id;
the_packet->the_priority = new_priority;
return _MPCI_Send_request_packet(
_Objects_Get_node( task_id ),
&the_packet->Prefix,
STATES_READY, /* Not used */
RTEMS_TIMEOUT
);
break;
case RTEMS_TASKS_MP_ANNOUNCE_CREATE:
case RTEMS_TASKS_MP_ANNOUNCE_DELETE:
case RTEMS_TASKS_MP_SUSPEND_RESPONSE:
case RTEMS_TASKS_MP_RESUME_RESPONSE:
case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE:
break;
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
* produce warnings when a function does not end with a return.
*/
return RTEMS_SUCCESSFUL;
the_packet->the_priority = new_priority;
_Thread_Executing->Wait.return_argument = old_priority;
return _RTEMS_tasks_MP_Send_request_packet(
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

@@ -25,32 +25,27 @@ rtems_status_code rtems_task_resume(
rtems_id id
)
{
Thread_Control *the_thread;
Objects_Locations location;
States_Control previous_state;
Thread_Control *the_thread;
ISR_lock_Context lock_context;
Per_CPU_Control *cpu_self;
States_Control previous_state;
the_thread = _Thread_Get( id, &location );
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;
the_thread = _Thread_Get_interrupt_disable( id, &lock_context );
if ( the_thread == NULL ) {
#if defined(RTEMS_MULTIPROCESSING)
case OBJECTS_REMOTE:
return _RTEMS_tasks_MP_Send_request_packet(
RTEMS_TASKS_MP_RESUME_REQUEST,
id,
0 /* Not used */
);
return _RTEMS_tasks_MP_Resume( id );
#else
return RTEMS_INVALID_ID;
#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

@@ -27,8 +27,9 @@ rtems_status_code rtems_task_set_priority(
rtems_task_priority *old_priority
)
{
Thread_Control *the_thread;
Objects_Locations location;
Thread_Control *the_thread;
ISR_lock_Context lock_context;
Per_CPU_Control *cpu_self;
if ( new_priority != RTEMS_CURRENT_PRIORITY &&
!_RTEMS_tasks_Priority_is_valid( new_priority ) )
@@ -37,39 +38,33 @@ rtems_status_code rtems_task_set_priority(
if ( !old_priority )
return RTEMS_INVALID_ADDRESS;
the_thread = _Thread_Get( id, &location );
switch ( location ) {
case OBJECTS_LOCAL:
if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
_Thread_Set_priority(
the_thread,
_RTEMS_tasks_Priority_to_Core( new_priority ),
old_priority,
false
);
*old_priority = _RTEMS_tasks_Priority_from_Core( *old_priority );
} else {
*old_priority = _RTEMS_tasks_Priority_from_Core(
the_thread->current_priority
);
}
_Objects_Put( &the_thread->Object );
return RTEMS_SUCCESSFUL;
the_thread = _Thread_Get_interrupt_disable( id, &lock_context );
if ( the_thread == NULL ) {
#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
);
return _RTEMS_tasks_MP_Set_priority( id, new_priority, old_priority );
#else
return RTEMS_INVALID_ID;
#endif
case OBJECTS_ERROR:
break;
}
return RTEMS_INVALID_ID;
cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
_ISR_lock_ISR_enable( &lock_context );
if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
_Thread_Set_priority(
the_thread,
_RTEMS_tasks_Priority_to_Core( new_priority ),
old_priority,
false
);
*old_priority = _RTEMS_tasks_Priority_from_Core( *old_priority );
} else {
*old_priority = _RTEMS_tasks_Priority_from_Core(
the_thread->current_priority
);
}
_Thread_Dispatch_enable( cpu_self );
return RTEMS_SUCCESSFUL;
}

View File

@@ -25,32 +25,27 @@ rtems_status_code rtems_task_suspend(
rtems_id id
)
{
Thread_Control *the_thread;
Objects_Locations location;
States_Control previous_state;
Thread_Control *the_thread;
ISR_lock_Context lock_context;
Per_CPU_Control *cpu_self;
States_Control previous_state;
the_thread = _Thread_Get( id, &location );
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;
the_thread = _Thread_Get_interrupt_disable( id, &lock_context );
if ( the_thread == NULL ) {
#if defined(RTEMS_MULTIPROCESSING)
case OBJECTS_REMOTE:
return _RTEMS_tasks_MP_Send_request_packet(
RTEMS_TASKS_MP_SUSPEND_REQUEST,
id,
0 /* Not used */
);
return _RTEMS_tasks_MP_Suspend( id );
#else
return RTEMS_INVALID_ID;
#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;
}