diff options
Diffstat (limited to 'cpukit/rtems')
-rw-r--r-- | cpukit/rtems/Makefile.am | 1 | ||||
-rw-r--r-- | cpukit/rtems/include/rtems/rtems/attr.h | 14 | ||||
-rw-r--r-- | cpukit/rtems/include/rtems/rtems/attrimpl.h | 31 | ||||
-rw-r--r-- | cpukit/rtems/include/rtems/rtems/sem.h | 46 | ||||
-rw-r--r-- | cpukit/rtems/include/rtems/rtems/semimpl.h | 9 | ||||
-rw-r--r-- | cpukit/rtems/src/semcreate.c | 38 | ||||
-rw-r--r-- | cpukit/rtems/src/semdelete.c | 21 | ||||
-rw-r--r-- | cpukit/rtems/src/semflush.c | 10 | ||||
-rw-r--r-- | cpukit/rtems/src/semobtain.c | 19 | ||||
-rw-r--r-- | cpukit/rtems/src/semrelease.c | 14 | ||||
-rw-r--r-- | cpukit/rtems/src/semsetpriority.c | 116 |
11 files changed, 309 insertions, 10 deletions
diff --git a/cpukit/rtems/Makefile.am b/cpukit/rtems/Makefile.am index 4b84fa1343..eb9b16ee04 100644 --- a/cpukit/rtems/Makefile.am +++ b/cpukit/rtems/Makefile.am @@ -206,6 +206,7 @@ librtems_a_SOURCES += src/semrelease.c librtems_a_SOURCES += src/semflush.c librtems_a_SOURCES += src/semtranslatereturncode.c librtems_a_SOURCES += src/semdata.c +librtems_a_SOURCES += src/semsetpriority.c ## EVENT_C_FILES librtems_a_SOURCES += src/event.c diff --git a/cpukit/rtems/include/rtems/rtems/attr.h b/cpukit/rtems/include/rtems/rtems/attr.h index d326539714..7e8fa4818a 100644 --- a/cpukit/rtems/include/rtems/rtems/attr.h +++ b/cpukit/rtems/include/rtems/rtems/attr.h @@ -139,6 +139,20 @@ typedef uint32_t rtems_attribute; */ #define RTEMS_PRIORITY_CEILING 0x00000080 +/** + * This attribute constant indicates that the Classic API Semaphore instance + * created will NOT use the Multiprocessor Resource Sharing Protocol. + */ +#define RTEMS_NO_MULTIPROCESSOR_RESOURCE_SHARING 0x00000000 + +/** + * This attribute constant indicates that the Classic API Semaphore instance + * created will use the Multiprocessor Resource Sharing Protocol. + * + * @note The semaphore instance must be a binary semaphore. + */ +#define RTEMS_MULTIPROCESSOR_RESOURCE_SHARING 0x00000100 + /******************** RTEMS Barrier Specific Attributes ********************/ /** diff --git a/cpukit/rtems/include/rtems/rtems/attrimpl.h b/cpukit/rtems/include/rtems/rtems/attrimpl.h index 0f78c44672..a32c37096d 100644 --- a/cpukit/rtems/include/rtems/rtems/attrimpl.h +++ b/cpukit/rtems/include/rtems/rtems/attrimpl.h @@ -185,6 +185,23 @@ RTEMS_INLINE_ROUTINE bool _Attributes_Is_inherit_priority( } /** + * @brief Returns true if the attribute set has at most one protocol, and false + * otherwise. + * + * The protocols are RTEMS_INHERIT_PRIORITY, RTEMS_PRIORITY_CEILING and + * RTEMS_MULTIPROCESSOR_RESOURCE_SHARING. + */ +RTEMS_INLINE_ROUTINE bool _Attributes_Has_at_most_one_protocol( + rtems_attribute attribute_set +) +{ + attribute_set &= RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY_CEILING + | RTEMS_MULTIPROCESSOR_RESOURCE_SHARING; + + return ( attribute_set & ( attribute_set - 1 ) ) == 0; +} + +/** * @brief Checks if the priority ceiling attribute * is enabled in the attribute_set * @@ -199,6 +216,20 @@ RTEMS_INLINE_ROUTINE bool _Attributes_Is_priority_ceiling( } /** + * @brief Checks if the Multiprocessor Resource Sharing Protocol attribute + * is enabled in the attribute_set + * + * This function returns TRUE if the Multiprocessor Resource Sharing Protocol + * attribute is enabled in the attribute_set and FALSE otherwise. + */ +RTEMS_INLINE_ROUTINE bool _Attributes_Is_multiprocessor_resource_sharing( + rtems_attribute attribute_set +) +{ + return ( attribute_set & RTEMS_MULTIPROCESSOR_RESOURCE_SHARING ) != 0; +} + +/** * @brief Checks if the barrier automatic release * attribute is enabled in the attribute_set * diff --git a/cpukit/rtems/include/rtems/rtems/sem.h b/cpukit/rtems/include/rtems/rtems/sem.h index 782314d163..2442010113 100644 --- a/cpukit/rtems/include/rtems/rtems/sem.h +++ b/cpukit/rtems/include/rtems/rtems/sem.h @@ -38,6 +38,7 @@ #include <rtems/score/coremutex.h> #include <rtems/score/object.h> #include <rtems/score/coresem.h> +#include <rtems/score/mrsp.h> #ifdef __cplusplus extern "C" { @@ -88,6 +89,10 @@ typedef struct { * API Semaphore instance. */ CORE_semaphore_Control semaphore; + +#if defined(RTEMS_SMP) + MRSP_Control mrsp; +#endif } Core_control; } Semaphore_Control; @@ -208,6 +213,47 @@ rtems_status_code rtems_semaphore_flush( rtems_id id ); +/** + * @brief Sets the priority value with respect to the specified scheduler of a + * semaphore. + * + * The special priority value @ref RTEMS_CURRENT_PRIORITY can be used to get + * the current priority value without changing it. + * + * The interpretation of the priority value depends on the protocol of the + * semaphore object. + * + * - The Multiprocessor Resource Sharing Protocol needs a ceiling priority per + * scheduler instance. This operation can be used to specify these priority + * values. + * - For the Priority Ceiling Protocol the ceiling priority is used with this + * operation. + * - For other protocols this operation is not defined. + * + * @param[in] semaphore_id Identifier of the semaphore. + * @param[in] scheduler_id Identifier of the scheduler. + * @param[in] new_priority The new priority value. Use + * @ref RTEMS_CURRENT_PRIORITY to not set a new priority and only get the + * current priority. + * @param[out] old_priority Reference to store the old priority value. + * + * @retval RTEMS_SUCCESSFUL Successful operation. + * @retval RTEMS_INVALID_ID Invalid semaphore or scheduler identifier. + * @retval RTEMS_INVALID_ADDRESS The old priority reference is @c NULL. + * @retval RTEMS_INVALID_PRIORITY The new priority value is invalid. + * @retval RTEMS_NOT_DEFINED The set priority operation is not defined for the + * protocol of this semaphore object. + * @retval RTEMS_ILLEGAL_ON_REMOTE_OBJECT Not supported for remote semaphores. + * + * @see rtems_scheduler_ident() and rtems_task_set_priority(). + */ +rtems_status_code rtems_semaphore_set_priority( + rtems_id semaphore_id, + rtems_id scheduler_id, + rtems_task_priority new_priority, + rtems_task_priority *old_priority +); + /**@}*/ #ifdef __cplusplus diff --git a/cpukit/rtems/include/rtems/rtems/semimpl.h b/cpukit/rtems/include/rtems/rtems/semimpl.h index 51da4cdbcf..e0a35a2e33 100644 --- a/cpukit/rtems/include/rtems/rtems/semimpl.h +++ b/cpukit/rtems/include/rtems/rtems/semimpl.h @@ -20,6 +20,7 @@ #include <rtems/rtems/sem.h> #include <rtems/score/coremuteximpl.h> #include <rtems/score/coresemimpl.h> +#include <rtems/score/mrspimpl.h> #ifdef __cplusplus extern "C" { @@ -92,6 +93,14 @@ _Semaphore_Translate_core_mutex_return_code( return _Semaphore_Translate_core_mutex_return_code_[status]; } +#if defined(RTEMS_SMP) +RTEMS_INLINE_ROUTINE rtems_status_code +_Semaphore_Translate_MRSP_status_code( MRSP_Status mrsp_status ) +{ + return (rtems_status_code) mrsp_status; +} +#endif + /** * @brief Semaphore Translate Core Semaphore Return Code * diff --git a/cpukit/rtems/src/semcreate.c b/cpukit/rtems/src/semcreate.c index fb597d1cbd..5e93e02632 100644 --- a/cpukit/rtems/src/semcreate.c +++ b/cpukit/rtems/src/semcreate.c @@ -78,12 +78,19 @@ rtems_status_code rtems_semaphore_create( return RTEMS_MP_NOT_CONFIGURED; if ( _Attributes_Is_inherit_priority( attribute_set ) || - _Attributes_Is_priority_ceiling( attribute_set ) ) + _Attributes_Is_priority_ceiling( attribute_set ) || + _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) ) return RTEMS_NOT_DEFINED; } else #endif + if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) && + !( _Attributes_Is_binary_semaphore( attribute_set ) && + !_Attributes_Is_priority( attribute_set ) ) ) { + return RTEMS_NOT_DEFINED; + } + if ( _Attributes_Is_inherit_priority( attribute_set ) || _Attributes_Is_priority_ceiling( attribute_set ) ) { @@ -93,13 +100,22 @@ rtems_status_code rtems_semaphore_create( } - if ( _Attributes_Is_inherit_priority( attribute_set ) && - _Attributes_Is_priority_ceiling( attribute_set ) ) + if ( !_Attributes_Has_at_most_one_protocol( attribute_set ) ) return RTEMS_NOT_DEFINED; if ( !_Attributes_Is_counting_semaphore( attribute_set ) && ( count > 1 ) ) return RTEMS_INVALID_NUMBER; +#if !defined(RTEMS_SMP) + /* + * On uni-processor configurations the Multiprocessor Resource Sharing + * Protocol is equivalent to the Priority Ceiling Protocol. + */ + if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) ) { + attribute_set |= RTEMS_PRIORITY_CEILING | RTEMS_PRIORITY; + } +#endif + the_semaphore = _Semaphore_Allocate(); if ( !the_semaphore ) { @@ -144,6 +160,22 @@ rtems_status_code rtems_semaphore_create( &the_semaphore_attr, count ); +#if defined(RTEMS_SMP) + } else if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) ) { + MRSP_Status mrsp_status = _MRSP_Initialize( + &the_semaphore->Core_control.mrsp, + priority_ceiling, + _Thread_Get_executing(), + count != 1 + ); + + if ( mrsp_status != MRSP_SUCCESSFUL ) { + _Semaphore_Free( the_semaphore ); + _Objects_Allocator_unlock(); + + return _Semaphore_Translate_MRSP_status_code( mrsp_status ); + } +#endif } else { /* * It is either simple binary semaphore or a more powerful mutex diff --git a/cpukit/rtems/src/semdelete.c b/cpukit/rtems/src/semdelete.c index 6e7c5eafad..52bb14e33c 100644 --- a/cpukit/rtems/src/semdelete.c +++ b/cpukit/rtems/src/semdelete.c @@ -43,6 +43,7 @@ rtems_status_code rtems_semaphore_delete( { Semaphore_Control *the_semaphore; Objects_Locations location; + rtems_attribute attribute_set; _Objects_Allocator_lock(); @@ -50,10 +51,22 @@ rtems_status_code rtems_semaphore_delete( switch ( location ) { case OBJECTS_LOCAL: - if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) { + attribute_set = the_semaphore->attribute_set; +#if defined(RTEMS_SMP) + if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) ) { + MRSP_Status mrsp_status = _MRSP_Destroy( + &the_semaphore->Core_control.mrsp + ); + if ( mrsp_status != MRSP_SUCCESSFUL ) { + _Objects_Put( &the_semaphore->Object ); + _Objects_Allocator_unlock(); + return _Semaphore_Translate_MRSP_status_code( mrsp_status ); + } + } else +#endif + if ( !_Attributes_Is_counting_semaphore( attribute_set ) ) { if ( _CORE_mutex_Is_locked( &the_semaphore->Core_control.mutex ) && - !_Attributes_Is_simple_binary_semaphore( - the_semaphore->attribute_set ) ) { + !_Attributes_Is_simple_binary_semaphore( attribute_set ) ) { _Objects_Put( &the_semaphore->Object ); _Objects_Allocator_unlock(); return RTEMS_RESOURCE_IN_USE; @@ -74,7 +87,7 @@ rtems_status_code rtems_semaphore_delete( _Objects_Close( &_Semaphore_Information, &the_semaphore->Object ); #if defined(RTEMS_MULTIPROCESSING) - if ( _Attributes_Is_global( the_semaphore->attribute_set ) ) { + if ( _Attributes_Is_global( attribute_set ) ) { _Objects_MP_Close( &_Semaphore_Information, the_semaphore->Object.id ); diff --git a/cpukit/rtems/src/semflush.c b/cpukit/rtems/src/semflush.c index f73c92949d..b9b1ec6992 100644 --- a/cpukit/rtems/src/semflush.c +++ b/cpukit/rtems/src/semflush.c @@ -43,12 +43,20 @@ rtems_status_code rtems_semaphore_flush( { Semaphore_Control *the_semaphore; Objects_Locations location; + rtems_attribute attribute_set; the_semaphore = _Semaphore_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: - if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) { + attribute_set = the_semaphore->attribute_set; +#if defined(RTEMS_SMP) + if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) ) { + _Objects_Put( &the_semaphore->Object ); + return RTEMS_NOT_DEFINED; + } else +#endif + if ( !_Attributes_Is_counting_semaphore( attribute_set ) ) { _CORE_mutex_Flush( &the_semaphore->Core_control.mutex, SEND_OBJECT_WAS_DELETED, diff --git a/cpukit/rtems/src/semobtain.c b/cpukit/rtems/src/semobtain.c index c9433ca6d9..3608a00053 100644 --- a/cpukit/rtems/src/semobtain.c +++ b/cpukit/rtems/src/semobtain.c @@ -41,6 +41,7 @@ rtems_status_code rtems_semaphore_obtain( Objects_Locations location; ISR_Level level; Thread_Control *executing; + rtems_attribute attribute_set; bool wait; the_semaphore = _Semaphore_Get_interrupt_disable( id, &location, &level ); @@ -48,8 +49,24 @@ rtems_status_code rtems_semaphore_obtain( case OBJECTS_LOCAL: executing = _Thread_Executing; + attribute_set = the_semaphore->attribute_set; wait = !_Options_Is_no_wait( option_set ); - if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) { +#if defined(RTEMS_SMP) + if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) ) { + MRSP_Status mrsp_status; + + _ISR_Enable( level ); + mrsp_status = _MRSP_Obtain( + &the_semaphore->Core_control.mrsp, + executing, + wait, + timeout + ); + _Objects_Put_for_get_isr_disable( &the_semaphore->Object ); + return _Semaphore_Translate_MRSP_status_code( mrsp_status ); + } else +#endif + if ( !_Attributes_Is_counting_semaphore( attribute_set ) ) { _CORE_mutex_Seize( &the_semaphore->Core_control.mutex, executing, diff --git a/cpukit/rtems/src/semrelease.c b/cpukit/rtems/src/semrelease.c index ff4e792b92..2c4be04c78 100644 --- a/cpukit/rtems/src/semrelease.c +++ b/cpukit/rtems/src/semrelease.c @@ -73,12 +73,24 @@ rtems_status_code rtems_semaphore_release( Objects_Locations location; CORE_mutex_Status mutex_status; CORE_semaphore_Status semaphore_status; + rtems_attribute attribute_set; the_semaphore = _Semaphore_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: - if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) { + attribute_set = the_semaphore->attribute_set; +#if defined(RTEMS_SMP) + if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) ) { + MRSP_Status mrsp_status = _MRSP_Release( + &the_semaphore->Core_control.mrsp, + _Thread_Get_executing() + ); + _Objects_Put( &the_semaphore->Object ); + return _Semaphore_Translate_MRSP_status_code( mrsp_status ); + } else +#endif + if ( !_Attributes_Is_counting_semaphore( attribute_set ) ) { mutex_status = _CORE_mutex_Surrender( &the_semaphore->Core_control.mutex, id, diff --git a/cpukit/rtems/src/semsetpriority.c b/cpukit/rtems/src/semsetpriority.c new file mode 100644 index 0000000000..b5dd1db101 --- /dev/null +++ b/cpukit/rtems/src/semsetpriority.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/rtems/semimpl.h> +#include <rtems/rtems/attrimpl.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 +) +{ + rtems_status_code sc; + rtems_attribute attribute_set = the_semaphore->attribute_set; + rtems_task_priority old_priority; + + new_priority = _RTEMS_tasks_Priority_to_Core( new_priority ); + +#if defined(RTEMS_SMP) + if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) ) { + MRSP_Control *mrsp = &the_semaphore->Core_control.mrsp; + uint32_t scheduler_index = _Scheduler_Get_index_by_id( scheduler_id ); + + old_priority = _MRSP_Get_ceiling_priority( mrsp, scheduler_index ); + + if ( new_priority != RTEMS_CURRENT_PRIORITY ) { + _MRSP_Set_ceiling_priority( mrsp, scheduler_index, new_priority ); + } + + sc = RTEMS_SUCCESSFUL; + } else +#endif + if ( _Attributes_Is_priority_ceiling( attribute_set ) ) { + CORE_mutex_Control *mutex = &the_semaphore->Core_control.mutex; + + old_priority = mutex->Attributes.priority_ceiling; + + if ( new_priority != RTEMS_CURRENT_PRIORITY ) { + mutex->Attributes.priority_ceiling = new_priority; + } + + sc = RTEMS_SUCCESSFUL; + } else { + old_priority = 0; + + sc = RTEMS_NOT_DEFINED; + } + + *old_priority_p = _RTEMS_tasks_Priority_from_Core( old_priority ); + + _Objects_Put( &the_semaphore->Object ); + + return sc; +} + +rtems_status_code rtems_semaphore_set_priority( + rtems_id semaphore_id, + rtems_id scheduler_id, + rtems_task_priority new_priority, + rtems_task_priority *old_priority +) +{ + Semaphore_Control *the_semaphore; + Objects_Locations location; + + if ( new_priority != RTEMS_CURRENT_PRIORITY && + !_RTEMS_tasks_Priority_is_valid( new_priority ) ) { + return RTEMS_INVALID_PRIORITY; + } + + if ( old_priority == NULL ) { + return RTEMS_INVALID_ADDRESS; + } + + if ( !_Scheduler_Is_id_valid( scheduler_id ) ) { + return RTEMS_INVALID_ID; + } + + the_semaphore = _Semaphore_Get( semaphore_id, &location ); + switch ( location ) { + case OBJECTS_LOCAL: + return _Semaphore_Set_priority( + the_semaphore, + scheduler_id, + new_priority, + old_priority + ); +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: + _Thread_Dispatch(); + return RTEMS_ILLEGAL_ON_REMOTE_OBJECT; +#endif + case OBJECTS_ERROR: + break; + } + + return RTEMS_INVALID_ID; +} |