summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit')
-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
-rw-r--r--cpukit/sapi/include/confdefs.h14
-rw-r--r--cpukit/score/Makefile.am2
-rw-r--r--cpukit/score/include/rtems/score/mrsp.h133
-rw-r--r--cpukit/score/include/rtems/score/mrspimpl.h283
-rw-r--r--cpukit/score/include/rtems/score/schedulerimpl.h10
-rw-r--r--cpukit/score/preinstall.am8
17 files changed, 758 insertions, 11 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;
+}
diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
index 1c97d153ba..6978277790 100644
--- a/cpukit/sapi/include/confdefs.h
+++ b/cpukit/sapi/include/confdefs.h
@@ -1792,6 +1792,17 @@ const rtems_libio_helper rtems_fs_init_helper =
CONFIGURE_SEMAPHORES_FOR_FILE_SYSTEMS + \
CONFIGURE_NETWORKING_SEMAPHORES)
+ #if !defined(RTEMS_SMP) || \
+ !defined(CONFIGURE_MAXIMUM_MRSP_SEMAPHORES)
+ #define CONFIGURE_MEMORY_FOR_MRSP_SEMAPHORES 0
+ #else
+ #define CONFIGURE_MEMORY_FOR_MRSP_SEMAPHORES \
+ CONFIGURE_MAXIMUM_MRSP_SEMAPHORES * \
+ _Configure_From_workspace( \
+ RTEMS_ARRAY_SIZE(_Scheduler_Table) * sizeof(Priority_Control) \
+ )
+ #endif
+
/*
* If there are no user or support semaphores defined, then we can assume
* that no memory need be allocated at all for semaphores.
@@ -1800,7 +1811,8 @@ const rtems_libio_helper rtems_fs_init_helper =
#define CONFIGURE_MEMORY_FOR_SEMAPHORES(_semaphores) 0
#else
#define CONFIGURE_MEMORY_FOR_SEMAPHORES(_semaphores) \
- _Configure_Object_RAM(_semaphores, sizeof(Semaphore_Control) )
+ _Configure_Object_RAM(_semaphores, sizeof(Semaphore_Control) ) + \
+ CONFIGURE_MEMORY_FOR_MRSP_SEMAPHORES
#endif
#ifndef CONFIGURE_MAXIMUM_MESSAGE_QUEUES
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index 7c426025ea..b9a9f28514 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -39,6 +39,8 @@ include_rtems_score_HEADERS += include/rtems/score/isr.h
include_rtems_score_HEADERS += include/rtems/score/isrlevel.h
include_rtems_score_HEADERS += include/rtems/score/isrlock.h
include_rtems_score_HEADERS += include/rtems/score/freechain.h
+include_rtems_score_HEADERS += include/rtems/score/mrsp.h
+include_rtems_score_HEADERS += include/rtems/score/mrspimpl.h
include_rtems_score_HEADERS += include/rtems/score/object.h
include_rtems_score_HEADERS += include/rtems/score/objectimpl.h
include_rtems_score_HEADERS += include/rtems/score/onceimpl.h
diff --git a/cpukit/score/include/rtems/score/mrsp.h b/cpukit/score/include/rtems/score/mrsp.h
new file mode 100644
index 0000000000..407d5efecd
--- /dev/null
+++ b/cpukit/score/include/rtems/score/mrsp.h
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+#ifndef _RTEMS_SCORE_MRSP_H
+#define _RTEMS_SCORE_MRSP_H
+
+#include <rtems/score/cpuopts.h>
+
+#if defined(RTEMS_SMP)
+
+#include <rtems/score/atomic.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/thread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup ScoreMRSP Multiprocessor Resource Sharing Protocol Handler
+ *
+ * @ingroup Score
+ *
+ * @brief 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. 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.
+ *
+ * @{
+ */
+
+/**
+ * @brief MrsP status code.
+ *
+ * The values are chosen to directly map to RTEMS status codes. In case this
+ * implementation is used for other APIs, then for example the errno values can
+ * be added with a bit shift.
+ */
+typedef enum {
+ MRSP_SUCCESSFUL = 0,
+ MRSP_TIMEOUT = 6,
+ MRSP_INVALID_NUMBER = 10,
+ MRSP_RESOUCE_IN_USE = 12,
+ MRSP_UNSATISFIED = 13,
+ MRSP_INVALID_PRIORITY = 19,
+ MRSP_NOT_OWNER_OF_RESOURCE = 23,
+ MRSP_NO_MEMORY = 26
+} MRSP_Status;
+
+/**
+ * @brief MrsP rival.
+ *
+ * The rivals are used by threads waiting for resource ownership. They are
+ * registered in the MRSP control block.
+ */
+typedef struct {
+ /**
+ * @brief The node for registration in the MRSP rival chain.
+ *
+ * @see MRSP_Control::Rivals.
+ */
+ Chain_Node Node;
+
+ /**
+ * @brief Identification of the rival thread.
+ */
+ Thread_Control *thread;
+
+ /**
+ * @brief The rival state.
+ *
+ * Initially no state bits are set (MRSP_RIVAL_STATE_WAITING). The rival
+ * will busy wait until a state change happens. This can be
+ * MRSP_RIVAL_STATE_NEW_OWNER or MRSP_RIVAL_STATE_TIMEOUT.
+ */
+ Atomic_Uint state;
+} MRSP_Rival;
+
+/**
+ * @brief MrsP control block.
+ */
+typedef struct {
+ /**
+ * @brief The owner of the MRSP resource.
+ *
+ * In case this field is @c NULL, then this MRSP resource has currently no
+ * owner.
+ */
+ Thread_Control *owner;
+
+ /**
+ * @brief A chain of MrsP rivals waiting for resource ownership.
+ *
+ * @see MRSP_Rival::Node.
+ */
+ Chain_Control Rivals;
+
+ /**
+ * @brief One ceiling priority per scheduler instance.
+ */
+ Priority_Control *ceiling_priorities;
+} MRSP_Control;
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* RTEMS_SMP */
+
+#endif /* _RTEMS_SCORE_MRSP_H */
diff --git a/cpukit/score/include/rtems/score/mrspimpl.h b/cpukit/score/include/rtems/score/mrspimpl.h
new file mode 100644
index 0000000000..76d3bc898d
--- /dev/null
+++ b/cpukit/score/include/rtems/score/mrspimpl.h
@@ -0,0 +1,283 @@
+/*
+ * 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.
+ */
+
+#ifndef _RTEMS_SCORE_MRSPIMPL_H
+#define _RTEMS_SCORE_MRSPIMPL_H
+
+#include <rtems/score/mrsp.h>
+
+#if defined(RTEMS_SMP)
+
+#include <rtems/score/assert.h>
+#include <rtems/score/chainimpl.h>
+#include <rtems/score/schedulerimpl.h>
+#include <rtems/score/watchdogimpl.h>
+#include <rtems/score/wkspace.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @addtogroup ScoreMRSP
+ *
+ * @{
+ */
+
+#define MRSP_RIVAL_STATE_WAITING 0x0U
+
+#define MRSP_RIVAL_STATE_NEW_OWNER 0x1U
+
+#define MRSP_RIVAL_STATE_TIMEOUT 0x2U
+
+RTEMS_INLINE_ROUTINE void _MRSP_Claim_ownership(
+ MRSP_Control *mrsp,
+ Thread_Control *new_owner,
+ Priority_Control ceiling_priority
+)
+{
+ ++new_owner->resource_count;
+ mrsp->owner = new_owner;
+ _Thread_Change_priority( new_owner, ceiling_priority, false );
+}
+
+RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Initialize(
+ MRSP_Control *mrsp,
+ Priority_Control ceiling_priority,
+ Thread_Control *executing,
+ bool initially_locked
+)
+{
+ uint32_t scheduler_count = _Scheduler_Count;
+ uint32_t i;
+
+ if ( initially_locked ) {
+ return MRSP_INVALID_NUMBER;
+ }
+
+ mrsp->ceiling_priorities = _Workspace_Allocate(
+ sizeof( *mrsp->ceiling_priorities ) * scheduler_count
+ );
+ if ( mrsp->ceiling_priorities == NULL ) {
+ return MRSP_NO_MEMORY;
+ }
+
+ for ( i = 0 ; i < scheduler_count ; ++i ) {
+ mrsp->ceiling_priorities[ i ] = ceiling_priority;
+ }
+
+ mrsp->owner = NULL;
+ _Chain_Initialize_empty( &mrsp->Rivals );
+
+ return MRSP_SUCCESSFUL;
+}
+
+RTEMS_INLINE_ROUTINE Priority_Control _MRSP_Get_ceiling_priority(
+ MRSP_Control *mrsp,
+ uint32_t scheduler_index
+)
+{
+ return mrsp->ceiling_priorities[ scheduler_index ];
+}
+
+RTEMS_INLINE_ROUTINE void _MRSP_Set_ceiling_priority(
+ MRSP_Control *mrsp,
+ uint32_t scheduler_index,
+ Priority_Control ceiling_priority
+)
+{
+ mrsp->ceiling_priorities[ scheduler_index ] = ceiling_priority;
+}
+
+RTEMS_INLINE_ROUTINE void _MRSP_Restore_priority( Thread_Control *thread )
+{
+ _Thread_Change_priority( thread, thread->real_priority, true );
+}
+
+RTEMS_INLINE_ROUTINE void _MRSP_Add_state(
+ MRSP_Rival *rival,
+ unsigned int state
+)
+{
+ _Atomic_Fetch_or_uint( &rival->state, state, ATOMIC_ORDER_RELEASE );
+}
+
+RTEMS_INLINE_ROUTINE void _MRSP_Timeout(
+ Objects_Id id,
+ void *arg
+)
+{
+ MRSP_Rival *rival = arg;
+
+ (void) id;
+
+ _MRSP_Add_state( rival, MRSP_RIVAL_STATE_TIMEOUT );
+}
+
+RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Wait_for_ownership(
+ MRSP_Control *mrsp,
+ Thread_Control *executing,
+ Priority_Control ceiling_priority,
+ Watchdog_Interval timeout
+)
+{
+ MRSP_Status status;
+ MRSP_Rival rival;
+ bool previous_life_protection;
+ unsigned int state;
+
+ _Thread_Change_priority( executing, ceiling_priority, false );
+
+ rival.thread = executing;
+ _Atomic_Init_uint( &rival.state, MRSP_RIVAL_STATE_WAITING );
+ _Chain_Append_unprotected( &mrsp->Rivals, &rival.Node );
+
+ if ( timeout > 0 ) {
+ _Watchdog_Initialize(
+ &executing->Timer,
+ _MRSP_Timeout,
+ 0,
+ &rival
+ );
+ _Watchdog_Insert_ticks( &executing->Timer, timeout );
+ }
+
+ previous_life_protection = _Thread_Set_life_protection( true );
+ _Thread_Enable_dispatch();
+
+ _Assert( _Debug_Is_thread_dispatching_allowed() );
+
+ while (
+ _Atomic_Load_uint( &rival.state, ATOMIC_ORDER_ACQUIRE )
+ == MRSP_RIVAL_STATE_WAITING
+ ) {
+ /* Wait for state change */
+ }
+
+ _Thread_Disable_dispatch();
+ _Thread_Set_life_protection( previous_life_protection );
+
+ if ( timeout > 0 ) {
+ _Watchdog_Remove( &executing->Timer );
+ }
+
+ _Chain_Extract_unprotected( &rival.Node );
+ state = _Atomic_Load_uint( &rival.state, ATOMIC_ORDER_RELAXED );
+
+ if ( ( state & MRSP_RIVAL_STATE_NEW_OWNER ) != 0 ) {
+ ++executing->resource_count;
+
+ status = MRSP_SUCCESSFUL;
+ } else {
+ if ( executing->resource_count == 0 ) {
+ _MRSP_Restore_priority( executing );
+ }
+
+ status = MRSP_TIMEOUT;
+ }
+
+ return status;
+}
+
+RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Obtain(
+ MRSP_Control *mrsp,
+ Thread_Control *executing,
+ bool wait,
+ Watchdog_Interval timeout
+)
+{
+ MRSP_Status status;
+ const Scheduler_Control *scheduler = _Scheduler_Get( executing );
+ uint32_t scheduler_index = _Scheduler_Get_index( scheduler );
+ Priority_Control ceiling_priority =
+ _MRSP_Get_ceiling_priority( mrsp, scheduler_index );
+ bool priority_ok = !_Scheduler_Is_priority_higher_than(
+ scheduler,
+ executing->current_priority,
+ ceiling_priority
+ );
+
+ if ( !priority_ok) {
+ return MRSP_INVALID_PRIORITY;
+ }
+
+ if ( mrsp->owner == NULL ) {
+ _MRSP_Claim_ownership( mrsp, executing, ceiling_priority );
+ status = MRSP_SUCCESSFUL;
+ } else if ( mrsp->owner == executing ) {
+ status = MRSP_UNSATISFIED;
+ } else if ( wait ) {
+ status = _MRSP_Wait_for_ownership(
+ mrsp,
+ executing,
+ ceiling_priority,
+ timeout
+ );
+ } else {
+ status = MRSP_UNSATISFIED;
+ }
+
+ return status;
+}
+
+RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Release(
+ MRSP_Control *mrsp,
+ Thread_Control *executing
+)
+{
+ uint32_t resource_count = executing->resource_count;
+
+ if ( mrsp->owner != executing ) {
+ return MRSP_NOT_OWNER_OF_RESOURCE;
+ }
+
+ if ( resource_count == 1 ) {
+ executing->resource_count = 0;
+ _MRSP_Restore_priority( executing );
+ } else {
+ executing->resource_count = resource_count - 1;
+ }
+
+ if ( _Chain_Is_empty( &mrsp->Rivals ) ) {
+ mrsp->owner = NULL;
+ } else {
+ MRSP_Rival *rival = (MRSP_Rival *) _Chain_First( &mrsp->Rivals );
+
+ mrsp->owner = rival->thread;
+ _MRSP_Add_state( rival, MRSP_RIVAL_STATE_NEW_OWNER );
+ }
+
+ return MRSP_SUCCESSFUL;
+}
+
+RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Destroy( MRSP_Control *mrsp )
+{
+ if ( mrsp->owner != NULL ) {
+ return MRSP_RESOUCE_IN_USE;
+ }
+
+ _Workspace_Free( mrsp->ceiling_priorities );
+
+ return MRSP_SUCCESSFUL;
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* RTEMS_SMP */
+
+#endif /* _RTEMS_SCORE_MRSPIMPL_H */
diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h
index 15a4207cfd..be841642ca 100644
--- a/cpukit/score/include/rtems/score/schedulerimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerimpl.h
@@ -617,6 +617,16 @@ RTEMS_INLINE_ROUTINE bool _Scheduler_Get_by_id(
&& _Scheduler_Get_processor_count( scheduler ) > 0;
}
+RTEMS_INLINE_ROUTINE bool _Scheduler_Is_id_valid( Objects_Id id )
+{
+ const Scheduler_Control *scheduler;
+ bool ok = _Scheduler_Get_by_id( id, &scheduler );
+
+ (void) scheduler;
+
+ return ok;
+}
+
RTEMS_INLINE_ROUTINE uint32_t _Scheduler_Get_index(
const Scheduler_Control *scheduler
)
diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am
index d00e1374c6..45a0ce730f 100644
--- a/cpukit/score/preinstall.am
+++ b/cpukit/score/preinstall.am
@@ -139,6 +139,14 @@ $(PROJECT_INCLUDE)/rtems/score/freechain.h: include/rtems/score/freechain.h $(PR
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/freechain.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/freechain.h
+$(PROJECT_INCLUDE)/rtems/score/mrsp.h: include/rtems/score/mrsp.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/mrsp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/mrsp.h
+
+$(PROJECT_INCLUDE)/rtems/score/mrspimpl.h: include/rtems/score/mrspimpl.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/mrspimpl.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/mrspimpl.h
+
$(PROJECT_INCLUDE)/rtems/score/object.h: include/rtems/score/object.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/object.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/object.h