summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/ChangeLog9
-rw-r--r--cpukit/configure.ac6
-rw-r--r--cpukit/score/include/rtems/score/coremutex.h37
-rw-r--r--cpukit/score/include/rtems/score/thread.h5
-rw-r--r--cpukit/score/inline/rtems/score/coremutex.inl14
-rw-r--r--cpukit/score/src/coremutexsurrender.c28
-rw-r--r--cpukit/score/src/threadinitialize.c5
7 files changed, 96 insertions, 8 deletions
diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog
index 2e9bd902d9..9074523e82 100644
--- a/cpukit/ChangeLog
+++ b/cpukit/ChangeLog
@@ -1,3 +1,12 @@
+2007-12-21 Xi Yang <hiyangxi@gmail.com>
+
+ * configure.ac, score/include/rtems/score/coremutex.h,
+ score/include/rtems/score/thread.h,
+ score/inline/rtems/score/coremutex.inl,
+ score/src/coremutexsurrender.c, score/src/threadinitialize.c: Add
+ support for proper stacking of priority inheritance on mutexes as
+ well as enforce proper order of release.
+
2007-12-21 Joel Sherrill <joel.sherrill@OARcorp.com>
PR 1268/cpukit
diff --git a/cpukit/configure.ac b/cpukit/configure.ac
index 3ec7a55281..04f2997d4a 100644
--- a/cpukit/configure.ac
+++ b/cpukit/configure.ac
@@ -224,6 +224,12 @@ RTEMS_CPUOPT([__RTEMS_DO_NOT_INLINE_THREAD_ENABLE_DISPATCH__],
[disable inlining _Thread_Enable_dispatch]
)
+RTEMS_CPUOPT([__STRICT_ORDER_MUTEX__],
+ [test x"${ENABLE_STRICT_ORDER_MUTEX}"=x"1"],
+ [1],
+ [disable strict order mutex]
+)
+
RTEMS_CPUOPT([__RTEMS_MAJOR__],
[true],
[$rtems_major],
diff --git a/cpukit/score/include/rtems/score/coremutex.h b/cpukit/score/include/rtems/score/coremutex.h
index ee600dcc2e..b61c8476e4 100644
--- a/cpukit/score/include/rtems/score/coremutex.h
+++ b/cpukit/score/include/rtems/score/coremutex.h
@@ -21,6 +21,7 @@
#ifndef _RTEMS_SCORE_COREMUTEX_H
#define _RTEMS_SCORE_COREMUTEX_H
+
/**
* @defgroup ScoreMutex Mutex Handler
*
@@ -70,7 +71,7 @@ typedef enum {
*/
CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING
} CORE_mutex_Disciplines;
-
+
/**
* @brief Mutex method return statuses
*
@@ -101,10 +102,16 @@ typedef enum {
* because the resource never became available.
*/
CORE_MUTEX_TIMEOUT,
+#ifdef __STRICT_ORDER_MUTEX__
+ /** This status indicates that a thread not release the mutex which has
+ * the priority inheritance property in a right order.
+ */
+ CORE_MUTEX_RELEASE_NOT_ORDER,
+#endif
/** This status indicates that a thread of logically greater importance
* than the ceiling priority attempted to lock this mutex.
*/
- CORE_MUTEX_STATUS_CEILING_VIOLATED
+ CORE_MUTEX_STATUS_CEILING_VIOLATED,
} CORE_mutex_Status;
/**
@@ -182,6 +189,25 @@ typedef struct {
Priority_Control priority_ceiling;
} CORE_mutex_Attributes;
+#ifdef __STRICT_ORDER_MUTEX__
+/*@brief Core Mutex Lock_Chain Struct
+ *
+ * The following defines the control block used to manage lock chain of
+ * priority inheritance mutex.
+ */
+ typedef struct{
+ /** This field is a chian of locked mutex by a thread,new mutex will
+ * be added to the head of queue, and the mutex which will be released
+ * must be the head of queue.
+ */
+ Chain_Node lock_queue;
+ /** This field is the priority of thread before locking this mutex
+ *
+ */
+ Priority_Control priority_before;
+ } CORE_mutex_order_list;
+#endif
+
/**
* @brief Core Mutex Control Structure
*
@@ -212,6 +238,11 @@ typedef struct {
Thread_Control *holder;
/** This element contains the object Id of the holding thread. */
Objects_Id holder_id;
+#ifdef __STRICT_ORDER_MUTEX__
+ /** This field is used to manipulate the priority inheritance mutex queue. */
+ CORE_mutex_order_list queue;
+#endif
+
} CORE_mutex_Control;
/**
@@ -250,7 +281,7 @@ void _CORE_mutex_Initialize(
* @note For performance reasons, this routine is implemented as
* a macro that uses two support routines.
*/
-RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock(
+int _CORE_mutex_Seize_interrupt_trylock(
CORE_mutex_Control *the_mutex,
ISR_Level *level_p
);
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index 5bfd4534e9..9b9f324b9e 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -253,6 +253,7 @@ typedef struct {
Priority_Control real_priority;
/** This field is the number of mutexes currently held by this proxy. */
uint32_t resource_count;
+
/** This field is the blocking information for this proxy. */
Thread_Wait_information Wait;
/** This field is the Watchdog used to manage proxy delays and timeouts. */
@@ -310,6 +311,10 @@ struct Thread_Control_struct {
/** This field is the received response packet in an MP system. */
MP_packet_Prefix *receive_packet;
#endif
+#ifdef __STRICT_ORDER_MUTEX__
+ /**This field is the head of queue of priority inheritance mutex holed by the thread*/
+ Chain_Control lock_mutex;
+#endif
/*================= end of common block =================*/
/** This field is the number of nested suspend calls. */
uint32_t suspend_count;
diff --git a/cpukit/score/inline/rtems/score/coremutex.inl b/cpukit/score/inline/rtems/score/coremutex.inl
index 342428ccbb..9311cd11a5 100644
--- a/cpukit/score/inline/rtems/score/coremutex.inl
+++ b/cpukit/score/inline/rtems/score/coremutex.inl
@@ -101,7 +101,6 @@ RTEMS_INLINE_ROUTINE boolean _CORE_mutex_Is_inherit_priority(
* PRIORITY_CEILING and FALSE otherwise.
*
* @param[in] the_attribute is the attribute set of the mutex
- *
* @return This method returns TRUE if the mutex is using priority
* ceiling.
*/
@@ -120,7 +119,8 @@ RTEMS_INLINE_ROUTINE boolean _CORE_mutex_Is_priority_ceiling(
*
* NOTE: The Doxygen for this routine is in the .h file.
*/
-RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock(
+
+RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock_body(
CORE_mutex_Control *the_mutex,
ISR_Level *level_p
)
@@ -138,8 +138,16 @@ RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock(
the_mutex->holder_id = executing->Object.id;
the_mutex->nest_count = 1;
if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
- _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) )
+ _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ){
+
+#ifdef __STRICT_ORDER_MUTEX__
+ _Chain_Prepend_unprotected(&executing->lock_mutex,&the_mutex->queue.lock_queue);
+ the_mutex->queue.priority_before = executing->current_priority;
+#endif
+
executing->resource_count++;
+ }
+
if ( !_CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
_ISR_Enable( level );
return 0;
diff --git a/cpukit/score/src/coremutexsurrender.c b/cpukit/score/src/coremutexsurrender.c
index 839c0af5bf..29b246983f 100644
--- a/cpukit/score/src/coremutexsurrender.c
+++ b/cpukit/score/src/coremutexsurrender.c
@@ -54,7 +54,9 @@ CORE_mutex_Status _CORE_mutex_Surrender(
{
Thread_Control *the_thread;
Thread_Control *holder;
-
+#ifdef __STRICT_ORDER_MUTEX__
+ Chain_Node *first_node;
+#endif
holder = the_mutex->holder;
/*
@@ -95,8 +97,18 @@ CORE_mutex_Status _CORE_mutex_Surrender(
* blocked thread.
*/
if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
- _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) )
+ _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ){
+#ifdef __STRICT_ORDER_MUTEX__
+ /*Check whether the holder release the mutex in LIFO order
+ if not return error code*/
+ if(holder->lock_mutex.first != &the_mutex->queue.lock_queue){
+ the_mutex->nest_count++;
+ return CORE_MUTEX_RELEASE_NOT_ORDER;
+ }
+ first_node = _Chain_Get_first_unprotected(&holder->lock_mutex);
+#endif
holder->resource_count--;
+ }
the_mutex->holder = NULL;
the_mutex->holder_id = 0;
@@ -107,6 +119,10 @@ CORE_mutex_Status _CORE_mutex_Surrender(
*/
if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
_CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
+#ifdef __STRICT_ORDER_MUTEX__
+ if(the_mutex->queue.priority_before != holder->current_priority)
+ _Thread_Change_priority(holder,the_mutex->queue.priority_before,TRUE);
+#endif
if ( holder->resource_count == 0 &&
holder->real_priority != holder->current_priority ) {
_Thread_Change_priority( holder, holder->real_priority, TRUE );
@@ -141,9 +157,17 @@ CORE_mutex_Status _CORE_mutex_Surrender(
case CORE_MUTEX_DISCIPLINES_PRIORITY:
break;
case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
+#ifdef __STRICT_ORDER_MUTEX__
+ _Chain_Prepend_unprotected(&the_thread->lock_mutex,&the_mutex->queue.lock_queue);
+ the_mutex->queue.priority_before = the_thread->current_priority;
+#endif
the_thread->resource_count++;
break;
case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
+#ifdef __STRICT_ORDER_MUTEX__
+ _Chain_Prepend_unprotected(&the_thread->lock_mutex,&the_mutex->queue.lock_queue);
+ the_mutex->queue.priority_before = the_thread->current_priority;
+#endif
the_thread->resource_count++;
if (the_mutex->Attributes.priority_ceiling <
the_thread->current_priority){
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index f3e13a4944..b2e09727cc 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -124,6 +124,11 @@ boolean _Thread_Initialize(
*/
_Watchdog_Initialize( &the_thread->Timer, NULL, 0, NULL );
+#ifdef __STRICT_ORDER_MUTEX__
+ /*Initialize the head of chain of mutex */
+ _Chain_Initialize_empty(&the_thread->lock_mutex);
+#endif
+
/*
* Clear the libc reent hook.
*/