Hi,
This is the patch for solving priority inversion problem for uniprocessor
architecture. It works correctly for all test cases on master. For 4.11 the
patch get applied cleanly but the branch does not compile because of some
rbtree error(unrelated to project). Github link:
https://github.com/saurabhgadia4/rtems/tree/nested-mutex
Thanks,

Saurabh Gadia
From ffe654a71bbe6eab9002499a245e023a4a08e5c1 Mon Sep 17 00:00:00 2001
From: Saurabh <ga...@usc.edu>
Date: Fri, 4 Sep 2015 16:27:31 -0700
Subject: [PATCH] Complete Nested Mutex patch for solving priority inversion
 problem in uniprocessor architecture

---
 README                                        |   1 +
 c/src/lib/libbsp/bfin/acinclude.m4            |   4 +-
 c/src/lib/libbsp/powerpc/acinclude.m4         |   4 +-
 cpukit/score/include/rtems/score/priority.h   |   7 +
 cpukit/score/include/rtems/score/threadimpl.h |  90 ++++++++++++
 cpukit/score/src/coremutexseize.c             |   4 +-
 cpukit/score/src/coremutexsurrender.c         |   2 +-
 cpukit/score/src/threadchangepriority.c       | 119 +++++++++++++++
 testsuites/sptests/Makefile.am                |   2 +-
 testsuites/sptests/configure.ac               |   1 +
 testsuites/sptests/spsem04/Makefile.am        |  21 +++
 testsuites/sptests/spsem04/init.c             | 202 ++++++++++++++++++++++++++
 testsuites/sptests/spsem04/spsem04.doc        |  27 ++++
 testsuites/sptests/spsem04/spsem04.scn        |  26 ++++
 14 files changed, 503 insertions(+), 7 deletions(-)
 create mode 100644 testsuites/sptests/spsem04/Makefile.am
 create mode 100644 testsuites/sptests/spsem04/init.c
 create mode 100644 testsuites/sptests/spsem04/spsem04.doc
 create mode 100644 testsuites/sptests/spsem04/spsem04.scn

diff --git a/README b/README
index 88a4999..d960835 100644
--- a/README
+++ b/README
@@ -22,3 +22,4 @@ discussions:
 See https://devel.rtems.org/ to view existing or file a new issue
 report ticket.
 
+This branch is for fixing problem of priority inversion caused by nested mutex.
\ No newline at end of file
diff --git a/c/src/lib/libbsp/bfin/acinclude.m4 b/c/src/lib/libbsp/bfin/acinclude.m4
index ab6082e..828fd89 100644
--- a/c/src/lib/libbsp/bfin/acinclude.m4
+++ b/c/src/lib/libbsp/bfin/acinclude.m4
@@ -2,12 +2,12 @@
 AC_DEFUN([RTEMS_CHECK_BSPDIR],
 [
   case "$1" in
-  TLL6527M )
-    AC_CONFIG_SUBDIRS([TLL6527M]);;
   bf537Stamp )
     AC_CONFIG_SUBDIRS([bf537Stamp]);;
   eZKit533 )
     AC_CONFIG_SUBDIRS([eZKit533]);;
+  TLL6527M )
+    AC_CONFIG_SUBDIRS([TLL6527M]);;
   *)
     AC_MSG_ERROR([Invalid BSP]);;
   esac
diff --git a/c/src/lib/libbsp/powerpc/acinclude.m4 b/c/src/lib/libbsp/powerpc/acinclude.m4
index 6442399..e46fa2b 100644
--- a/c/src/lib/libbsp/powerpc/acinclude.m4
+++ b/c/src/lib/libbsp/powerpc/acinclude.m4
@@ -38,12 +38,12 @@ AC_DEFUN([RTEMS_CHECK_BSPDIR],
     AC_CONFIG_SUBDIRS([t32mppc]);;
   tqm8xx )
     AC_CONFIG_SUBDIRS([tqm8xx]);;
-  virtex )
-    AC_CONFIG_SUBDIRS([virtex]);;
   virtex4 )
     AC_CONFIG_SUBDIRS([virtex4]);;
   virtex5 )
     AC_CONFIG_SUBDIRS([virtex5]);;
+  virtex )
+    AC_CONFIG_SUBDIRS([virtex]);;
   *)
     AC_MSG_ERROR([Invalid BSP]);;
   esac
diff --git a/cpukit/score/include/rtems/score/priority.h b/cpukit/score/include/rtems/score/priority.h
index 0a772f6..262b889 100644
--- a/cpukit/score/include/rtems/score/priority.h
+++ b/cpukit/score/include/rtems/score/priority.h
@@ -55,6 +55,13 @@ extern "C" {
  */
 typedef uint32_t   Priority_Control;
 
+typedef enum {
+	PRIORITY_STATUS_NORMAL,
+	PRIORITY_STATUS_CHANGED,
+	PRIORITY_STATUS_NOT_CHANGED,
+	PRIORITY_STATUS_INVERSION_ERROR
+} Priority_Status;
+
 /** This defines the highest (most important) thread priority. */
 #define PRIORITY_MINIMUM      0
 
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index 4656881..8a2e6f5 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -396,6 +396,96 @@ typedef bool ( *Thread_Change_priority_filter )(
 );
 
 /**
+ * @brief Changes the priority of a holder thread.
+ *
+ * It is the wrapper function for updating priority of holder thread.
+ *
+ * @param[in] holder This thread is holder of mutex.
+ * @param[in] the_mutex It is the mutex which is acquired by the holder 
+ * thread and executing thread is contending on it.
+ * @param[in] new_priority It is the current_priority of executing thread.
+ * @param[in] prepend_it In case this is true, then the thread is prepended to
+ * its priority group in its scheduler instance, otherwise it is appended.
+ * 
+ * @note This function is only valid for uniprocessor targets.
+ */
+void _Thread_Change_priority_UP(
+  Thread_Control   *holder,
+  CORE_mutex_Control  *the_mutex,
+  Priority_Control  new_priority,
+  bool prepend_it
+);
+
+/**
+ * @brief Updates the recorded priority_before and current_priority of thread
+ * 
+ * It goes through the list of acquired mutex by the holder thread and checks
+ * the priority_before recorded while holder acquired that mutex. If
+ * priority_before is greater than the contending executing thread then
+ * it changes the priority_before to executing thread's current_priority. This
+ * ensure proper stepdown of priority to avoid priority inversion for
+ * priority inheritance discipline mutex.
+ *
+ * @param[in] holder This thread is holder of mutex on which executing thread
+ * is contending.
+ * @param[in] mutex_queue It consists of node chained to the mutex list 
+ * maintained be Thread_Control.
+ * @param[in] new_priority It is the priority of executing thread.
+ * @param[in] lock_context The lock context used for the corresponding lock
+ * release.
+ * @param[in] prepend_it In case this is true, then the thread is prepended to
+ * its priority group in its scheduler instance, otherwise it is appended.
+ *
+ * @note This function is only valid for uniprocessor targets.
+ */
+void _Thread_Update_Priority_UP(
+  Thread_Control   *holder,
+  CORE_mutex_order_list  *mutex_queue,
+  Priority_Control  new_priority,
+  ISR_lock_Context    *lock_context,
+  bool prepend_it
+);
+
+/**
+ * @brief Updates priorities recorded in mutex list of holder thread.
+ * 
+ * @param[in] holder This thread is holder of mutex on which executing thread
+ * is contending.
+ * @param[in] mutex_queue It consists of node chained to the mutex list 
+ * maintained be Thread_Control.
+ * @param[in] new_priority It is the priority of executing thread.
+ * @param[out] Priority_StatusIt returns whether to update current_priority
+ * of holder thread.
+ *
+ * @note This function is only valid for uniprocessor targets.
+ */
+Priority_Status _Thread_Update_Rec_Priority_UP(
+  Thread_Control   *holder,
+  CORE_mutex_order_list  *mutex_queue,
+  Priority_Control  new_priority
+);
+
+/**
+ * @brief Validates the current_priority of executing thread.
+ * 
+ * It validates current_priority of executing thread against priority of 
+ * top most waited thread on mutexes acquired by executing thread. It
+ * should be paired with unlock/release operation and both operations should
+ * be togetherly atomic for correctness. It is developed for checking of
+ * priority inversion problem. 
+ * 
+ * @param[in] holder This thread is holder of mutex on which executing thread
+ * is contending.
+ * @param[out] Priority_Status It returns the status of current_priorty
+ * of executing thread.
+ *
+ * @note This function is only valid for uniprocessor targets.
+ */
+Priority_Status _Thread_Validate_Priority(
+  Thread_Control *executing
+);
+
+/**
  * @brief Changes the priority of a thread if allowed by the filter function.
  *
  * It changes current priority of the thread to the new priority in case the
diff --git a/cpukit/score/src/coremutexseize.c b/cpukit/score/src/coremutexseize.c
index ddc5d6b..1ec74f6 100644
--- a/cpukit/score/src/coremutexseize.c
+++ b/cpukit/score/src/coremutexseize.c
@@ -73,9 +73,11 @@ void _CORE_mutex_Seize_interrupt_blocking(
      * once we released the lock.
      */
     _Thread_queue_Release( &the_mutex->Wait_queue, lock_context );
-#endif
+    _Thread_Change_priority_UP( holder, the_mutex, executing->current_priority, false);
 
+#else
     _Thread_Raise_priority( holder, executing->current_priority );
+#endif
 
 #if !defined(RTEMS_SMP)
     _Thread_queue_Acquire( &the_mutex->Wait_queue, lock_context );
diff --git a/cpukit/score/src/coremutexsurrender.c b/cpukit/score/src/coremutexsurrender.c
index d3f965d..8c802df 100644
--- a/cpukit/score/src/coremutexsurrender.c
+++ b/cpukit/score/src/coremutexsurrender.c
@@ -57,7 +57,7 @@
     _Chain_Get_first_unprotected( &holder->lock_mutex );
 
     if ( mutex->queue.priority_before != holder->current_priority )
-      _Thread_Change_priority( holder, mutex->queue.priority_before, true );
+      _Thread_Restore_priority( holder);
 
     return CORE_MUTEX_STATUS_SUCCESSFUL;
   }
diff --git a/cpukit/score/src/threadchangepriority.c b/cpukit/score/src/threadchangepriority.c
index 8f5d14f..5c4e5d8 100644
--- a/cpukit/score/src/threadchangepriority.c
+++ b/cpukit/score/src/threadchangepriority.c
@@ -22,6 +22,125 @@
 #include <rtems/score/threadimpl.h>
 #include <rtems/score/schedulerimpl.h>
 
+Priority_Status _Thread_Validate_Priority(
+  Thread_Control *executing
+)
+{
+  CORE_mutex_Control *the_mutex;
+  CORE_mutex_order_list  *node;
+  Thread_Control *the_thread;
+  Chain_Node *head = _Chain_Head(&executing->lock_mutex);
+  Chain_Node *check = head->next;
+  while(head!=check)
+  {
+    node = RTEMS_CONTAINER_OF(check, CORE_mutex_order_list, lock_queue);
+    the_mutex = RTEMS_CONTAINER_OF(node, CORE_mutex_Control, queue);
+    if ( ( the_thread = _Thread_queue_First_locked( &the_mutex->Wait_queue ) ) )
+    {
+      if(executing->current_priority > the_thread->current_priority)
+      {
+        return PRIORITY_STATUS_INVERSION_ERROR;
+      }
+    }
+    check=check->next;
+  }
+  return PRIORITY_STATUS_NORMAL;
+}
+
+Priority_Status _Thread_Update_Rec_Priority_UP(
+  Thread_Control   *holder,
+  CORE_mutex_order_list  *queue,
+  Priority_Control  new_priority
+)
+{
+  Chain_Node *start = &queue->lock_queue;
+  Chain_Node *head = _Chain_Head(&holder->lock_mutex);
+  Chain_Node *check = start->previous;
+  while(check!=head)
+  {
+    queue = RTEMS_CONTAINER_OF(check, CORE_mutex_order_list, lock_queue);
+    if(!(queue->priority_before > new_priority))
+    {
+      return PRIORITY_STATUS_NOT_CHANGED;
+    }
+    queue->priority_before = new_priority;
+    check = check->previous;
+  }
+  if(holder->current_priority > new_priority)
+    return PRIORITY_STATUS_CHANGED;
+  else
+    return PRIORITY_STATUS_NOT_CHANGED;
+}
+
+
+void _Thread_Update_Priority_UP(
+  Thread_Control   *holder,
+  CORE_mutex_order_list  *queue,
+  Priority_Control  new_priority,
+  ISR_lock_Context    *lock_context,
+  bool prepend_it
+)
+{
+  Priority_Status status;
+  status = _Thread_Update_Rec_Priority_UP(holder, queue, new_priority);
+  if(status == PRIORITY_STATUS_CHANGED)
+  {
+    uint32_t my_generation;
+    my_generation = holder->priority_generation + 1;
+    holder->current_priority = new_priority;
+    holder->priority_generation = my_generation;
+    ( *holder->Wait.operations->priority_change )(
+      holder,
+      new_priority,
+      holder->Wait.queue
+    );
+    
+    _Scheduler_Acquire( holder, lock_context );
+
+    if ( holder->priority_generation == my_generation ) {
+      if ( _States_Is_ready( holder->current_state ) ) {
+        _Scheduler_Change_priority(
+          holder,
+          new_priority,
+          prepend_it
+        );
+      } else {
+        _Scheduler_Update_priority( holder, new_priority );
+      }
+    }
+
+    _Scheduler_Release( holder, lock_context );
+
+    if(holder->Wait.queue!=NULL){
+      CORE_mutex_Control *the_mutex = RTEMS_CONTAINER_OF(holder->Wait.queue, 
+        CORE_mutex_Control, Wait_queue);
+      _Thread_Update_Priority_UP(the_mutex->holder, &the_mutex->queue, 
+        holder->current_priority, lock_context, prepend_it);  
+    }
+  
+  }
+    
+}
+
+void _Thread_Change_priority_UP(
+  Thread_Control   *holder,
+  CORE_mutex_Control  *the_mutex,
+  Priority_Control  new_priority,
+  bool prepend_it
+)
+{
+  ISR_lock_Context  lock_context;
+  ISR_lock_Control *lock;
+
+  lock = _Thread_Lock_acquire( holder, &lock_context );
+  holder->priority_restore_hint = true;
+  _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
+  _Thread_Update_Priority_UP(holder, &the_mutex->queue, new_priority, 
+    &lock_context, prepend_it);
+  _Thread_Lock_release( lock, &lock_context );
+
+}
+
 void _Thread_Change_priority(
   Thread_Control                *the_thread,
   Priority_Control               new_priority,
diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am
index d012019..2ece6cc 100644
--- a/testsuites/sptests/Makefile.am
+++ b/testsuites/sptests/Makefile.am
@@ -26,7 +26,7 @@ _SUBDIRS = \
     spintrcritical09 spintrcritical10 spintrcritical11 spintrcritical12 \
     spintrcritical13 spintrcritical14 spintrcritical15 spintrcritical16 \
     spintrcritical17 spintrcritical18 spmkdir spmountmgr01 spheapprot \
-    sppagesize spsem01 spsem02 spsimplesched01 spsimplesched02 \
+    sppagesize spsem01 spsem02 spsem04 spsimplesched01 spsimplesched02 \
     spsimplesched03 spnsext01 spedfsched01 spedfsched02 spedfsched03 \
     spcbssched01 spcbssched02 spcbssched03 spqreslib sptimespec01 \
     spregion_err01 sppartition_err01 spratemon_err01 spintr_err01 \
diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac
index be69f09..d334e36 100644
--- a/testsuites/sptests/configure.ac
+++ b/testsuites/sptests/configure.ac
@@ -53,6 +53,7 @@ spatomic01/Makefile
 spglobalcon01/Makefile
 spintrcritical22/Makefile
 spsem03/Makefile
+spsem04/Makefile
 spresource01/Makefile
 spmrsp01/Makefile
 spscheduler01/Makefile
diff --git a/testsuites/sptests/spsem04/Makefile.am b/testsuites/sptests/spsem04/Makefile.am
new file mode 100644
index 0000000..d3935a9
--- /dev/null
+++ b/testsuites/sptests/spsem04/Makefile.am
@@ -0,0 +1,21 @@
+
+rtems_tests_PROGRAMS = spsem04
+spsem04_SOURCES = init.c
+
+dist_rtems_tests_DATA = spsem04.scn
+dist_rtems_tests_DATA += spsem04.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 = $(spsem04_OBJECTS)
+LINK_LIBS = $(spsem04_LDLIBS)
+
+spsem04$(EXEEXT): $(spsem04_OBJECTS) $(spsem04_DEPENDENCIES)
+	@rm -f spsem04$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/sptests/spsem04/init.c b/testsuites/sptests/spsem04/init.c
new file mode 100644
index 0000000..3bc283c
--- /dev/null
+++ b/testsuites/sptests/spsem04/init.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2013 Gedare Bloom.
+ *
+ * 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.
+ */
+
+#include <rtems.h>
+
+#include <stdio.h>
+#include "tmacros.h"
+
+/* configuration information */
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+#define CONFIGURE_MAXIMUM_TASKS 4
+#define CONFIGURE_MAXIMUM_SEMAPHORES 2
+#define CONFIGURE_INIT
+#include <rtems/confdefs.h>
+
+const char rtems_test_name[] = "SPSEM 4";
+
+rtems_task Task01(rtems_task_argument ignored);
+rtems_task Task02(rtems_task_argument ignored);
+rtems_task Task03(rtems_task_argument ignored);
+rtems_task Init(rtems_task_argument ignored);
+
+static int getprio(void)
+{
+  rtems_status_code status;
+  rtems_task_priority pri;
+
+  status = rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &pri);
+  directive_failed( status, "rtems_task_set_priority");
+  return (int)pri;
+}
+
+rtems_id   Task_id[3];
+rtems_name Task_name[3];
+
+rtems_id   sem_id[2];
+rtems_name sem_name[2];
+
+rtems_task Init(rtems_task_argument ignored)
+{
+  rtems_status_code status;
+  rtems_attribute sem_attr;
+
+  TEST_BEGIN();
+
+  sem_attr = RTEMS_INHERIT_PRIORITY | RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY;
+
+  sem_name[0] = rtems_build_name( 'S','0',' ',' ');
+  status = rtems_semaphore_create(
+    sem_name[0],
+    1,
+    sem_attr,
+    0,
+    &sem_id[0]
+  );
+  directive_failed( status, "rtems_semaphore_create of S0");
+  printf("init: S0 created\n");
+
+  sem_name[1] = rtems_build_name( 'S','1',' ',' ');
+  status = rtems_semaphore_create(
+    sem_name[1],
+    1,
+    sem_attr,
+    0,
+    &sem_id[1]
+  );
+  directive_failed( status, "rtems_semaphore_create of S1");
+  printf("init: S1 created\n");
+
+  Task_name[0] = rtems_build_name( 'T','A','0','1');
+  status = rtems_task_create(
+    Task_name[0],
+    36,
+    RTEMS_MINIMUM_STACK_SIZE,
+    RTEMS_DEFAULT_MODES,
+    RTEMS_DEFAULT_ATTRIBUTES,
+    &Task_id[0]
+  );
+  directive_failed( status, "rtems_task_create of TA01");
+  printf("init: TA01 created with priority 36\n");
+
+  Task_name[1] = rtems_build_name( 'T','A','0','2');
+  status = rtems_task_create(
+    Task_name[1],
+    34,
+    RTEMS_MINIMUM_STACK_SIZE,
+    RTEMS_DEFAULT_MODES,
+    RTEMS_DEFAULT_ATTRIBUTES,
+    &Task_id[1]
+  );
+  directive_failed( status , "rtems_task_create of TA02\n");
+  printf("init: TA02 created with priority 34\n");
+
+  Task_name[2] = rtems_build_name( 'T','A','0','3');
+  status = rtems_task_create(
+    Task_name[2],
+    32,
+    RTEMS_MINIMUM_STACK_SIZE,
+    RTEMS_DEFAULT_MODES,
+    RTEMS_DEFAULT_ATTRIBUTES,
+    &Task_id[2]
+  );
+  directive_failed( status , "rtems_task_create of TA03\n");
+  printf("init: TA03 created with priority 32\n");
+
+  status = rtems_task_start( Task_id[0], Task01, 0);
+  directive_failed( status, "rtems_task_start of TA01");
+
+  status = rtems_task_delete( RTEMS_SELF);
+  directive_failed( status, "rtems_task_delete of INIT");
+}
+
+/* Task01 starts with priority 36 */
+rtems_task Task01(rtems_task_argument ignored)
+{
+  rtems_status_code status;
+  printf("TA01: started with priority %d\n", getprio());
+
+  status = rtems_semaphore_obtain( sem_id[0], RTEMS_WAIT, 0 );
+  directive_failed( status, "rtems_semaphore_obtain of S0\n");
+  printf("TA01: priority %d, holding S0\n", getprio());
+
+  /* Start Task 2 (TA02) with priority 34. It will run immediately. */
+  status = rtems_task_start( Task_id[1], Task02, 0);
+  directive_failed( status, "rtems_task_start of TA02\n");
+
+  /* Start Task 3 (TA03) with priority 32. It will run immediately. */
+  printf("TA01: priority %d, holding S0 and now creating TA03\n", getprio());
+  status = rtems_task_start( Task_id[2], Task03, 0);
+  directive_failed( status, "rtems_task_start of TA03\n");
+ 
+  printf("TA01: priority %d Releasing s0\n", getprio());
+  status = rtems_semaphore_release(sem_id[0]);
+  directive_failed( status, "rtems_semaphore_release of S0\n");
+  printf("TA01: priority %d\n", getprio());
+
+  printf("TA01: exiting\n");
+  TEST_END();
+  rtems_test_exit(0);
+ 
+}
+
+/* TA02 starts at Task02 with priority 34 */
+rtems_task Task02(rtems_task_argument ignored)
+{
+  rtems_status_code status;
+
+  printf("TA02: started with priority %d\n", getprio());
+
+  /* Obtain S1, which should be held by TA01 by now */
+  status = rtems_semaphore_obtain( sem_id[1], RTEMS_WAIT, 0 );
+  directive_failed( status, " rtems_semaphore_obtain S1");
+  printf("TA02: priority %d, holding S1\n", getprio());
+
+  status = rtems_semaphore_obtain( sem_id[0], RTEMS_WAIT, 0 );
+  directive_failed( status, " rtems_semaphore_obtain S1");
+  printf("TA02: priority %d, holding S1,S0\n", getprio());
+
+  printf("TA02: priority %d before releasing S0\n", getprio());
+  status = rtems_semaphore_release(sem_id[0]);
+  directive_failed( status, "rtems_semaphore_release of S0\n");
+  printf("TA02: priority %d after releasing S0\n", getprio());
+
+  printf("TA02: priority %d before releasing S1\n", getprio());
+  status = rtems_semaphore_release(sem_id[1]);
+  directive_failed( status, "rtems_semaphore_release of S0\n");
+  printf("TA02: priority %d after releasing S1\n", getprio());
+
+  printf("TA02: suspending\n");
+  status = rtems_task_suspend( RTEMS_SELF);
+  directive_failed( status, "rtems_task_suspend TA02");
+}
+
+/* Task03 starts with priority 32 */
+rtems_task Task03(rtems_task_argument ignored)
+{
+  rtems_status_code status;
+  printf("TA03: started with priority %d\n", getprio());
+
+  status = rtems_semaphore_obtain( sem_id[1], RTEMS_WAIT, 0 );
+  directive_failed( status, "rtems_semaphore_obtain of S0\n");
+  printf("TA03: priority %d, holding S1\n", getprio());
+
+  status = rtems_semaphore_release(sem_id[1]);
+  directive_failed( status, "rtems_semaphore_release of S0\n");
+  printf("TA03: priority %d\n", getprio());
+
+  printf("TA03: suspending\n");
+  status = rtems_task_suspend( RTEMS_SELF);
+  directive_failed( status, "rtems_task_suspend TA03");
+
+
+}
diff --git a/testsuites/sptests/spsem04/spsem04.doc b/testsuites/sptests/spsem04/spsem04.doc
new file mode 100644
index 0000000..e6d8d1b
--- /dev/null
+++ b/testsuites/sptests/spsem04/spsem04.doc
@@ -0,0 +1,27 @@
+This test demonstrates priority inheritance with multiple locks and threads.
+
+The scenario consists of 3 Task s of different priority and 2 semaphore/mutexes
+using priority inheritance. The scenario is:
+
+Task  1 has priority 36. Task  2 has priority 34. Task  3 has priority 32.
+
+Throughout the course following actions are to be executed:
+
+Task 1 acauires semaphore S0, Task 2 acquires S1 and S0 and Task 3 acquires S1.
+
+
+1. Task 1  acquires semaphore S0 with priority 36.
+2. Task 1 spawns Task 2 having priority 34.
+3. Task 2 takes over as it has higher priority than Task 1.
+4. Task 2 acquires semaphore S1 with priority 34.
+5. Task 2 tries to acquire S0 but it is locked so promotes Task 1 priority to 34.
+6. Task 1 gains control and now creates Task 3 having 32.
+7. Task 3 takes over and tries to acquire semaphore S1. But it is acquired by Task 2.
+8. Task 3 promotes Task 2 priority to 32. But it observe that Task 2 is also waiting on semaphore S0 held by Task 1.
+9. Task 3 promotes Task 1 priority to 32 as well. (Indirect reference case).
+10. Task 1 get control. It releases semaphore S0 and now its priority becomes 36 so Task 2 takes over.
+11. Task 2 acquires semaphore S0. 
+12. Task 2 releases S0 and S1. And its priority now becomes 34(real priority)
+13. Task 3 takes over. It acquires S1. Releases S1 and suspends self.
+14. Task 2 gets control. It also suspends self.
+15. Task 1 gets control and exits the test.
diff --git a/testsuites/sptests/spsem04/spsem04.scn b/testsuites/sptests/spsem04/spsem04.scn
new file mode 100644
index 0000000..01004bf
--- /dev/null
+++ b/testsuites/sptests/spsem04/spsem04.scn
@@ -0,0 +1,26 @@
+*** BEGIN OF TEST SPSEM 4 ***
+init: S0 created
+init: S1 created
+init: TA01 created with priority 36
+init: TA02 created with priority 34
+init: TA03 created with priority 32
+TA01: started with priority 36
+TA01: priority 36, holding S0
+TA02: started with priority 34
+TA02: priority 34, holding S1
+TA01: priority 34, holding S0 and now creating TA03
+TA03: started with priority 32
+TA01: priority 32 Releasing s0
+TA02: priority 32, holding S1,S0
+TA02: priority 32 before releasing S0
+TA02: priority 32 after releasing S0
+TA02: priority 32 before releasing S1
+TA03: priority 32, holding S1
+TA03: priority 32
+TA03: suspending
+TA02: priority 34 after releasing S1
+TA02: suspending
+TA01: priority 36
+TA01: exiting
+*** END OF TEST SPSEM 4 ***
+[Inferior 1 (process 42000) exited normally]
-- 
1.9.1

_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

Reply via email to