forked from Imagelibrary/rtems
Reimplemented _Core_MUTEX_Seize to return with interrupts disabled
if the mutex is successfully obtained.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user