Introduce map/unmap priority scheduler operations to map thread priority values from/to the user domain to/from the scheduler domain. Use the map priority operation to validate the thread priority. The EDF schedulers use this new operation to distinguish between normal priorities and priorities obtain through a job release. --- cpukit/libmisc/monitor/mon-sema.c | 6 +- cpukit/posix/include/rtems/posix/priorityimpl.h | 13 +- cpukit/posix/src/mutexgetprioceiling.c | 12 +- cpukit/posix/src/mutexinit.c | 6 +- cpukit/posix/src/mutexsetprioceiling.c | 36 ++-- cpukit/posix/src/psxpriorityisvalid.c | 25 ++- cpukit/posix/src/pthreadcreate.c | 3 +- cpukit/posix/src/pthreadgetschedparam.c | 9 +- cpukit/rtems/src/semcreate.c | 59 ++++--- cpukit/rtems/src/semsetpriority.c | 105 +++++++----- cpukit/rtems/src/tasksetpriority.c | 47 +++--- cpukit/score/Makefile.am | 2 + cpukit/score/include/rtems/score/coremutex.h | 9 + cpukit/score/include/rtems/score/coremuteximpl.h | 42 +++++ cpukit/score/include/rtems/score/mrspimpl.h | 39 +++-- cpukit/score/include/rtems/score/scheduler.h | 40 +++++ cpukit/score/include/rtems/score/schedulercbs.h | 2 + cpukit/score/include/rtems/score/scheduleredf.h | 12 ++ cpukit/score/include/rtems/score/schedulerimpl.h | 39 +++++ .../score/include/rtems/score/schedulerpriority.h | 2 + .../rtems/score/schedulerpriorityaffinitysmp.h | 2 + .../include/rtems/score/schedulerprioritysmp.h | 2 + cpukit/score/include/rtems/score/schedulersimple.h | 2 + .../score/include/rtems/score/schedulersimplesmp.h | 2 + .../score/include/rtems/score/schedulerstrongapa.h | 2 + cpukit/score/include/rtems/score/status.h | 5 + cpukit/score/include/rtems/score/threadimpl.h | 24 +++ cpukit/score/src/schedulerdefaultmappriority.c | 21 +++ cpukit/score/src/schedulerdefaultunmappriority.c | 23 +++ cpukit/score/src/scheduleredfchangepriority.c | 21 +++ cpukit/score/src/threadcreateidle.c | 11 +- cpukit/score/src/threadsetpriority.c | 57 +++++++ testsuites/psxtests/psxautoinit01/init.c | 4 + testsuites/smptests/Makefile.am | 1 + testsuites/smptests/configure.ac | 1 + testsuites/smptests/smppsxmutex01/Makefile.am | 19 +++ testsuites/smptests/smppsxmutex01/init.c | 184 +++++++++++++++++++++ .../smptests/smppsxmutex01/smppsxmutex01.doc | 12 ++ .../smptests/smppsxmutex01/smppsxmutex01.scn | 2 + testsuites/smptests/smpscheduler02/init.c | 35 +++- testsuites/sptests/sp51/init.c | 10 ++ testsuites/sptests/sp51/sp51.scn | 5 +- testsuites/sptests/spmrsp01/init.c | 13 ++ 43 files changed, 825 insertions(+), 141 deletions(-) create mode 100644 cpukit/score/src/schedulerdefaultmappriority.c create mode 100644 cpukit/score/src/schedulerdefaultunmappriority.c create mode 100644 testsuites/smptests/smppsxmutex01/Makefile.am create mode 100644 testsuites/smptests/smppsxmutex01/init.c create mode 100644 testsuites/smptests/smppsxmutex01/smppsxmutex01.doc create mode 100644 testsuites/smptests/smppsxmutex01/smppsxmutex01.scn
diff --git a/cpukit/libmisc/monitor/mon-sema.c b/cpukit/libmisc/monitor/mon-sema.c index 272391f..7334611 100644 --- a/cpukit/libmisc/monitor/mon-sema.c +++ b/cpukit/libmisc/monitor/mon-sema.c @@ -61,8 +61,10 @@ rtems_monitor_sema_canonical( switch ( rtems_sema->variant ) { case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING: - canonical_sema->priority_ceiling = - rtems_sema->Core_control.Mutex.priority_ceiling; + canonical_sema->priority_ceiling = _Scheduler_Unmap_priority( + _CORE_ceiling_mutex_Get_scheduler( &rtems_sema->Core_control.Mutex ), + _CORE_ceiling_mutex_Get_priority( &rtems_sema->Core_control.Mutex ) + ); /* Fall through */ case SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY: case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL: diff --git a/cpukit/posix/include/rtems/posix/priorityimpl.h b/cpukit/posix/include/rtems/posix/priorityimpl.h index 54f5c9c..bc59742 100644 --- a/cpukit/posix/include/rtems/posix/priorityimpl.h +++ b/cpukit/posix/include/rtems/posix/priorityimpl.h @@ -79,20 +79,17 @@ bool _POSIX_Priority_To_core( ); /** - * @brief Converts SuperCore priority to POSIX priority. + * @brief Converts SuperCore priority to the corresponding POSIX API priority. * * @param[in] scheduler The scheduler instance. - * @param[in] priority The SuperCore priority. + * @param[in] core_priority The SuperCore priority. * * @return Returns the corresponding POSIX API priority. */ -RTEMS_INLINE_ROUTINE int _POSIX_Priority_From_core( +int _POSIX_Priority_From_core( const Scheduler_Control *scheduler, - Priority_Control priority -) -{ - return (int) ( scheduler->maximum_priority - priority ); -} + Priority_Control core_priority +); /** @} */ diff --git a/cpukit/posix/src/mutexgetprioceiling.c b/cpukit/posix/src/mutexgetprioceiling.c index eda02cb..dfff98f 100644 --- a/cpukit/posix/src/mutexgetprioceiling.c +++ b/cpukit/posix/src/mutexgetprioceiling.c @@ -45,10 +45,14 @@ int pthread_mutex_getprioceiling( _POSIX_Mutex_Acquire_critical( the_mutex, &queue_context ); - *prioceiling = _POSIX_Priority_From_core( - &_Scheduler_Table[ 0 ], - the_mutex->Mutex.priority_ceiling - ); + if ( the_mutex->protocol == POSIX_MUTEX_PRIORITY_CEILING ) { + *prioceiling = _POSIX_Priority_From_core( + _CORE_ceiling_mutex_Get_scheduler( &the_mutex->Mutex ), + _CORE_ceiling_mutex_Get_priority( &the_mutex->Mutex ) + ); + } else { + *prioceiling = 0; + } _POSIX_Mutex_Release( the_mutex, &queue_context ); diff --git a/cpukit/posix/src/mutexinit.c b/cpukit/posix/src/mutexinit.c index 7fbb53a..0b5f19e 100644 --- a/cpukit/posix/src/mutexinit.c +++ b/cpukit/posix/src/mutexinit.c @@ -19,6 +19,7 @@ #endif #include <rtems/posix/muteximpl.h> +#include <rtems/posix/posixapi.h> #include <rtems/posix/priorityimpl.h> #include <rtems/score/schedulerimpl.h> @@ -133,10 +134,7 @@ int pthread_mutex_init( switch ( protocol ) { case POSIX_MUTEX_PRIORITY_CEILING: - _CORE_ceiling_mutex_Initialize( - &the_mutex->Mutex, - priority - ); + _CORE_ceiling_mutex_Initialize( &the_mutex->Mutex, scheduler, priority ); break; default: _Assert( diff --git a/cpukit/posix/src/mutexsetprioceiling.c b/cpukit/posix/src/mutexsetprioceiling.c index f1aa741..69aed16 100644 --- a/cpukit/posix/src/mutexsetprioceiling.c +++ b/cpukit/posix/src/mutexsetprioceiling.c @@ -19,6 +19,7 @@ #endif #include <rtems/posix/muteximpl.h> +#include <rtems/posix/posixapi.h> #include <rtems/posix/priorityimpl.h> /* @@ -31,14 +32,13 @@ int pthread_mutex_setprioceiling( int *old_ceiling ) { - POSIX_Mutex_Control *the_mutex; - const Scheduler_Control *scheduler; - Priority_Control priority; - int error; - int unlock_error; + POSIX_Mutex_Control *the_mutex; + int error; + int unlock_error; - if ( !old_ceiling ) + if ( old_ceiling == NULL ) { return EINVAL; + } /* * Must acquire the mutex before we can change it's ceiling. @@ -53,18 +53,24 @@ int pthread_mutex_setprioceiling( the_mutex = _POSIX_Mutex_Get_no_protection( mutex ); _Assert( the_mutex != NULL ); - scheduler = &_Scheduler_Table[ 0 ]; + if ( the_mutex->protocol == POSIX_MUTEX_PRIORITY_CEILING ) { + const Scheduler_Control *scheduler; + Priority_Control new_priority; + Priority_Control old_priority; - *old_ceiling = _POSIX_Priority_From_core( - scheduler, - the_mutex->Mutex.priority_ceiling - ); + scheduler = _CORE_ceiling_mutex_Get_scheduler( &the_mutex->Mutex ); + old_priority = _CORE_ceiling_mutex_Get_priority( &the_mutex->Mutex ); + *old_ceiling = _POSIX_Priority_From_core( scheduler, old_priority ); - if ( _POSIX_Priority_To_core( scheduler, prioceiling, &priority ) ) { - the_mutex->Mutex.priority_ceiling = priority; - error = 0; + if ( _POSIX_Priority_To_core( scheduler, prioceiling, &new_priority ) ) { + _CORE_ceiling_mutex_Set_priority( &the_mutex->Mutex, new_priority ); + error = 0; + } else { + error = EINVAL; + } } else { - error = EINVAL; + *old_ceiling = 0; + error = 0; } unlock_error = pthread_mutex_unlock( mutex ); diff --git a/cpukit/posix/src/psxpriorityisvalid.c b/cpukit/posix/src/psxpriorityisvalid.c index 2d3a0d4..48b2794 100644 --- a/cpukit/posix/src/psxpriorityisvalid.c +++ b/cpukit/posix/src/psxpriorityisvalid.c @@ -19,6 +19,7 @@ #endif #include <rtems/posix/priorityimpl.h> +#include <rtems/score/schedulerimpl.h> int _POSIX_Priority_Get_maximum( const Scheduler_Control *scheduler ) { @@ -36,13 +37,27 @@ bool _POSIX_Priority_To_core( ) { Priority_Control core_posix_priority; - Priority_Control core_priority; core_posix_priority = (Priority_Control) posix_priority; - core_priority = scheduler->maximum_priority - core_posix_priority; - *core_priority_p = core_priority; + if ( + posix_priority < POSIX_SCHEDULER_MINIMUM_PRIORITY + || core_posix_priority >= scheduler->maximum_priority + ) { + return false; + } + + *core_priority_p = scheduler->maximum_priority - core_posix_priority; + + return _Scheduler_Map_priority( scheduler, core_priority_p ); +} + +int _POSIX_Priority_From_core( + const Scheduler_Control *scheduler, + Priority_Control core_priority +) +{ + core_priority = _Scheduler_Unmap_priority( scheduler, core_priority ); - return posix_priority >= POSIX_SCHEDULER_MINIMUM_PRIORITY - && core_posix_priority < scheduler->maximum_priority; + return (int) ( scheduler->maximum_priority - core_priority ); } diff --git a/cpukit/posix/src/pthreadcreate.c b/cpukit/posix/src/pthreadcreate.c index b471625..887c9ae 100644 --- a/cpukit/posix/src/pthreadcreate.c +++ b/cpukit/posix/src/pthreadcreate.c @@ -102,6 +102,7 @@ int pthread_create( #endif executing = _Thread_Get_executing(); + scheduler = _Scheduler_Get_own( executing ); /* * P1003.1c/Draft 10, p. 121. @@ -194,7 +195,7 @@ int pthread_create( status = _Thread_Initialize( &_POSIX_Threads_Information, the_thread, - _Scheduler_Get( executing ), + scheduler, the_attr->stackaddr, _POSIX_Threads_Ensure_minimum_stack(the_attr->stacksize), is_fp, diff --git a/cpukit/posix/src/pthreadgetschedparam.c b/cpukit/posix/src/pthreadgetschedparam.c index 55e4048..4f91f95 100644 --- a/cpukit/posix/src/pthreadgetschedparam.c +++ b/cpukit/posix/src/pthreadgetschedparam.c @@ -26,6 +26,7 @@ #include <rtems/posix/pthreadimpl.h> #include <rtems/posix/priorityimpl.h> +#include <rtems/score/schedulerimpl.h> #include <rtems/score/threadimpl.h> #include <rtems/score/schedulerimpl.h> @@ -39,6 +40,7 @@ int pthread_getschedparam( ISR_lock_Context lock_context; POSIX_API_Control *api; const Scheduler_Control *scheduler; + Priority_Control priority; if ( policy == NULL || param == NULL ) { return EINVAL; @@ -58,11 +60,10 @@ int pthread_getschedparam( *param = api->Attributes.schedparam; scheduler = _Scheduler_Get_own( the_thread ); - param->sched_priority = _POSIX_Priority_From_core( - scheduler, - the_thread->real_priority - ); + priority = the_thread->real_priority; _Thread_Lock_release_default( the_thread, &lock_context ); + + param->sched_priority = _POSIX_Priority_From_core( scheduler, priority ); return 0; } diff --git a/cpukit/rtems/src/semcreate.c b/cpukit/rtems/src/semcreate.c index bb1c6b4..c7a7821 100644 --- a/cpukit/rtems/src/semcreate.c +++ b/cpukit/rtems/src/semcreate.c @@ -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,13 @@ 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; if ( !rtems_is_name_valid( name ) ) return RTEMS_INVALID_NAME; @@ -154,31 +156,38 @@ 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 - ); - - if ( count == 0 ) { - Thread_queue_Context queue_context; + scheduler = _Scheduler_Get_own( executing ); - _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 ( _Scheduler_Map_priority( scheduler, &priority_ceiling ) ) { + _CORE_ceiling_mutex_Initialize( &the_semaphore->Core_control.Mutex, - executing, - &queue_context + scheduler, + priority_ceiling ); - 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; diff --git a/cpukit/rtems/src/semsetpriority.c b/cpukit/rtems/src/semsetpriority.c index 455cc15..4afed04 100644 --- a/cpukit/rtems/src/semsetpriority.c +++ b/cpukit/rtems/src/semsetpriority.c @@ -17,60 +17,84 @@ #endif #include <rtems/rtems/semimpl.h> +#include <rtems/rtems/statusimpl.h> #include <rtems/rtems/tasksimpl.h> #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 +static Status_Control _Semaphore_Is_scheduler_valid( + const CORE_ceiling_mutex_Control *the_mutex, + const Scheduler_Control *scheduler ) { - rtems_status_code sc; - rtems_task_priority old_priority; #if defined(RTEMS_SMP) - MRSP_Control *mrsp; - uint32_t scheduler_index; + if ( scheduler != _CORE_ceiling_mutex_Get_scheduler( the_mutex ) ) { + return STATUS_NOT_DEFINED; + } #endif + return STATUS_SUCCESSFUL; +} + +static rtems_status_code _Semaphore_Set_priority( + 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_task_priority old_priority; + Status_Control status; + new_priority = _RTEMS_tasks_Priority_to_Core( new_priority ); + if ( !_Scheduler_Map_priority( scheduler, &new_priority ) ) { + return RTEMS_INVALID_PRIORITY; + } + + _Thread_queue_Acquire_critical( + &the_semaphore->Core_control.Wait_queue, + &queue_context->Lock_context + ); + switch ( the_semaphore->variant ) { case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING: - _CORE_mutex_Acquire_critical( - &the_semaphore->Core_control.Mutex.Recursive.Mutex, - queue_context + status = _Semaphore_Is_scheduler_valid( + &the_semaphore->Core_control.Mutex, + scheduler ); - old_priority = the_semaphore->Core_control.Mutex.priority_ceiling; + old_priority = _CORE_ceiling_mutex_Get_priority( + &the_semaphore->Core_control.Mutex + ); - if ( new_priority != RTEMS_CURRENT_PRIORITY ) { - the_semaphore->Core_control.Mutex.priority_ceiling = new_priority; + if ( + status == STATUS_SUCCESSFUL + && new_priority != RTEMS_CURRENT_PRIORITY + ) { + _CORE_ceiling_mutex_Set_priority( + &the_semaphore->Core_control.Mutex, + new_priority + ); } - _CORE_mutex_Release( - &the_semaphore->Core_control.Mutex.Recursive.Mutex, - queue_context - ); - sc = RTEMS_SUCCESSFUL; break; #if defined(RTEMS_SMP) case SEMAPHORE_VARIANT_MRSP: - mrsp = &the_semaphore->Core_control.MRSP; - scheduler_index = _Scheduler_Get_index_by_id( scheduler_id ); - - _MRSP_Acquire_critical( mrsp, queue_context ); - - old_priority = _MRSP_Get_ceiling_priority( mrsp, scheduler_index ); + old_priority = _MRSP_Get_priority( + &the_semaphore->Core_control.MRSP, + scheduler + ); if ( new_priority != RTEMS_CURRENT_PRIORITY ) { - _MRSP_Set_ceiling_priority( mrsp, scheduler_index, new_priority ); + _MRSP_Set_priority( + &the_semaphore->Core_control.MRSP, + scheduler, + new_priority + ); } - _MRSP_Release( mrsp, queue_context ); - sc = RTEMS_SUCCESSFUL; + status = STATUS_SUCCESSFUL; break; #endif default: @@ -80,15 +104,19 @@ static rtems_status_code _Semaphore_Set_priority( || the_semaphore->variant == SEMAPHORE_VARIANT_SIMPLE_BINARY || the_semaphore->variant == SEMAPHORE_VARIANT_COUNTING ); - _ISR_lock_ISR_enable( &queue_context->Lock_context ); old_priority = 0; - sc = RTEMS_NOT_DEFINED; + status = STATUS_NOT_DEFINED; break; } - *old_priority_p = _RTEMS_tasks_Priority_from_Core( old_priority ); + _Thread_queue_Release( + &the_semaphore->Core_control.Wait_queue, + &queue_context->Lock_context + ); - return sc; + old_priority = _Scheduler_Unmap_priority( scheduler, old_priority ); + *old_priority_p = _RTEMS_tasks_Priority_from_Core( old_priority ); + return _Status_Get( status ); } rtems_status_code rtems_semaphore_set_priority( @@ -98,8 +126,9 @@ rtems_status_code rtems_semaphore_set_priority( rtems_task_priority *old_priority ) { - Semaphore_Control *the_semaphore; - Thread_queue_Context queue_context; + const Scheduler_Control *scheduler; + Semaphore_Control *the_semaphore; + Thread_queue_Context queue_context; if ( new_priority != RTEMS_CURRENT_PRIORITY && !_RTEMS_tasks_Priority_is_valid( new_priority ) ) { @@ -110,7 +139,7 @@ rtems_status_code rtems_semaphore_set_priority( 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 +157,7 @@ rtems_status_code rtems_semaphore_set_priority( return _Semaphore_Set_priority( the_semaphore, - scheduler_id, + scheduler, new_priority, old_priority, &queue_context diff --git a/cpukit/rtems/src/tasksetpriority.c b/cpukit/rtems/src/tasksetpriority.c index 32a77f7..eff0740 100644 --- a/cpukit/rtems/src/tasksetpriority.c +++ b/cpukit/rtems/src/tasksetpriority.c @@ -19,52 +19,59 @@ #endif #include <rtems/rtems/tasksimpl.h> +#include <rtems/rtems/statusimpl.h> +#include <rtems/score/schedulerimpl.h> #include <rtems/score/threadimpl.h> 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; + Status_Control 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( + Per_CPU_Control *cpu_self; + + cpu_self = _Thread_Dispatch_disable_critical( &lock_context ); + _ISR_lock_ISR_enable( &lock_context ); + + status = _Thread_Map_and_set_priority( the_thread, _RTEMS_tasks_Priority_to_Core( new_priority ), - old_priority, - false + old_priority_p ); - *old_priority = _RTEMS_tasks_Priority_from_Core( *old_priority ); + + _Thread_Dispatch_enable( cpu_self ); } else { - *old_priority = _RTEMS_tasks_Priority_from_Core( - the_thread->current_priority - ); + const Scheduler_Control *scheduler; + Priority_Control old_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 ); + *old_priority_p = _Scheduler_Unmap_priority( scheduler, old_priority ); + status = STATUS_SUCCESSFUL; } - _Thread_Dispatch_enable( cpu_self ); - return RTEMS_SUCCESSFUL; + *old_priority_p = _RTEMS_tasks_Priority_from_Core( *old_priority_p ); + return _Status_Get( status ); } diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am index 7166d72..5437562 100644 --- a/cpukit/score/Makefile.am +++ b/cpukit/score/Makefile.am @@ -227,12 +227,14 @@ libscore_a_SOURCES += src/log2table.c libscore_a_SOURCES += src/scheduler.c libscore_a_SOURCES += src/schedulergetaffinity.c libscore_a_SOURCES += src/schedulersetaffinity.c +libscore_a_SOURCES += src/schedulerdefaultmappriority.c libscore_a_SOURCES += src/schedulerdefaultnodedestroy.c libscore_a_SOURCES += src/schedulerdefaultnodeinit.c libscore_a_SOURCES += src/schedulerdefaultreleasejob.c libscore_a_SOURCES += src/schedulerdefaultschedule.c libscore_a_SOURCES += src/schedulerdefaultstartidle.c libscore_a_SOURCES += src/schedulerdefaulttick.c +libscore_a_SOURCES += src/schedulerdefaultunmappriority.c libscore_a_SOURCES += src/schedulerdefaultupdate.c ## SCHEDULERPRIORITY_C_FILES diff --git a/cpukit/score/include/rtems/score/coremutex.h b/cpukit/score/include/rtems/score/coremutex.h index 26bb539..a3dcabf 100644 --- a/cpukit/score/include/rtems/score/coremutex.h +++ b/cpukit/score/include/rtems/score/coremutex.h @@ -27,6 +27,8 @@ #include <rtems/score/watchdog.h> #include <rtems/score/interr.h> +struct Scheduler_Control; + #ifdef __cplusplus extern "C" { #endif @@ -83,6 +85,13 @@ typedef struct { * @brief The priority ceiling value for the mutex owner. */ Priority_Control priority_ceiling; + +#if defined(RTEMS_SMP) + /** + * @brief The scheduler instance for this priority ceiling mutex. + */ + const struct Scheduler_Control *scheduler; +#endif } CORE_ceiling_mutex_Control; /**@}*/ diff --git a/cpukit/score/include/rtems/score/coremuteximpl.h b/cpukit/score/include/rtems/score/coremuteximpl.h index 956dfa8..3a5ae99 100644 --- a/cpukit/score/include/rtems/score/coremuteximpl.h +++ b/cpukit/score/include/rtems/score/coremuteximpl.h @@ -20,6 +20,7 @@ #include <rtems/score/coremutex.h> #include <rtems/score/chainimpl.h> +#include <rtems/score/schedulerimpl.h> #include <rtems/score/status.h> #include <rtems/score/threadimpl.h> #include <rtems/score/threadqimpl.h> @@ -358,11 +359,42 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_recursive_mutex_Surrender_no_protocol( RTEMS_INLINE_ROUTINE void _CORE_ceiling_mutex_Initialize( CORE_ceiling_mutex_Control *the_mutex, + const Scheduler_Control *scheduler, Priority_Control priority_ceiling ) { _CORE_recursive_mutex_Initialize( &the_mutex->Recursive ); the_mutex->priority_ceiling = priority_ceiling; +#if defined(RTEMS_SMP) + the_mutex->scheduler = scheduler; +#endif +} + +RTEMS_INLINE_ROUTINE const Scheduler_Control * +_CORE_ceiling_mutex_Get_scheduler( + const CORE_ceiling_mutex_Control *the_mutex +) +{ +#if defined(RTEMS_SMP) + return the_mutex->scheduler; +#else + return _Scheduler_Get_by_CPU_index( 0 ); +#endif +} + +RTEMS_INLINE_ROUTINE void _CORE_ceiling_mutex_Set_priority( + CORE_ceiling_mutex_Control *the_mutex, + Priority_Control priority_ceiling +) +{ + the_mutex->priority_ceiling = priority_ceiling; +} + +RTEMS_INLINE_ROUTINE Priority_Control _CORE_ceiling_mutex_Get_priority( + const CORE_ceiling_mutex_Control *the_mutex +) +{ + return the_mutex->priority_ceiling; } RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Set_owner( @@ -414,6 +446,16 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Seize( owner = _CORE_mutex_Get_owner( &the_mutex->Recursive.Mutex ); if ( owner == NULL ) { +#if defined(RTEMS_SMP) + if ( + _Scheduler_Get_own( executing ) + != _CORE_ceiling_mutex_Get_scheduler( the_mutex ) + ) { + _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context ); + return STATUS_NOT_DEFINED; + } +#endif + return _CORE_ceiling_mutex_Set_owner( the_mutex, executing, diff --git a/cpukit/score/include/rtems/score/mrspimpl.h b/cpukit/score/include/rtems/score/mrspimpl.h index cdeaff3..16bc8ff 100644 --- a/cpukit/score/include/rtems/score/mrspimpl.h +++ b/cpukit/score/include/rtems/score/mrspimpl.h @@ -159,7 +159,17 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Initialize( } for ( i = 0 ; i < scheduler_count ; ++i ) { + const Scheduler_Control *scheduler; + + scheduler = _Scheduler_Get_by_CPU_index( i ); mrsp->ceiling_priorities[ i ] = ceiling_priority; + + if ( + !_Scheduler_Map_priority( scheduler, &mrsp->ceiling_priorities[ i ] ) + ) { + _Workspace_Free( mrsp->ceiling_priorities ); + return STATUS_INVALID_PRIORITY; + } } _Resource_Initialize( &mrsp->Resource ); @@ -169,21 +179,30 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Initialize( return STATUS_SUCCESSFUL; } -RTEMS_INLINE_ROUTINE Priority_Control _MRSP_Get_ceiling_priority( - MRSP_Control *mrsp, - uint32_t scheduler_index +RTEMS_INLINE_ROUTINE Priority_Control _MRSP_Get_priority( + const MRSP_Control *mrsp, + const Scheduler_Control *scheduler ) { - return mrsp->ceiling_priorities[ scheduler_index ]; + uint32_t scheduler_index; + + scheduler_index = _Scheduler_Get_index( scheduler ); + return _Scheduler_Unmap_priority( + scheduler, + mrsp->ceiling_priorities[ scheduler_index ] + ); } -RTEMS_INLINE_ROUTINE void _MRSP_Set_ceiling_priority( - MRSP_Control *mrsp, - uint32_t scheduler_index, - Priority_Control ceiling_priority +RTEMS_INLINE_ROUTINE void _MRSP_Set_priority( + MRSP_Control *mrsp, + const Scheduler_Control *scheduler, + Priority_Control new_priority ) { - mrsp->ceiling_priorities[ scheduler_index ] = ceiling_priority; + uint32_t scheduler_index; + + scheduler_index = _Scheduler_Get_index( scheduler ); + mrsp->ceiling_priorities[ scheduler_index ] = new_priority; } RTEMS_INLINE_ROUTINE void _MRSP_Timeout( Watchdog_Control *watchdog ) @@ -310,7 +329,7 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Seize( uint32_t scheduler_index = _Scheduler_Get_index( scheduler ); Priority_Control initial_priority = executing->current_priority; Priority_Control ceiling_priority = - _MRSP_Get_ceiling_priority( mrsp, scheduler_index ); + mrsp->ceiling_priorities[ scheduler_index ]; bool priority_ok = !_Thread_Priority_less_than( ceiling_priority, initial_priority diff --git a/cpukit/score/include/rtems/score/scheduler.h b/cpukit/score/include/rtems/score/scheduler.h index 2e9aba5..c4e2bb9 100644 --- a/cpukit/score/include/rtems/score/scheduler.h +++ b/cpukit/score/include/rtems/score/scheduler.h @@ -91,6 +91,18 @@ typedef struct { bool ); + /** @see _Scheduler_Map_priority() */ + bool ( *map_priority )( + const Scheduler_Control *, + Priority_Control * + ); + + /** @see _Scheduler_Unmap_priority() */ + Priority_Control ( *unmap_priority )( + const Scheduler_Control *, + Priority_Control + ); + #if defined(RTEMS_SMP) /** * Ask for help operation. @@ -403,6 +415,34 @@ extern const Scheduler_Control _Scheduler_Table[]; extern const Scheduler_Assignment _Scheduler_Assignments[]; #endif +/** + * @brief Checks the priority is less than or equal to the maximum priority + * value of this scheduler instance. + * + * @param[in] scheduler The scheduler control. + * @param[in] priority The priority which is not modified. + * + * @retval true The priority is valid. + * @retval false Otherwise. + */ +bool _Scheduler_default_Map_priority( + const Scheduler_Control *scheduler, + Priority_Control *priority +); + +/** + * @brief Returns the priority. + * + * @param[in] scheduler Unused. + * @param[in] priority The priority. + * + * @return The priority. + */ +Priority_Control _Scheduler_default_Unmap_priority( + const Scheduler_Control *scheduler, + Priority_Control priority +); + #if defined(RTEMS_SMP) /** * @brief Does nothing. diff --git a/cpukit/score/include/rtems/score/schedulercbs.h b/cpukit/score/include/rtems/score/schedulercbs.h index 397488f..4e03e11 100644 --- a/cpukit/score/include/rtems/score/schedulercbs.h +++ b/cpukit/score/include/rtems/score/schedulercbs.h @@ -55,6 +55,8 @@ extern "C" { _Scheduler_EDF_Block, /* block entry point */ \ _Scheduler_CBS_Unblock, /* unblock entry point */ \ _Scheduler_EDF_Change_priority, /* change priority entry point */ \ + _Scheduler_EDF_Map_priority, /* map priority entry point */ \ + _Scheduler_EDF_Unmap_priority, /* unmap priority entry point */ \ SCHEDULER_OPERATION_DEFAULT_ASK_FOR_HELP \ _Scheduler_CBS_Node_initialize, /* node initialize entry point */ \ _Scheduler_default_Node_destroy, /* node destroy entry point */ \ diff --git a/cpukit/score/include/rtems/score/scheduleredf.h b/cpukit/score/include/rtems/score/scheduleredf.h index 7d513ca..8dfc187 100644 --- a/cpukit/score/include/rtems/score/scheduleredf.h +++ b/cpukit/score/include/rtems/score/scheduleredf.h @@ -48,6 +48,8 @@ extern "C" { _Scheduler_EDF_Block, /* block entry point */ \ _Scheduler_EDF_Unblock, /* unblock entry point */ \ _Scheduler_EDF_Change_priority, /* change priority entry point */ \ + _Scheduler_EDF_Map_priority, /* map priority entry point */ \ + _Scheduler_EDF_Unmap_priority, /* unmap priority entry point */ \ SCHEDULER_OPERATION_DEFAULT_ASK_FOR_HELP \ _Scheduler_EDF_Node_initialize, /* node initialize entry point */ \ _Scheduler_default_Node_destroy, /* node destroy entry point */ \ @@ -203,6 +205,16 @@ Scheduler_Void_or_thread _Scheduler_EDF_Change_priority( bool prepend_it ); +bool _Scheduler_EDF_Map_priority( + const Scheduler_Control *scheduler, + Priority_Control *priority +); + +Priority_Control _Scheduler_EDF_Unmap_priority( + const Scheduler_Control *scheduler, + Priority_Control priority +); + /** * @brief invoked when a thread wishes to voluntarily * transfer control of the processor to another thread diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h index 50061fb..fad7ecc 100644 --- a/cpukit/score/include/rtems/score/schedulerimpl.h +++ b/cpukit/score/include/rtems/score/schedulerimpl.h @@ -420,6 +420,45 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Change_priority( } /** + * @brief Maps a thread priority from the user domain to the scheduler domain. + * + * The mapping must be injective. A scheduler domain value must exist for all + * user domain values from 0 up to and including the maximum scheduler + * priority. + * + * @param[in] scheduler The scheduler instance. + * @param[in, out] priority The thread priority. + * + * @retval true The thread priority in the scheduler domain exists for the user + * specified thread priority. In this case the corresponding thread priority + * of the scheduler domain is returned. + * @retval false Otherwise. + */ +RTEMS_INLINE_ROUTINE bool _Scheduler_Map_priority( + const Scheduler_Control *scheduler, + Priority_Control *priority +) +{ + return ( *scheduler->Operations.map_priority )( scheduler, priority ); +} + +/** + * @brief Unmaps a thread priority from the scheduler domain to the user domain. + * + * @param[in] scheduler The scheduler instance. + * @param[in] priority The thread priority. + * + * @return The corresponding thread priority of the user domain is returned. + */ +RTEMS_INLINE_ROUTINE Priority_Control _Scheduler_Unmap_priority( + const Scheduler_Control *scheduler, + Priority_Control priority +) +{ + return ( *scheduler->Operations.unmap_priority )( scheduler, priority ); +} + +/** * @brief Initializes a scheduler node. * * The scheduler node contains arbitrary data on function entry. The caller diff --git a/cpukit/score/include/rtems/score/schedulerpriority.h b/cpukit/score/include/rtems/score/schedulerpriority.h index 0759941..d5e73c1 100644 --- a/cpukit/score/include/rtems/score/schedulerpriority.h +++ b/cpukit/score/include/rtems/score/schedulerpriority.h @@ -45,6 +45,8 @@ extern "C" { _Scheduler_priority_Block, /* block entry point */ \ _Scheduler_priority_Unblock, /* unblock entry point */ \ _Scheduler_priority_Change_priority, /* change priority entry point */ \ + _Scheduler_default_Map_priority, /* map priority entry point */ \ + _Scheduler_default_Unmap_priority, /* unmap priority entry point */ \ SCHEDULER_OPERATION_DEFAULT_ASK_FOR_HELP \ _Scheduler_default_Node_initialize, /* node initialize entry point */ \ _Scheduler_default_Node_destroy, /* node destroy entry point */ \ diff --git a/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h b/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h index e2d6f3b..b0a7044 100644 --- a/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h +++ b/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h @@ -55,6 +55,8 @@ extern "C" { _Scheduler_priority_affinity_SMP_Block, \ _Scheduler_priority_affinity_SMP_Unblock, \ _Scheduler_priority_affinity_SMP_Change_priority, \ + _Scheduler_default_Map_priority, \ + _Scheduler_default_Unmap_priority, \ _Scheduler_priority_affinity_SMP_Ask_for_help, \ _Scheduler_priority_affinity_SMP_Node_initialize, \ _Scheduler_default_Node_destroy, \ diff --git a/cpukit/score/include/rtems/score/schedulerprioritysmp.h b/cpukit/score/include/rtems/score/schedulerprioritysmp.h index d550c78..0af7000 100644 --- a/cpukit/score/include/rtems/score/schedulerprioritysmp.h +++ b/cpukit/score/include/rtems/score/schedulerprioritysmp.h @@ -84,6 +84,8 @@ typedef struct { _Scheduler_priority_SMP_Block, \ _Scheduler_priority_SMP_Unblock, \ _Scheduler_priority_SMP_Change_priority, \ + _Scheduler_default_Map_priority, \ + _Scheduler_default_Unmap_priority, \ _Scheduler_priority_SMP_Ask_for_help, \ _Scheduler_priority_SMP_Node_initialize, \ _Scheduler_default_Node_destroy, \ diff --git a/cpukit/score/include/rtems/score/schedulersimple.h b/cpukit/score/include/rtems/score/schedulersimple.h index 9e40c4a..00f8dd7 100644 --- a/cpukit/score/include/rtems/score/schedulersimple.h +++ b/cpukit/score/include/rtems/score/schedulersimple.h @@ -45,6 +45,8 @@ extern "C" { _Scheduler_simple_Block, /* block entry point */ \ _Scheduler_simple_Unblock, /* unblock entry point */ \ _Scheduler_simple_Change_priority, /* change priority entry point */ \ + _Scheduler_default_Map_priority, /* map priority entry point */ \ + _Scheduler_default_Unmap_priority, /* unmap priority entry point */ \ SCHEDULER_OPERATION_DEFAULT_ASK_FOR_HELP \ _Scheduler_default_Node_initialize, /* node initialize entry point */ \ _Scheduler_default_Node_destroy, /* node destroy entry point */ \ diff --git a/cpukit/score/include/rtems/score/schedulersimplesmp.h b/cpukit/score/include/rtems/score/schedulersimplesmp.h index b943353..31c837d 100644 --- a/cpukit/score/include/rtems/score/schedulersimplesmp.h +++ b/cpukit/score/include/rtems/score/schedulersimplesmp.h @@ -67,6 +67,8 @@ typedef struct { _Scheduler_simple_SMP_Block, \ _Scheduler_simple_SMP_Unblock, \ _Scheduler_simple_SMP_Change_priority, \ + _Scheduler_default_Map_priority, \ + _Scheduler_default_Unmap_priority, \ _Scheduler_simple_SMP_Ask_for_help, \ _Scheduler_simple_SMP_Node_initialize, \ _Scheduler_default_Node_destroy, \ diff --git a/cpukit/score/include/rtems/score/schedulerstrongapa.h b/cpukit/score/include/rtems/score/schedulerstrongapa.h index 4f95aac..d7c3888 100644 --- a/cpukit/score/include/rtems/score/schedulerstrongapa.h +++ b/cpukit/score/include/rtems/score/schedulerstrongapa.h @@ -84,6 +84,8 @@ typedef struct { _Scheduler_strong_APA_Block, \ _Scheduler_strong_APA_Unblock, \ _Scheduler_strong_APA_Change_priority, \ + _Scheduler_default_Map_priority, \ + _Scheduler_default_Unmap_priority, \ _Scheduler_strong_APA_Ask_for_help, \ _Scheduler_strong_APA_Node_initialize, \ _Scheduler_default_Node_destroy, \ diff --git a/cpukit/score/include/rtems/score/status.h b/cpukit/score/include/rtems/score/status.h index eaf69c1..d30f731 100644 --- a/cpukit/score/include/rtems/score/status.h +++ b/cpukit/score/include/rtems/score/status.h @@ -38,6 +38,7 @@ typedef enum { STATUS_CLASSIC_INVALID_PRIORITY = 19, STATUS_CLASSIC_INVALID_SIZE = 8, STATUS_CLASSIC_NO_MEMORY = 26, + STATUS_CLASSIC_NOT_DEFINED = 11, STATUS_CLASSIC_NOT_OWNER_OF_RESOURCE = 23, STATUS_CLASSIC_OBJECT_WAS_DELETED = 7, STATUS_CLASSIC_RESOURCE_IN_USE = 12, @@ -86,6 +87,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 = @@ -102,6 +105,8 @@ typedef enum { STATUS_BUILD( STATUS_CLASSIC_UNSATISFIED, EDEADLK ), STATUS_NO_MEMORY = STATUS_BUILD( STATUS_CLASSIC_NO_MEMORY, EINVAL ), + STATUS_NOT_DEFINED = + STATUS_BUILD( STATUS_CLASSIC_NOT_DEFINED, EINVAL ), STATUS_NOT_OWNER = STATUS_BUILD( STATUS_CLASSIC_NOT_OWNER_OF_RESOURCE, EPERM ), STATUS_OBJECT_WAS_DELETED = diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h index 164773a..4bd1330 100644 --- a/cpukit/score/include/rtems/score/threadimpl.h +++ b/cpukit/score/include/rtems/score/threadimpl.h @@ -535,6 +535,30 @@ RTEMS_INLINE_ROUTINE void _Thread_Inherit_priority( void _Thread_Restore_priority( Thread_Control *the_thread ); /** + * @brief Maps and sets the priority of a thread if the mapping was successful. + * + * It sets the real priority of the thread. In addition it changes the current + * priority of the thread if the new priority is higher than the current + * priority or the thread owns no resources. + * + * @param[in] the_thread The thread. + * @param[in] new_priority The new priority of the thread. + * @param[out] old_priority The old real priority of the thread. This pointer + * must not be @c NULL. + * + * @retval STATUS_SUCCESSFUL Successful operation. + * @retval STATUS_INVALID_PRIORITY An invalid thread priority was specified for + * which no mapping to a value suitable for the scheduler exists. + * + * @see _Thread_Change_priority(). + */ +Status_Control _Thread_Map_and_set_priority( + Thread_Control *the_thread, + Priority_Control new_priority, + Priority_Control *old_priority +); + +/** * @brief Sets the priority of a thread. * * It sets the real priority of the thread. In addition it changes the current diff --git a/cpukit/score/src/schedulerdefaultmappriority.c b/cpukit/score/src/schedulerdefaultmappriority.c new file mode 100644 index 0000000..dc68689 --- /dev/null +++ b/cpukit/score/src/schedulerdefaultmappriority.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2016 embedded brains GmbH + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/score/scheduler.h> + +bool _Scheduler_default_Map_priority( + const Scheduler_Control *scheduler, + Priority_Control *priority +) +{ + return *priority <= scheduler->maximum_priority; +} diff --git a/cpukit/score/src/schedulerdefaultunmappriority.c b/cpukit/score/src/schedulerdefaultunmappriority.c new file mode 100644 index 0000000..2f75298 --- /dev/null +++ b/cpukit/score/src/schedulerdefaultunmappriority.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016 embedded brains GmbH + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems/score/scheduler.h> + +Priority_Control _Scheduler_default_Unmap_priority( + const Scheduler_Control *scheduler, + Priority_Control priority +) +{ + (void) scheduler; + + return priority; +} diff --git a/cpukit/score/src/scheduleredfchangepriority.c b/cpukit/score/src/scheduleredfchangepriority.c index 61e0481..1444dff 100644 --- a/cpukit/score/src/scheduleredfchangepriority.c +++ b/cpukit/score/src/scheduleredfchangepriority.c @@ -20,6 +20,27 @@ #include <rtems/score/scheduleredfimpl.h> +bool _Scheduler_EDF_Map_priority( + const Scheduler_Control *scheduler, + Priority_Control *priority +) +{ + if ( *priority > scheduler->maximum_priority ) { + return false; + } + + *priority = SCHEDULER_EDF_PRIO_MSB | *priority; + return true; +} + +Priority_Control _Scheduler_EDF_Unmap_priority( + const Scheduler_Control *scheduler, + Priority_Control priority +) +{ + return priority & ~SCHEDULER_EDF_PRIO_MSB; +} + Scheduler_Void_or_thread _Scheduler_EDF_Change_priority( const Scheduler_Control *scheduler, Thread_Control *the_thread, diff --git a/cpukit/score/src/threadcreateidle.c b/cpukit/score/src/threadcreateidle.c index 0df53ec..d76a7fa 100644 --- a/cpukit/score/src/threadcreateidle.c +++ b/cpukit/score/src/threadcreateidle.c @@ -19,6 +19,7 @@ #endif #include <rtems/score/threadimpl.h> +#include <rtems/score/assert.h> #include <rtems/score/schedulerimpl.h> #include <rtems/score/stackimpl.h> #include <rtems/score/sysstate.h> @@ -30,6 +31,8 @@ static void _Thread_Create_idle_for_CPU( Per_CPU_Control *cpu ) Objects_Name name; Thread_Control *idle; const Scheduler_Control *scheduler; + Priority_Control idle_priority; + bool success; scheduler = _Scheduler_Get_by_CPU( cpu ); @@ -41,12 +44,18 @@ static void _Thread_Create_idle_for_CPU( Per_CPU_Control *cpu ) name.name_u32 = _Objects_Build_name( 'I', 'D', 'L', 'E' ); + idle_priority = scheduler->maximum_priority; + success = _Scheduler_Map_priority( scheduler, &idle_priority ); + _Assert( success ); + (void) success; + /* * The entire workspace is zeroed during its initialization. Thus, all * fields not explicitly assigned were explicitly zeroed by * _Workspace_Initialization. */ idle = _Thread_Internal_allocate(); + _Assert( idle != NULL ); _Thread_Initialize( &_Thread_Internal_information, @@ -55,7 +64,7 @@ static void _Thread_Create_idle_for_CPU( Per_CPU_Control *cpu ) NULL, /* allocate the stack */ _Stack_Ensure_minimum( rtems_configuration_get_idle_task_stack_size() ), CPU_IDLE_TASK_IS_FP, - scheduler->maximum_priority, + idle_priority, true, /* preemptable */ THREAD_CPU_BUDGET_ALGORITHM_NONE, NULL, /* no budget algorithm callout */ diff --git a/cpukit/score/src/threadsetpriority.c b/cpukit/score/src/threadsetpriority.c index f6a061a..36d3d63 100644 --- a/cpukit/score/src/threadsetpriority.c +++ b/cpukit/score/src/threadsetpriority.c @@ -19,6 +19,63 @@ #endif #include <rtems/score/threadimpl.h> +#include <rtems/score/schedulerimpl.h> + +typedef struct { + Priority_Control *old_priority; + Status_Control status; +} Thread_Map_and_set_context; + +static bool _Thread_Map_and_set_priority_filter( + Thread_Control *the_thread, + Priority_Control *new_priority_ptr, + void *arg +) +{ + Thread_Map_and_set_context *context; + const Scheduler_Control *scheduler; + Priority_Control current_priority; + Priority_Control new_priority; + + context = arg; + scheduler = _Scheduler_Get_own( the_thread ); + + if ( !_Scheduler_Map_priority( scheduler, new_priority_ptr ) ) { + context->status = STATUS_INVALID_PRIORITY; + return false; + } + + current_priority = the_thread->current_priority; + new_priority = *new_priority_ptr; + + context->status = STATUS_SUCCESSFUL; + *context->old_priority = + _Scheduler_Unmap_priority( scheduler, current_priority ); + the_thread->real_priority = new_priority; + + return _Thread_Priority_less_than( current_priority, new_priority ) + || !_Thread_Owns_resources( the_thread ); +} + +Status_Control _Thread_Map_and_set_priority( + Thread_Control *the_thread, + Priority_Control new_priority, + Priority_Control *old_priority +) +{ + Thread_Map_and_set_context context; + + context.old_priority = old_priority; + _Thread_Change_priority( + the_thread, + new_priority, + &context, + _Thread_Map_and_set_priority_filter, + false + ); + + return context.status; +} static bool _Thread_Set_priority_filter( Thread_Control *the_thread, diff --git a/testsuites/psxtests/psxautoinit01/init.c b/testsuites/psxtests/psxautoinit01/init.c index fb70a1e..f22cb1d 100644 --- a/testsuites/psxtests/psxautoinit01/init.c +++ b/testsuites/psxtests/psxautoinit01/init.c @@ -54,12 +54,16 @@ void *POSIX_Init( mutex1 = PTHREAD_MUTEX_INITIALIZER; mutex2 = PTHREAD_MUTEX_INITIALIZER; puts( "Init - pthread_mutex_getprioceiling - auto initialize - OK" ); + prioceiling = 1; sc = pthread_mutex_getprioceiling( &mutex1, &prioceiling ); fatal_posix_service_status( sc, 0, "mutex getprioceiling OK" ); + rtems_test_assert( prioceiling == 0 ); puts( "Init - pthread_mutex_getprioceiling - auto initialize - EINVAL" ); + prioceiling = 1; sc = pthread_mutex_getprioceiling( &mutex2, &prioceiling ); fatal_posix_service_status( sc, EINVAL, "mutex getprioceiling EINVAL" ); + rtems_test_assert( prioceiling == 1 ); puts( "Init - pthread_mutex_destroy - OK" ); sc = pthread_mutex_destroy( &mutex1 ); diff --git a/testsuites/smptests/Makefile.am b/testsuites/smptests/Makefile.am index 9cefd26..66c2780 100644 --- a/testsuites/smptests/Makefile.am +++ b/testsuites/smptests/Makefile.am @@ -45,6 +45,7 @@ SUBDIRS += smpwakeafter01 if HAS_POSIX SUBDIRS += smppsxaffinity01 SUBDIRS += smppsxaffinity02 +SUBDIRS += smppsxmutex01 SUBDIRS += smppsxsignal01 endif endif diff --git a/testsuites/smptests/configure.ac b/testsuites/smptests/configure.ac index 2ea9eec..2e70252 100644 --- a/testsuites/smptests/configure.ac +++ b/testsuites/smptests/configure.ac @@ -57,6 +57,7 @@ AM_CONDITIONAL(HAS_CPUSET,test x"${ac_cv_header_sys_cpuset_h}" = x"yes") # Explicitly list all Makefiles here AC_CONFIG_FILES([Makefile +smppsxmutex01/Makefile smpstrongapa01/Makefile smp01/Makefile smp02/Makefile diff --git a/testsuites/smptests/smppsxmutex01/Makefile.am b/testsuites/smptests/smppsxmutex01/Makefile.am new file mode 100644 index 0000000..0b09b16 --- /dev/null +++ b/testsuites/smptests/smppsxmutex01/Makefile.am @@ -0,0 +1,19 @@ +rtems_tests_PROGRAMS = smppsxmutex01 +smppsxmutex01_SOURCES = init.c + +dist_rtems_tests_DATA = smppsxmutex01.scn smppsxmutex01.doc + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + +AM_CPPFLAGS += -I$(top_srcdir)/../support/include + +LINK_OBJS = $(smppsxmutex01_OBJECTS) +LINK_LIBS = $(smppsxmutex01_LDLIBS) + +smppsxmutex01$(EXEEXT): $(smppsxmutex01_OBJECTS) $(smppsxmutex01_DEPENDENCIES) + @rm -f smppsxmutex01$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/smptests/smppsxmutex01/init.c b/testsuites/smptests/smppsxmutex01/init.c new file mode 100644 index 0000000..761b5b9 --- /dev/null +++ b/testsuites/smptests/smppsxmutex01/init.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rt...@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include <errno.h> +#include <pthread.h> + +#include <rtems.h> +#include <rtems/libcsupport.h> + +#include "tmacros.h" + +const char rtems_test_name[] = "SMPPSXMUTEX 1"; + +#define SCHED_A rtems_build_name(' ', ' ', ' ', 'A') + +#define SCHED_B rtems_build_name(' ', ' ', ' ', 'B') + +typedef struct { + pthread_t thread_b; + pthread_mutexattr_t mtx_attr; + pthread_mutex_t mtx_a; + pthread_mutex_t mtx_b; +} test_context; + +static test_context test_instance; + +static void *thread_b(void *arg) +{ + test_context *ctx; + rtems_id scheduler_b_id; + rtems_status_code sc; + int prio_ceiling; + int eno; + + ctx = arg; + + rtems_test_assert(rtems_get_current_processor() == 0); + + sc = rtems_scheduler_ident(SCHED_B, &scheduler_b_id); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_set_scheduler(pthread_self(), scheduler_b_id); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + rtems_test_assert(rtems_get_current_processor() == 1); + + eno = pthread_mutex_init(&ctx->mtx_b, &ctx->mtx_attr); + rtems_test_assert(eno == 0); + + eno = pthread_mutex_getprioceiling(&ctx->mtx_b, &prio_ceiling); + rtems_test_assert(eno == 0); + rtems_test_assert(prio_ceiling == 254); + + eno = pthread_mutex_lock(&ctx->mtx_b); + rtems_test_assert(eno == 0); + + eno = pthread_mutex_unlock(&ctx->mtx_b); + rtems_test_assert(eno == 0); + + eno = pthread_mutex_destroy(&ctx->mtx_b); + rtems_test_assert(eno == 0); + + eno = pthread_mutex_getprioceiling(&ctx->mtx_a, &prio_ceiling); + rtems_test_assert(eno == 0); + rtems_test_assert(prio_ceiling == 126); + + eno = pthread_mutex_lock(&ctx->mtx_a); + rtems_test_assert(eno == EINVAL); + + return ctx; +} + +static void test(test_context *ctx) +{ + uint32_t cpu_count; + int prio_ceiling; + int eno; + + cpu_count = rtems_get_processor_count(); + + rtems_test_assert(rtems_get_current_processor() == 0); + + eno = pthread_mutexattr_init(&ctx->mtx_attr); + rtems_test_assert(eno == 0); + + eno = pthread_mutexattr_setprotocol(&ctx->mtx_attr, PTHREAD_PRIO_PROTECT); + rtems_test_assert(eno == 0); + + eno = pthread_mutex_init(&ctx->mtx_a, &ctx->mtx_attr); + rtems_test_assert(eno == 0); + + eno = pthread_mutex_getprioceiling(&ctx->mtx_a, &prio_ceiling); + rtems_test_assert(eno == 0); + rtems_test_assert(prio_ceiling == 126); + + eno = pthread_mutex_lock(&ctx->mtx_a); + rtems_test_assert(eno == 0); + + eno = pthread_mutex_unlock(&ctx->mtx_a); + rtems_test_assert(eno == 0); + + if (cpu_count > 1) { + void *exit_code; + + eno = pthread_create(&ctx->thread_b, NULL, thread_b, ctx); + rtems_test_assert(eno == 0); + + exit_code = NULL; + eno = pthread_join(ctx->thread_b, &exit_code); + rtems_test_assert(eno == 0); + rtems_test_assert(exit_code == ctx); + } + + eno = pthread_mutex_destroy(&ctx->mtx_a); + rtems_test_assert(eno == 0); + + eno = pthread_mutexattr_destroy(&ctx->mtx_attr); + rtems_test_assert(eno == 0); +} + +static void *POSIX_Init(void *arg) +{ + rtems_resource_snapshot snapshot; + + TEST_BEGIN(); + + rtems_resource_snapshot_take(&snapshot); + + test(&test_instance); + + rtems_test_assert(rtems_resource_snapshot_check(&snapshot)); + + TEST_END(); + rtems_test_exit(0); +} + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_MAXIMUM_POSIX_THREADS 2 +#define CONFIGURE_MAXIMUM_POSIX_MUTEXES 2 + +#define CONFIGURE_SMP_APPLICATION + +#define CONFIGURE_SMP_MAXIMUM_PROCESSORS 2 + +#define CONFIGURE_SCHEDULER_PRIORITY_SMP + +#include <rtems/scheduler.h> + +RTEMS_SCHEDULER_CONTEXT_PRIORITY_SMP(a, 128); + +RTEMS_SCHEDULER_CONTEXT_PRIORITY_SMP(b, 256); + +#define CONFIGURE_SCHEDULER_CONTROLS \ + RTEMS_SCHEDULER_CONTROL_PRIORITY_SMP(a, SCHED_A), \ + RTEMS_SCHEDULER_CONTROL_PRIORITY_SMP(b, SCHED_B) \ + +#define CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS \ + RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \ + RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL) + +#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION + +#define CONFIGURE_POSIX_INIT_THREAD_TABLE + +#define CONFIGURE_INIT + +#include <rtems/confdefs.h> diff --git a/testsuites/smptests/smppsxmutex01/smppsxmutex01.doc b/testsuites/smptests/smppsxmutex01/smppsxmutex01.doc new file mode 100644 index 0000000..dd255da --- /dev/null +++ b/testsuites/smptests/smppsxmutex01/smppsxmutex01.doc @@ -0,0 +1,12 @@ +This file describes the directives and concepts tested by this test set. + +test set name: smppsxmutex01 + +directives: + + - pthread_mutex_lock() + +concepts: + + - Ensure that priority ceiling mutexes work only in their dedicated scheduler + instance. diff --git a/testsuites/smptests/smppsxmutex01/smppsxmutex01.scn b/testsuites/smptests/smppsxmutex01/smppsxmutex01.scn new file mode 100644 index 0000000..e4c8a1a --- /dev/null +++ b/testsuites/smptests/smppsxmutex01/smppsxmutex01.scn @@ -0,0 +1,2 @@ +*** BEGIN OF TEST SMPPSXMUTEX 1 *** +*** END OF TEST SMPPSXMUTEX 1 *** diff --git a/testsuites/smptests/smpscheduler02/init.c b/testsuites/smptests/smpscheduler02/init.c index 479e468..52b3f61 100644 --- a/testsuites/smptests/smpscheduler02/init.c +++ b/testsuites/smptests/smpscheduler02/init.c @@ -35,6 +35,8 @@ const char rtems_test_name[] = "SMPSCHEDULER 2"; static rtems_id main_task_id; +static rtems_id sema_id; + static void task(rtems_task_argument arg) { rtems_status_code sc; @@ -45,6 +47,9 @@ static void task(rtems_task_argument arg) rtems_test_assert(sched_get_priority_min(SCHED_RR) == 1); rtems_test_assert(sched_get_priority_max(SCHED_RR) == 126); + sc = rtems_semaphore_obtain(sema_id, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + rtems_test_assert(sc == RTEMS_NOT_DEFINED); + sc = rtems_event_transient_send(main_task_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); @@ -61,6 +66,7 @@ static void test(void) rtems_id scheduler_a_id; rtems_id scheduler_b_id; rtems_id scheduler_c_id; + rtems_task_priority prio; cpu_set_t cpuset; cpu_set_t first_cpu; cpu_set_t second_cpu; @@ -95,6 +101,27 @@ static void test(void) sc = rtems_scheduler_ident(SCHED_C, &scheduler_c_id); rtems_test_assert(sc == RTEMS_UNSATISFIED); + sc = rtems_semaphore_create( + SCHED_A, + 1, + RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_PRIORITY_CEILING, + 1, + &sema_id + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + prio = 2; + sc = rtems_semaphore_set_priority(sema_id, scheduler_a_id, prio, &prio); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + rtems_test_assert(prio == 1); + + if (cpu_count > 1) { + prio = 1; + sc = rtems_semaphore_set_priority(sema_id, scheduler_b_id, prio, &prio); + rtems_test_assert(sc == RTEMS_NOT_DEFINED); + rtems_test_assert(prio == 2); + } + CPU_ZERO(&cpuset); sc = rtems_scheduler_get_processor_set( scheduler_a_id, @@ -182,6 +209,9 @@ static void test(void) sc = rtems_task_delete(task_id); rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_semaphore_delete(sema_id); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); } #else /* defined(__RTEMS_HAVE_SYS_CPUSET_H__) */ @@ -212,6 +242,9 @@ static void Init(rtems_task_argument arg) #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_MAXIMUM_TASKS 2 +#define CONFIGURE_MAXIMUM_SEMAPHORES 1 + #define CONFIGURE_SMP_APPLICATION /* Lets see when the first RTEMS system hits this limit */ @@ -269,8 +302,6 @@ RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(c); RTEMS_SCHEDULER_ASSIGN_NO_SCHEDULER, \ RTEMS_SCHEDULER_ASSIGN(2, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL) -#define CONFIGURE_MAXIMUM_TASKS 2 - #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION #define CONFIGURE_RTEMS_INIT_TASKS_TABLE diff --git a/testsuites/sptests/sp51/init.c b/testsuites/sptests/sp51/init.c index 48f0146..1e8f9e5 100644 --- a/testsuites/sptests/sp51/init.c +++ b/testsuites/sptests/sp51/init.c @@ -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' ), diff --git a/testsuites/sptests/sp51/sp51.scn b/testsuites/sptests/sp51/sp51.scn index 9fe4622..4ade359 100644 --- a/testsuites/sptests/sp51/sp51.scn +++ b/testsuites/sptests/sp51/sp51.scn @@ -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 *** diff --git a/testsuites/sptests/spmrsp01/init.c b/testsuites/sptests/spmrsp01/init.c index d5acb0a..e5e522f 100644 --- a/testsuites/sptests/spmrsp01/init.c +++ b/testsuites/sptests/spmrsp01/init.c @@ -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 -- 1.8.4.5 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel