rtems: Rework RTEMS API to SuperCore priority

Use same structure as POSIX API for thread priority conversion to/from
SuperCore.
This commit is contained in:
Sebastian Huber
2016-06-21 17:12:40 +02:00
parent 1a4eac500c
commit c82835a231
13 changed files with 226 additions and 118 deletions

View File

@@ -365,16 +365,14 @@ void rtems_capture_initialize_task( rtems_tcb* tcb )
void rtems_capture_record_task( rtems_tcb* tcb )
{
rtems_capture_task_record_t rec;
void* ptr;
rtems_capture_task_record_t rec;
void* ptr;
rtems_interrupt_lock_context lock_context;
rtems_object_get_classic_name( tcb->Object.id, &rec.name );
rec.stack_size = tcb->Start.Initial_stack.size;
rec.start_priority = _RTEMS_tasks_Priority_from_Core(
tcb->Start.initial_priority
);
rec.start_priority = rtems_capture_task_start_priority (tcb);
rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
tcb->Capture.flags |= RTEMS_CAPTURE_RECORD_TASK;

View File

@@ -47,6 +47,7 @@ extern "C" {
#include <rtems.h>
#include <rtems/rtems/tasksimpl.h>
#include <rtems/score/schedulerimpl.h>
/**
* The number of tasks in a trigger group.
@@ -737,7 +738,8 @@ rtems_capture_task_control_flags (rtems_tcb* tcb)
static inline rtems_task_priority
rtems_capture_task_start_priority (rtems_tcb* tcb)
{
return _RTEMS_tasks_Priority_from_Core(
return _RTEMS_Priority_From_core(
_Scheduler_Get_own( tcb ),
tcb->Start.initial_priority
);
}

View File

@@ -19,6 +19,7 @@
#include <rtems/rtems/tasks.h>
#include <rtems/score/objectimpl.h>
#include <rtems/score/scheduler.h>
#include <rtems/score/threadimpl.h>
#ifdef __cplusplus
@@ -74,43 +75,47 @@ RTEMS_INLINE_ROUTINE void _RTEMS_tasks_Free (
}
/**
* @brief Converts an RTEMS API priority into a core priority.
* @brief Converts the RTEMS API priority to the corresponding SuperCore
* priority and validates it.
*
* This function converts an RTEMS API priority into a core priority.
* The RTEMS API system priority is accepted as valid.
*
* @param[in] scheduler The scheduler instance.
* @param[in] priority The RTEMS API priority to convert and validate.
* @param[out] valid Indicates if the RTEMS API priority is valid and a
* corresponding SuperCore priority in the specified scheduler instance
* exists.
*
* @return The corresponding SuperCore priority.
*/
RTEMS_INLINE_ROUTINE Priority_Control _RTEMS_tasks_Priority_to_Core(
rtems_task_priority priority
RTEMS_INLINE_ROUTINE Priority_Control _RTEMS_Priority_To_core(
const Scheduler_Control *scheduler,
rtems_task_priority priority,
bool *valid
)
{
*valid = ( priority <= scheduler->maximum_priority );
return (Priority_Control) priority;
}
/**
* @brief Converts a core priority into an RTEMS API priority.
* @brief Converts the SuperCore priority to the corresponding RTEMS API
* priority.
*
* This function converts a core priority into an RTEMS API priority.
* @param[in] scheduler The scheduler instance.
* @param[in] priority The SuperCore priority to convert.
*
* @return The corresponding RTEMS API priority.
*/
RTEMS_INLINE_ROUTINE rtems_task_priority _RTEMS_tasks_Priority_from_Core (
Priority_Control priority
RTEMS_INLINE_ROUTINE rtems_task_priority _RTEMS_Priority_From_core(
const Scheduler_Control *scheduler,
Priority_Control priority
)
{
return (rtems_task_priority) priority;
}
/**
* @brief Checks whether the priority is a valid user task.
*
* This function returns TRUE if the_priority is a valid user task priority
* and FALSE otherwise.
*/
RTEMS_INLINE_ROUTINE bool _RTEMS_tasks_Priority_is_valid (
rtems_task_priority the_priority
)
{
return ( ( the_priority >= RTEMS_MINIMUM_PRIORITY ) &&
( the_priority <= RTEMS_MAXIMUM_PRIORITY ) );
}
/**@}*/
#if defined(RTEMS_MULTIPROCESSING)

View File

@@ -22,6 +22,7 @@
#include <rtems/rtems/attrimpl.h>
#include <rtems/rtems/statusimpl.h>
#include <rtems/rtems/tasksimpl.h>
#include <rtems/score/schedulerimpl.h>
#include <rtems/score/sysstate.h>
#define SEMAPHORE_KIND_MASK ( RTEMS_SEMAPHORE_CLASS | RTEMS_INHERIT_PRIORITY \
@@ -35,12 +36,15 @@ rtems_status_code rtems_semaphore_create(
rtems_id *id
)
{
Semaphore_Control *the_semaphore;
Thread_Control *executing;
Status_Control status;
rtems_attribute maybe_global;
rtems_attribute mutex_with_protocol;
Semaphore_Variant variant;
Semaphore_Control *the_semaphore;
Thread_Control *executing;
Status_Control status;
rtems_attribute maybe_global;
rtems_attribute mutex_with_protocol;
Semaphore_Variant variant;
const Scheduler_Control *scheduler;
bool valid;
Priority_Control priority;
if ( !rtems_is_name_valid( name ) )
return RTEMS_INVALID_NAME;
@@ -122,7 +126,6 @@ rtems_status_code rtems_semaphore_create(
}
#endif
priority_ceiling = _RTEMS_tasks_Priority_to_Core( priority_ceiling );
executing = _Thread_Get_executing();
the_semaphore->variant = variant;
@@ -154,42 +157,57 @@ rtems_status_code rtems_semaphore_create(
status = STATUS_SUCCESSFUL;
break;
case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING:
_CORE_ceiling_mutex_Initialize(
&the_semaphore->Core_control.Mutex,
priority_ceiling
);
scheduler = _Scheduler_Get_own( executing );
priority = _RTEMS_Priority_To_core( scheduler, priority_ceiling, &valid );
if ( count == 0 ) {
Thread_queue_Context queue_context;
_Thread_queue_Context_initialize( &queue_context );
_ISR_lock_ISR_disable( &queue_context.Lock_context );
_CORE_mutex_Acquire_critical(
&the_semaphore->Core_control.Mutex.Recursive.Mutex,
&queue_context
);
status = _CORE_ceiling_mutex_Set_owner(
if ( valid ) {
_CORE_ceiling_mutex_Initialize(
&the_semaphore->Core_control.Mutex,
executing,
&queue_context
priority
);
if ( status != STATUS_SUCCESSFUL ) {
_Thread_queue_Destroy( &the_semaphore->Core_control.Wait_queue );
if ( count == 0 ) {
Thread_queue_Context queue_context;
_Thread_queue_Context_initialize( &queue_context );
_ISR_lock_ISR_disable( &queue_context.Lock_context );
_CORE_mutex_Acquire_critical(
&the_semaphore->Core_control.Mutex.Recursive.Mutex,
&queue_context
);
status = _CORE_ceiling_mutex_Set_owner(
&the_semaphore->Core_control.Mutex,
executing,
&queue_context
);
if ( status != STATUS_SUCCESSFUL ) {
_Thread_queue_Destroy( &the_semaphore->Core_control.Wait_queue );
}
} else {
status = STATUS_SUCCESSFUL;
}
} else {
status = STATUS_SUCCESSFUL;
status = STATUS_INVALID_PRIORITY;
}
break;
#if defined(RTEMS_SMP)
case SEMAPHORE_VARIANT_MRSP:
status = _MRSP_Initialize(
&the_semaphore->Core_control.MRSP,
priority_ceiling,
executing,
count == 0
);
scheduler = _Scheduler_Get_own( executing );
priority = _RTEMS_Priority_To_core( scheduler, priority_ceiling, &valid );
if ( valid ) {
status = _MRSP_Initialize(
&the_semaphore->Core_control.MRSP,
priority,
executing,
count == 0
);
} else {
status = STATUS_INVALID_PRIORITY;
}
break;
#endif
default:

View File

@@ -21,21 +21,26 @@
#include <rtems/score/schedulerimpl.h>
static rtems_status_code _Semaphore_Set_priority(
Semaphore_Control *the_semaphore,
rtems_id scheduler_id,
rtems_task_priority new_priority,
rtems_task_priority *old_priority_p,
Thread_queue_Context *queue_context
Semaphore_Control *the_semaphore,
const Scheduler_Control *scheduler,
rtems_task_priority new_priority,
rtems_task_priority *old_priority_p,
Thread_queue_Context *queue_context
)
{
rtems_status_code sc;
rtems_task_priority old_priority;
bool valid;
Priority_Control core_priority;
Priority_Control old_priority;
#if defined(RTEMS_SMP)
MRSP_Control *mrsp;
uint32_t scheduler_index;
#endif
new_priority = _RTEMS_tasks_Priority_to_Core( new_priority );
core_priority = _RTEMS_Priority_To_core( scheduler, new_priority, &valid );
if ( new_priority != RTEMS_CURRENT_PRIORITY && !valid ) {
return RTEMS_INVALID_PRIORITY;
}
switch ( the_semaphore->variant ) {
case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING:
@@ -47,7 +52,7 @@ static rtems_status_code _Semaphore_Set_priority(
old_priority = the_semaphore->Core_control.Mutex.priority_ceiling;
if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
the_semaphore->Core_control.Mutex.priority_ceiling = new_priority;
the_semaphore->Core_control.Mutex.priority_ceiling = core_priority;
}
_CORE_mutex_Release(
@@ -59,14 +64,14 @@ static rtems_status_code _Semaphore_Set_priority(
#if defined(RTEMS_SMP)
case SEMAPHORE_VARIANT_MRSP:
mrsp = &the_semaphore->Core_control.MRSP;
scheduler_index = _Scheduler_Get_index_by_id( scheduler_id );
scheduler_index = _Scheduler_Get_index( scheduler );
_MRSP_Acquire_critical( mrsp, queue_context );
old_priority = _MRSP_Get_ceiling_priority( mrsp, scheduler_index );
if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
_MRSP_Set_ceiling_priority( mrsp, scheduler_index, new_priority );
_MRSP_Set_ceiling_priority( mrsp, scheduler_index, core_priority );
}
_MRSP_Release( mrsp, queue_context );
@@ -86,7 +91,7 @@ static rtems_status_code _Semaphore_Set_priority(
break;
}
*old_priority_p = _RTEMS_tasks_Priority_from_Core( old_priority );
*old_priority_p = _RTEMS_Priority_From_core( scheduler, old_priority );
return sc;
}
@@ -98,19 +103,15 @@ rtems_status_code rtems_semaphore_set_priority(
rtems_task_priority *old_priority
)
{
Semaphore_Control *the_semaphore;
Thread_queue_Context queue_context;
if ( new_priority != RTEMS_CURRENT_PRIORITY &&
!_RTEMS_tasks_Priority_is_valid( new_priority ) ) {
return RTEMS_INVALID_PRIORITY;
}
const Scheduler_Control *scheduler;
Semaphore_Control *the_semaphore;
Thread_queue_Context queue_context;
if ( old_priority == NULL ) {
return RTEMS_INVALID_ADDRESS;
}
if ( !_Scheduler_Is_id_valid( scheduler_id ) ) {
if ( !_Scheduler_Get_by_id( scheduler_id, &scheduler ) ) {
return RTEMS_INVALID_ID;
}
@@ -128,7 +129,7 @@ rtems_status_code rtems_semaphore_set_priority(
return _Semaphore_Set_priority(
the_semaphore,
scheduler_id,
scheduler,
new_priority,
old_priority,
&queue_context

View File

@@ -37,6 +37,7 @@ rtems_status_code rtems_task_create(
)
{
Thread_Control *the_thread;
const Scheduler_Control *scheduler;
bool is_fp;
#if defined(RTEMS_MULTIPROCESSING)
Objects_MP_Control *the_global_object = NULL;
@@ -44,7 +45,8 @@ rtems_status_code rtems_task_create(
#endif
bool status;
rtems_attribute the_attribute_set;
Priority_Control core_priority;
bool valid;
Priority_Control priority;
RTEMS_API_Control *api;
ASR_Information *asr;
@@ -83,11 +85,17 @@ rtems_status_code rtems_task_create(
*/
if ( !_Attributes_Is_system_task( the_attribute_set ) ) {
if ( !_RTEMS_tasks_Priority_is_valid( initial_priority ) )
if ( initial_priority == PRIORITY_MINIMUM ) {
return RTEMS_INVALID_PRIORITY;
}
}
core_priority = _RTEMS_tasks_Priority_to_Core( initial_priority );
scheduler = _Scheduler_Get_by_CPU_index( _SMP_Get_current_processor() );
priority = _RTEMS_Priority_To_core( scheduler, initial_priority, &valid );
if ( !valid ) {
return RTEMS_INVALID_PRIORITY;
}
#if defined(RTEMS_MULTIPROCESSING)
if ( _Attributes_Is_global( the_attribute_set ) ) {
@@ -136,11 +144,11 @@ rtems_status_code rtems_task_create(
status = _Thread_Initialize(
&_RTEMS_tasks_Information,
the_thread,
_Scheduler_Get_by_CPU_index( _SMP_Get_current_processor() ),
scheduler,
NULL,
stack_size,
is_fp,
core_priority,
priority,
_Modes_Is_preempt(initial_modes) ? true : false,
_Modes_Is_timeslice(initial_modes) ?
THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE :

View File

@@ -19,52 +19,109 @@
#endif
#include <rtems/rtems/tasksimpl.h>
#include <rtems/score/schedulerimpl.h>
#include <rtems/score/threadimpl.h>
typedef struct {
const Scheduler_Control *scheduler;
rtems_task_priority new_priority;
Priority_Control old_priority;
rtems_status_code status;
} RTEMS_tasks_Set_priority_context;
static bool _RTEMS_tasks_Set_priority_filter(
Thread_Control *the_thread,
Priority_Control *new_priority_p,
void *arg
)
{
RTEMS_tasks_Set_priority_context *context;
const Scheduler_Control *scheduler;
bool valid;
Priority_Control current_priority;
Priority_Control new_priority;
context = arg;
scheduler = _Scheduler_Get_own( the_thread );
current_priority = the_thread->current_priority;
context->scheduler = scheduler;
context->old_priority = current_priority;
new_priority = _RTEMS_Priority_To_core(
scheduler,
context->new_priority,
&valid
);
*new_priority_p = new_priority;
if ( !valid ) {
context->status = RTEMS_INVALID_PRIORITY;
return false;
}
the_thread->real_priority = new_priority;
context->status = STATUS_SUCCESSFUL;
return _Thread_Priority_less_than( current_priority, new_priority )
|| !_Thread_Owns_resources( the_thread );
}
rtems_status_code rtems_task_set_priority(
rtems_id id,
rtems_task_priority new_priority,
rtems_task_priority *old_priority
rtems_task_priority *old_priority_p
)
{
Thread_Control *the_thread;
ISR_lock_Context lock_context;
Per_CPU_Control *cpu_self;
Thread_Control *the_thread;
ISR_lock_Context lock_context;
const Scheduler_Control *scheduler;
Priority_Control old_priority;
rtems_status_code status;
if ( new_priority != RTEMS_CURRENT_PRIORITY &&
!_RTEMS_tasks_Priority_is_valid( new_priority ) )
return RTEMS_INVALID_PRIORITY;
if ( !old_priority )
if ( old_priority_p == NULL ) {
return RTEMS_INVALID_ADDRESS;
}
the_thread = _Thread_Get( id, &lock_context );
if ( the_thread == NULL ) {
#if defined(RTEMS_MULTIPROCESSING)
return _RTEMS_tasks_MP_Set_priority( id, new_priority, old_priority );
return _RTEMS_tasks_MP_Set_priority( id, new_priority, old_priority_p );
#else
return RTEMS_INVALID_ID;
#endif
}
cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
_ISR_lock_ISR_enable( &lock_context );
if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
_Thread_Set_priority(
RTEMS_tasks_Set_priority_context context;
Per_CPU_Control *cpu_self;
cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
_ISR_lock_ISR_enable( &lock_context );
context.new_priority = new_priority;
_Thread_Change_priority(
the_thread,
_RTEMS_tasks_Priority_to_Core( new_priority ),
old_priority,
0,
&context,
_RTEMS_tasks_Set_priority_filter,
false
);
*old_priority = _RTEMS_tasks_Priority_from_Core( *old_priority );
_Thread_Dispatch_enable( cpu_self );
scheduler = context.scheduler;
old_priority = context.old_priority;
status = context.status;
} else {
*old_priority = _RTEMS_tasks_Priority_from_Core(
the_thread->current_priority
);
_Thread_State_acquire_critical( the_thread, &lock_context );
scheduler = _Scheduler_Get_own( the_thread );
old_priority = the_thread->current_priority;
_Thread_State_release( the_thread, &lock_context );
status = RTEMS_SUCCESSFUL;
}
_Thread_Dispatch_enable( cpu_self );
return RTEMS_SUCCESSFUL;
*old_priority_p = _RTEMS_Priority_From_core( scheduler, old_priority );
return status;
}

View File

@@ -153,14 +153,7 @@ static rtems_status_code _Timer_server_Initiate(
return RTEMS_INCORRECT_STATE;
}
/*
* Make sure the requested priority is valid. The if is
* structured so we check it is invalid before looking for
* a specific invalid value as the default.
*/
if ( !_RTEMS_tasks_Priority_is_valid( priority ) ) {
if ( priority != RTEMS_TIMER_SERVER_DEFAULT_PRIORITY )
return RTEMS_INVALID_PRIORITY;
if ( priority == RTEMS_TIMER_SERVER_DEFAULT_PRIORITY ) {
priority = PRIORITY_PSEUDO_ISR;
}

View File

@@ -86,6 +86,8 @@ typedef enum {
STATUS_BUILD( STATUS_CLASSIC_INTERNAL_ERROR, EINTR ),
STATUS_INVALID_NUMBER =
STATUS_BUILD( STATUS_CLASSIC_INVALID_NUMBER, EINVAL ),
STATUS_INVALID_PRIORITY =
STATUS_BUILD( STATUS_CLASSIC_INVALID_PRIORITY, EINVAL ),
STATUS_MAXIMUM_COUNT_EXCEEDED =
STATUS_BUILD( STATUS_CLASSIC_INTERNAL_ERROR, EOVERFLOW ),
STATUS_MESSAGE_INVALID_SIZE =

View File

@@ -61,6 +61,16 @@ rtems_task Init(
TEST_BEGIN();
puts( "Create semaphore - priority ceiling unlocked - invalid ceiling" );
sc = rtems_semaphore_create(
rtems_build_name( 'S', 'E', 'M', '1' ),
0,
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY_CEILING | RTEMS_PRIORITY,
UINT32_MAX,
&mutex
);
fatal_directive_status(sc, RTEMS_INVALID_PRIORITY, "rtems_semaphore_create");
puts( "Create semaphore - priority ceiling locked - violate ceiling" );
sc = rtems_semaphore_create(
rtems_build_name( 'S', 'E', 'M', '1' ),

View File

@@ -1,6 +1,7 @@
*** TEST 51 ***
*** BEGIN OF TEST SP 51 ***
Create semaphore - priority ceiling unlocked - invalid ceiling
Create semaphore - priority ceiling locked - violate ceiling
Create semaphore - priority ceiling unlocked
Obtain semaphore -- violate ceiling
Release semaphore we did not obtain
*** END OF TEST 51 ***
*** END OF TEST SP 51 ***

View File

@@ -45,8 +45,21 @@ static void create_not_defined(rtems_attribute attr)
static void test_mrsp_create_errors(void)
{
rtems_status_code sc;
rtems_id id;
puts("test MrsP create errors");
sc = rtems_semaphore_create(
rtems_build_name('M', 'R', 'S', 'P'),
1,
RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
| RTEMS_BINARY_SEMAPHORE,
UINT32_MAX,
&id
);
rtems_test_assert(sc == RTEMS_INVALID_PRIORITY);
create_not_defined(
RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
| RTEMS_COUNTING_SEMAPHORE

View File

@@ -66,7 +66,7 @@ rtems_task Init(
puts( "TA1 - rtems_timer_server_fire_when - RTEMS_INCORRECT_STATE" );
/* invalid priority */
status = rtems_timer_initiate_server( 0, 0, 0 );
status = rtems_timer_initiate_server( UINT32_MAX - 1, 0, 0 );
fatal_directive_status(
status,
RTEMS_INVALID_PRIORITY,