summaryrefslogtreecommitdiffstats
path: root/cpukit/rtems
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2014-05-21 10:33:43 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2014-05-28 10:50:41 +0200
commit8fcafdd553f3a564ecb5ab5093d01b29971418da (patch)
tree7807b3a4ae28e62f0218f8e20051b1b7e0143206 /cpukit/rtems
parentbsps/sparc: Change tabs to spaces. (diff)
downloadrtems-8fcafdd553f3a564ecb5ab5093d01b29971418da.tar.bz2
score: Multiprocessor Resource Sharing Protocol
Add basic support for the Multiprocessor Resource Sharing Protocol (MrsP). The Multiprocessor Resource Sharing Protocol (MrsP) is defined in A. Burns and A.J. Wellings, A Schedulability Compatible Multiprocessor Resource Sharing Protocol - MrsP, Proceedings of the 25th Euromicro Conference on Real-Time Systems (ECRTS 2013), July 2013. It is a generalization of the Priority Ceiling Protocol to SMP systems. Each MrsP semaphore uses a ceiling priority per scheduler instance. These ceiling priorities can be specified with rtems_semaphore_set_priority(). A task obtaining or owning a MrsP semaphore will execute with the ceiling priority for its scheduler instance as specified by the MrsP semaphore object. Tasks waiting to get ownership of a MrsP semaphore will not relinquish the processor voluntarily. In case the owner of a MrsP semaphore gets preempted it can ask all tasks waiting for this semaphore to help out and temporarily borrow the right to execute on one of their assigned processors. The help out feature is not implemented with this patch.
Diffstat (limited to 'cpukit/rtems')
-rw-r--r--cpukit/rtems/Makefile.am1
-rw-r--r--cpukit/rtems/include/rtems/rtems/attr.h14
-rw-r--r--cpukit/rtems/include/rtems/rtems/attrimpl.h31
-rw-r--r--cpukit/rtems/include/rtems/rtems/sem.h46
-rw-r--r--cpukit/rtems/include/rtems/rtems/semimpl.h9
-rw-r--r--cpukit/rtems/src/semcreate.c38
-rw-r--r--cpukit/rtems/src/semdelete.c21
-rw-r--r--cpukit/rtems/src/semflush.c10
-rw-r--r--cpukit/rtems/src/semobtain.c19
-rw-r--r--cpukit/rtems/src/semrelease.c14
-rw-r--r--cpukit/rtems/src/semsetpriority.c116
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;
+}