summaryrefslogtreecommitdiffstats
path: root/cpukit/score/include/rtems/score/mrspimpl.h
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/score/include/rtems/score/mrspimpl.h
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/score/include/rtems/score/mrspimpl.h')
-rw-r--r--cpukit/score/include/rtems/score/mrspimpl.h283
1 files changed, 283 insertions, 0 deletions
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 */