From fd84982c0019205ea5e4c226f47dd62480cfd5e6 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Fri, 21 Dec 2007 15:50:09 +0000 Subject: 2007-12-21 Xi Yang * 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. --- cpukit/ChangeLog | 9 +++++++ cpukit/configure.ac | 6 +++++ cpukit/score/include/rtems/score/coremutex.h | 37 ++++++++++++++++++++++++--- cpukit/score/include/rtems/score/thread.h | 5 ++++ cpukit/score/inline/rtems/score/coremutex.inl | 14 +++++++--- cpukit/score/src/coremutexsurrender.c | 28 ++++++++++++++++++-- cpukit/score/src/threadinitialize.c | 5 ++++ 7 files changed, 96 insertions(+), 8 deletions(-) (limited to 'cpukit') 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 + + * 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 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. */ @@ -309,6 +310,10 @@ struct Thread_Control_struct { #if defined(RTEMS_MULTIPROCESSING) /** 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. */ 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. */ -- cgit v1.2.3