summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2000-07-06 19:32:00 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2000-07-06 19:32:00 +0000
commit21e2b2b9bec211f2b2c00ea6496366f5ad985b7e (patch)
tree9adacb7a0a6e1774482165e70b374c7b36d606f9 /cpukit
parent8d5b438b9e9b410872123ff421c3b38bba3c36dd (diff)
downloadrtems-21e2b2b9bec211f2b2c00ea6496366f5ad985b7e.tar.bz2
Reimplemented _Core_MUTEX_Seize to return with interrupts disabled
if the mutex is successfully obtained.
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/score/include/rtems/score/coremutex.h36
-rw-r--r--cpukit/score/inline/rtems/score/coremutex.inl90
2 files changed, 119 insertions, 7 deletions
diff --git a/cpukit/score/include/rtems/score/coremutex.h b/cpukit/score/include/rtems/score/coremutex.h
index 9f27ae0c1d..db3350dab2 100644
--- a/cpukit/score/include/rtems/score/coremutex.h
+++ b/cpukit/score/include/rtems/score/coremutex.h
@@ -149,15 +149,41 @@ void _CORE_mutex_Initialize(
* If a unit is available or if the wait flag is FALSE, then the routine
* returns. Otherwise, the calling task is blocked until a unit becomes
* available.
+ *
+ * NOTE: For performance reasons, this routine is implemented as
+ * a macro that uses two support routines.
*/
-void _CORE_mutex_Seize(
+RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock(
+ CORE_mutex_Control *the_mutex,
+ ISR_Level *level_p
+);
+
+void _CORE_mutex_Seize_interrupt_blocking(
CORE_mutex_Control *the_mutex,
- Objects_Id id,
boolean wait,
Watchdog_Interval timeout
);
-
+
+#define _CORE_mutex_Seize( \
+ _the_mutex, _id, _wait, _timeout, _level ) \
+ do { \
+ if ( _CORE_mutex_Seize_interrupt_trylock( _the_mutex, &_level ) ) { \
+ if ( !_wait ) { \
+ _ISR_Enable( _level ); \
+ _Thread_Executing->Wait.return_code = \
+ CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT; \
+ } else { \
+ _Thread_queue_Enter_critical_section( &(_the_mutex)->Wait_queue ); \
+ _Thread_Executing->Wait.queue = &(_the_mutex)->Wait_queue; \
+ _Thread_Executing->Wait.id = _id; \
+ _Thread_Disable_dispatch(); \
+ _ISR_Enable( _level ); \
+ _CORE_mutex_Seize_interrupt_blocking( _the_mutex, _id, _timeout ); \
+ } \
+ } \
+ } while (0)
+
/*
* _CORE_mutex_Surrender
*
@@ -189,10 +215,6 @@ void _CORE_mutex_Flush(
unsigned32 status
);
-#ifndef __RTEMS_APPLICATION__
-#include <rtems/score/coremutex.inl>
-#endif
-
#ifdef __cplusplus
}
#endif
diff --git a/cpukit/score/inline/rtems/score/coremutex.inl b/cpukit/score/inline/rtems/score/coremutex.inl
index 8ce3a9b214..5192528d87 100644
--- a/cpukit/score/inline/rtems/score/coremutex.inl
+++ b/cpukit/score/inline/rtems/score/coremutex.inl
@@ -101,5 +101,95 @@ RTEMS_INLINE_ROUTINE boolean _CORE_mutex_Is_priority_ceiling(
return the_attribute->discipline == CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
}
+/*PAGE
+ *
+ * _CORE_mutex_Seize_interrupt_trylock
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns 0 if "trylock" can resolve whether or not the
+ * mutex is immediately obtained or there was an error attempting to
+ * get it. It returns 1 to indicate that the caller cannot obtain
+ * the mutex and will have to block to do so.
+ *
+ * NOTE: There is no MACRO version of this routine.
+ */
+
+RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock(
+ CORE_mutex_Control *the_mutex,
+ ISR_Level *level_p
+)
+{
+ Thread_Control *executing;
+ ISR_Level level = *level_p;
+
+ /* disabled when you get here */
+
+ executing = _Thread_Executing;
+ executing->Wait.return_code = CORE_MUTEX_STATUS_SUCCESSFUL;
+ if ( !_CORE_mutex_Is_locked( the_mutex ) ) {
+ the_mutex->lock = CORE_MUTEX_LOCKED;
+ the_mutex->holder = executing;
+ the_mutex->holder_id = executing->Object.id;
+ the_mutex->nest_count = 1;
+ executing->resource_count++;
+ if ( the_mutex->Attributes.discipline !=
+ CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING ) {
+ _ISR_Enable( level );
+ return 0;
+ }
+ /* else must be CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING */
+ {
+ Priority_Control ceiling;
+ Priority_Control current;
+
+ ceiling = the_mutex->Attributes.priority_ceiling;
+ current = executing->current_priority;
+ if ( current == ceiling ) {
+ _ISR_Enable( level );
+ return 0;
+ }
+ if ( current > ceiling ) {
+ _Thread_Disable_dispatch();
+ _ISR_Enable( level );
+ _Thread_Change_priority(
+ the_mutex->holder,
+ the_mutex->Attributes.priority_ceiling,
+ FALSE
+ );
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ /* if ( current < ceiling ) */ {
+ executing->Wait.return_code = CORE_MUTEX_STATUS_CEILING_VIOLATED;
+ the_mutex->nest_count = 0; /* undo locking above */
+ executing->resource_count--; /* undo locking above */
+ _ISR_Enable( level );
+ return 0;
+ }
+ }
+ return 0;
+ }
+
+ if ( _Thread_Is_executing( the_mutex->holder ) ) {
+ switch ( the_mutex->Attributes.lock_nesting_behavior ) {
+ case CORE_MUTEX_NESTING_ACQUIRES:
+ the_mutex->nest_count++;
+ _ISR_Enable( level );
+ return 0;
+ case CORE_MUTEX_NESTING_IS_ERROR:
+ executing->Wait.return_code = CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
+ _ISR_Enable( level );
+ return 0;
+ case CORE_MUTEX_NESTING_BLOCKS:
+ break;
+ }
+ }
+
+ return 1;
+}
+
+#endif
+
#endif
/* end of include file */