mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-28 15:53:06 +08:00
Added support for simple binary semaphores in addition to the high
power binary/mutex style semaphores already supported by RTEMS. This was done at the request of Eric Norum <eric@cls.usask.ca> in support of his effort to port EPICS to RTEMS. This change consisted of changing the nesting_allowed boolean into a lock_nesting_behavior enumerated value as well as allowing the core mutex object to optionally support ensuring that the holder of a binary semaphore released it. Finally, a more subtle enhancement was to allow the non-holder to release a priority inheritance/ceiling mutex and still allow the holding task to return to its original priority.
This commit is contained in:
@@ -144,7 +144,11 @@ int pthread_mutex_init(
|
||||
|
||||
the_mutex_attr = &the_mutex->Mutex.Attributes;
|
||||
|
||||
the_mutex_attr->allow_nesting = the_attr->recursive;
|
||||
if ( the_attr->recursive )
|
||||
the_mutex_attr->lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
|
||||
else
|
||||
the_mutex_attr->lock_nesting_behavior = CORE_MUTEX_NESTING_IS_ERROR;
|
||||
the_mutex_attr->only_owner_release = TRUE;
|
||||
the_mutex_attr->priority_ceiling =
|
||||
_POSIX_Priority_To_core( the_attr->prio_ceiling );
|
||||
the_mutex_attr->discipline = the_discipline;
|
||||
|
||||
@@ -37,17 +37,16 @@ typedef unsigned32 rtems_attribute;
|
||||
#define RTEMS_FIFO 0x00000000 /* process RTEMS_FIFO */
|
||||
#define RTEMS_PRIORITY 0x00000004 /* process by priority */
|
||||
|
||||
#define RTEMS_COUNTING_SEMAPHORE 0x00000000
|
||||
#define RTEMS_BINARY_SEMAPHORE 0x00000010
|
||||
#define RTEMS_SEMAPHORE_CLASS 0x00000030 /* mask */
|
||||
#define RTEMS_COUNTING_SEMAPHORE 0x00000000
|
||||
#define RTEMS_BINARY_SEMAPHORE 0x00000010
|
||||
#define RTEMS_SIMPLE_BINARY_SEMAPHORE 0x00000020
|
||||
|
||||
#define RTEMS_NO_INHERIT_PRIORITY 0x00000000
|
||||
#define RTEMS_INHERIT_PRIORITY 0x00000020
|
||||
#define RTEMS_INHERIT_PRIORITY 0x00000040
|
||||
|
||||
#define RTEMS_NO_PRIORITY_CEILING 0x00000000
|
||||
#define RTEMS_PRIORITY_CEILING 0x00000040
|
||||
|
||||
#define RTEMS_NESTING_ALLOWED 0x00000000
|
||||
#define RTEMS_NO_NESTING_ALLOWED 0x00000080
|
||||
#define RTEMS_PRIORITY_CEILING 0x00000080
|
||||
|
||||
#define RTEMS_APPLICATION_TASK 0x00000000
|
||||
#define RTEMS_SYSTEM_TASK 0x00000100
|
||||
|
||||
@@ -119,7 +119,42 @@ RTEMS_INLINE_ROUTINE boolean _Attributes_Is_binary_semaphore(
|
||||
rtems_attribute attribute_set
|
||||
)
|
||||
{
|
||||
return ( attribute_set & RTEMS_BINARY_SEMAPHORE );
|
||||
return ((attribute_set & RTEMS_SEMAPHORE_CLASS) == RTEMS_BINARY_SEMAPHORE);
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Attributes_Is_simple_binary_semaphore
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* This function returns TRUE if the simple binary semaphore attribute is
|
||||
* enabled in the attribute_set and FALSE otherwise.
|
||||
*/
|
||||
|
||||
RTEMS_INLINE_ROUTINE boolean _Attributes_Is_simple_binary_semaphore(
|
||||
rtems_attribute attribute_set
|
||||
)
|
||||
{
|
||||
return
|
||||
((attribute_set & RTEMS_SEMAPHORE_CLASS) == RTEMS_SIMPLE_BINARY_SEMAPHORE);
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Attributes_Is_counting_semaphore
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* This function returns TRUE if the counting semaphore attribute is
|
||||
* enabled in the attribute_set and FALSE otherwise.
|
||||
*/
|
||||
|
||||
RTEMS_INLINE_ROUTINE boolean _Attributes_Is_counting_semaphore(
|
||||
rtems_attribute attribute_set
|
||||
)
|
||||
{
|
||||
return ((attribute_set & RTEMS_SEMAPHORE_CLASS) == RTEMS_COUNTING_SEMAPHORE);
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
@@ -156,23 +191,6 @@ RTEMS_INLINE_ROUTINE boolean _Attributes_Is_priority_ceiling(
|
||||
return ( attribute_set & RTEMS_PRIORITY_CEILING );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Attributes_Is_nesting_allowed
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* This function returns TRUE if the nesting allowed attribute
|
||||
* is enabled in the attribute_set and FALSE otherwise.
|
||||
*/
|
||||
|
||||
RTEMS_INLINE_ROUTINE boolean _Attributes_Is_nesting_allowed(
|
||||
rtems_attribute attribute_set
|
||||
)
|
||||
{
|
||||
return ( !(attribute_set & RTEMS_NO_NESTING_ALLOWED) );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Attributes_Is_system_task
|
||||
|
||||
@@ -68,7 +68,25 @@
|
||||
*/
|
||||
|
||||
#define _Attributes_Is_binary_semaphore( _attribute_set ) \
|
||||
( (_attribute_set) & RTEMS_BINARY_SEMAPHORE )
|
||||
(((_attribute_set) & RTEMS_SEMAPHORE_CLASS) == RTEMS_BINARY_SEMAPHORE)
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Attributes_Is_simple_binary_semaphore
|
||||
*
|
||||
*/
|
||||
|
||||
#define _Attributes_Is_simple_binary_semaphore( _attribute_set ) \
|
||||
(((_attribute_set) & RTEMS_SEMAPHORE_CLASS) == RTEMS_SIMPLE_BINARY_SEMAPHORE)
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Attributes_Is_counting_semaphore
|
||||
*
|
||||
*/
|
||||
|
||||
#define _Attributes_Is_counting_semaphore( _attribute_set ) \
|
||||
(((_attribute_set) & RTEMS_SEMAPHORE_CLASS) == RTEMS_COUNTING_SEMAPHORE)
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
@@ -88,15 +106,6 @@
|
||||
#define _Attributes_Is_priority_ceiling( _attribute_set ) \
|
||||
( (_attribute_set) & RTEMS_PRIORITY_CEILING )
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Attributes_Is_nesting_allowed
|
||||
*
|
||||
*/
|
||||
|
||||
#define _Attributes_Is_nesting_allowed( _attribute_set ) \
|
||||
( !((_attribute_set) & RTEMS_NO_NESTING_ALLOWED) )
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Attributes_Is_system_task
|
||||
|
||||
@@ -96,13 +96,15 @@ rtems_status_code rtems_semaphore_create(
|
||||
if ( _Attributes_Is_inherit_priority( attribute_set ) ||
|
||||
_Attributes_Is_priority_ceiling( attribute_set ) ) {
|
||||
|
||||
if ( ! ( _Attributes_Is_binary_semaphore( attribute_set ) &&
|
||||
if ( ! ( (_Attributes_Is_binary_semaphore( attribute_set ) ||
|
||||
_Attributes_Is_simple_binary_semaphore( attribute_set )) &&
|
||||
|
||||
_Attributes_Is_priority( attribute_set ) ) )
|
||||
return RTEMS_NOT_DEFINED;
|
||||
|
||||
}
|
||||
|
||||
if ( _Attributes_Is_binary_semaphore( attribute_set ) && ( count > 1 ) )
|
||||
if ( !_Attributes_Is_counting_semaphore( attribute_set ) && ( count > 1 ) )
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
_Thread_Disable_dispatch(); /* prevents deletion */
|
||||
@@ -126,7 +128,13 @@ rtems_status_code rtems_semaphore_create(
|
||||
|
||||
the_semaphore->attribute_set = attribute_set;
|
||||
|
||||
if ( _Attributes_Is_binary_semaphore( attribute_set ) ) {
|
||||
/*
|
||||
* If it is not a counting, semaphore, then it is either a
|
||||
* simple binary semaphore or a more powerful lmutex style binary
|
||||
* semaphore.
|
||||
*/
|
||||
|
||||
if ( !_Attributes_Is_counting_semaphore( attribute_set ) ) {
|
||||
if ( _Attributes_Is_inherit_priority( attribute_set ) )
|
||||
the_mutex_attributes.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
|
||||
else if ( _Attributes_Is_priority_ceiling( attribute_set ) )
|
||||
@@ -136,12 +144,24 @@ rtems_status_code rtems_semaphore_create(
|
||||
else
|
||||
the_mutex_attributes.discipline = CORE_MUTEX_DISCIPLINES_FIFO;
|
||||
|
||||
if ( _Attributes_Is_nesting_allowed( attribute_set ) )
|
||||
the_mutex_attributes.allow_nesting = TRUE;
|
||||
else
|
||||
the_mutex_attributes.allow_nesting = FALSE;
|
||||
|
||||
/* Add priority ceiling code here ????? */
|
||||
if ( _Attributes_Is_binary_semaphore( attribute_set ) ) {
|
||||
the_mutex_attributes.lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
|
||||
|
||||
switch ( the_mutex_attributes.discipline ) {
|
||||
case CORE_MUTEX_DISCIPLINES_FIFO:
|
||||
case CORE_MUTEX_DISCIPLINES_PRIORITY:
|
||||
the_mutex_attributes.only_owner_release = FALSE;
|
||||
break;
|
||||
case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
|
||||
case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
|
||||
the_mutex_attributes.only_owner_release = TRUE;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
the_mutex_attributes.lock_nesting_behavior = CORE_MUTEX_NESTING_BLOCKS;
|
||||
the_mutex_attributes.only_owner_release = FALSE;
|
||||
}
|
||||
|
||||
the_mutex_attributes.priority_ceiling = priority_ceiling;
|
||||
|
||||
@@ -161,8 +181,7 @@ rtems_status_code rtems_semaphore_create(
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if ( _Attributes_Is_priority( attribute_set ) )
|
||||
the_semaphore_attributes.discipline = CORE_SEMAPHORE_DISCIPLINES_PRIORITY;
|
||||
else
|
||||
@@ -178,7 +197,7 @@ rtems_status_code rtems_semaphore_create(
|
||||
* The following are just to make Purify happy.
|
||||
*/
|
||||
|
||||
the_mutex_attributes.allow_nesting = TRUE;
|
||||
the_mutex_attributes.lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
|
||||
the_mutex_attributes.priority_ceiling = PRIORITY_MINIMUM;
|
||||
|
||||
_CORE_semaphore_Initialize(
|
||||
|
||||
@@ -81,7 +81,7 @@ rtems_status_code rtems_semaphore_delete(
|
||||
return RTEMS_INVALID_ID;
|
||||
|
||||
case OBJECTS_LOCAL:
|
||||
if ( _Attributes_Is_binary_semaphore( the_semaphore->attribute_set) ) {
|
||||
if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) {
|
||||
if ( _CORE_mutex_Is_locked( &the_semaphore->Core_control.mutex ) ) {
|
||||
_Thread_Enable_dispatch();
|
||||
return RTEMS_RESOURCE_IN_USE;
|
||||
|
||||
@@ -77,7 +77,7 @@ rtems_status_code rtems_semaphore_flush(
|
||||
return RTEMS_INVALID_ID;
|
||||
|
||||
case OBJECTS_LOCAL:
|
||||
if ( _Attributes_Is_binary_semaphore(the_semaphore->attribute_set) ) {
|
||||
if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) {
|
||||
_CORE_mutex_Flush(
|
||||
&the_semaphore->Core_control.mutex,
|
||||
SEND_OBJECT_WAS_DELETED,
|
||||
|
||||
@@ -92,7 +92,7 @@ rtems_status_code rtems_semaphore_obtain(
|
||||
else
|
||||
wait = TRUE;
|
||||
|
||||
if ( _Attributes_Is_binary_semaphore( the_semaphore->attribute_set ) ) {
|
||||
if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) {
|
||||
_CORE_mutex_Seize(
|
||||
&the_semaphore->Core_control.mutex,
|
||||
id,
|
||||
|
||||
@@ -85,7 +85,7 @@ rtems_status_code rtems_semaphore_release(
|
||||
return RTEMS_INVALID_ID;
|
||||
|
||||
case OBJECTS_LOCAL:
|
||||
if ( _Attributes_Is_binary_semaphore( the_semaphore->attribute_set ) ) {
|
||||
if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) {
|
||||
mutex_status = _CORE_mutex_Surrender(
|
||||
&the_semaphore->Core_control.mutex,
|
||||
id,
|
||||
|
||||
@@ -62,6 +62,35 @@ typedef enum {
|
||||
CORE_MUTEX_STATUS_CEILING_VIOLATED
|
||||
} CORE_mutex_Status;
|
||||
|
||||
/*
|
||||
* Mutex lock nesting behavior
|
||||
*
|
||||
* CORE_MUTEX_NESTING_ACQUIRES:
|
||||
* This sequence has no blocking or errors:
|
||||
* lock(m)
|
||||
* lock(m)
|
||||
* unlock(m)
|
||||
* unlock(m)
|
||||
*
|
||||
* CORE_MUTEX_NESTING_IS_ERROR
|
||||
* This sequence returns an error at the indicated point:
|
||||
* lock(m)
|
||||
* lock(m) - already locked error
|
||||
* unlock(m)
|
||||
*
|
||||
* CORE_MUTEX_NESTING_BLOCKS
|
||||
* This sequence performs as indicated:
|
||||
* lock(m)
|
||||
* lock(m) - deadlocks or timeouts
|
||||
* unlock(m) - releases
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
CORE_MUTEX_NESTING_ACQUIRES,
|
||||
CORE_MUTEX_NESTING_IS_ERROR,
|
||||
CORE_MUTEX_NESTING_BLOCKS
|
||||
} CORE_mutex_Nesting_behaviors;
|
||||
|
||||
/*
|
||||
* Locked and unlocked values
|
||||
*/
|
||||
@@ -75,9 +104,10 @@ typedef enum {
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
boolean allow_nesting;
|
||||
CORE_mutex_Disciplines discipline;
|
||||
Priority_Control priority_ceiling;
|
||||
CORE_mutex_Nesting_behaviors lock_nesting_behavior;
|
||||
boolean only_owner_release;
|
||||
CORE_mutex_Disciplines discipline;
|
||||
Priority_Control priority_ceiling;
|
||||
} CORE_mutex_Attributes;
|
||||
|
||||
/*
|
||||
|
||||
@@ -53,7 +53,8 @@ typedef enum {
|
||||
INTERNAL_ERROR_OUT_OF_GLOBAL_OBJECTS,
|
||||
INTERNAL_ERROR_OUT_OF_PROXIES,
|
||||
INTERNAL_ERROR_INVALID_GLOBAL_ID,
|
||||
INTERNAL_ERROR_BAD_STACK_HOOK
|
||||
INTERNAL_ERROR_BAD_STACK_HOOK,
|
||||
INTERNAL_ERROR_BAD_ATTRIBUTES
|
||||
} Internal_errors_Core_list;
|
||||
|
||||
/*
|
||||
|
||||
@@ -101,23 +101,5 @@ RTEMS_INLINE_ROUTINE boolean _CORE_mutex_Is_priority_ceiling(
|
||||
return the_attribute->discipline == CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _CORE_mutex_Is_nesting_allowed
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* This routine returns TRUE if the mutex allows a task to obtain a
|
||||
* semaphore more than once and nest.
|
||||
*/
|
||||
|
||||
RTEMS_INLINE_ROUTINE boolean _CORE_mutex_Is_nesting_allowed(
|
||||
CORE_mutex_Attributes *the_attribute
|
||||
)
|
||||
{
|
||||
return the_attribute->allow_nesting == TRUE;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
/* end of include file */
|
||||
|
||||
@@ -63,14 +63,5 @@
|
||||
#define _CORE_mutex_Is_priority_ceiling( _the_attribute )\
|
||||
( (_the_attribute)->discipline == CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING )
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _CORE_mutex_Is_nesting_allowed
|
||||
*
|
||||
*/
|
||||
|
||||
#define _CORE_mutex_Is_nesting_allowed( _the_attribute ) \
|
||||
( (_the_attribute)->allow_nesting == TRUE )
|
||||
|
||||
#endif
|
||||
/* end of include file */
|
||||
|
||||
@@ -55,7 +55,18 @@ void _CORE_mutex_Initialize(
|
||||
*/
|
||||
|
||||
the_mutex->Attributes = *the_mutex_attributes;
|
||||
the_mutex->lock = initial_lock;
|
||||
the_mutex->lock = initial_lock;
|
||||
|
||||
#if 0
|
||||
if ( !the_mutex_attributes->only_owner_release &&
|
||||
the_mutex_attributes->nesting_allowed ) {
|
||||
_Internal_error_Occurred(
|
||||
INTERNAL_ERROR_CORE,
|
||||
TRUE,
|
||||
INTERNAL_ERROR_BAD_ATTRIBUTES
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( initial_lock == CORE_MUTEX_LOCKED ) {
|
||||
the_mutex->nest_count = 1;
|
||||
|
||||
@@ -94,15 +94,19 @@ void _CORE_mutex_Seize(
|
||||
return;
|
||||
}
|
||||
|
||||
if ( _Objects_Are_ids_equal(
|
||||
_Thread_Executing->Object.id, the_mutex->holder_id ) ) {
|
||||
if ( _CORE_mutex_Is_nesting_allowed( &the_mutex->Attributes ) )
|
||||
the_mutex->nest_count++;
|
||||
else
|
||||
executing->Wait.return_code = CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
|
||||
|
||||
_ISR_Enable( level );
|
||||
return;
|
||||
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;
|
||||
case CORE_MUTEX_NESTING_IS_ERROR:
|
||||
executing->Wait.return_code = CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
|
||||
_ISR_Enable( level );
|
||||
return;
|
||||
case CORE_MUTEX_NESTING_BLOCKS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !wait ) {
|
||||
|
||||
@@ -49,9 +49,9 @@ CORE_mutex_Status _CORE_mutex_Surrender(
|
||||
)
|
||||
{
|
||||
Thread_Control *the_thread;
|
||||
Thread_Control *executing;
|
||||
Thread_Control *holder;
|
||||
|
||||
executing = _Thread_Executing;
|
||||
holder = the_mutex->holder;
|
||||
|
||||
/*
|
||||
* The following code allows a thread (or ISR) other than the thread
|
||||
@@ -61,20 +61,9 @@ CORE_mutex_Status _CORE_mutex_Surrender(
|
||||
* must be released by the thread which acquired them.
|
||||
*/
|
||||
|
||||
if ( the_mutex->Attributes.allow_nesting ) {
|
||||
if ( !_Objects_Are_ids_equal(
|
||||
_Thread_Executing->Object.id, the_mutex->holder_id ) ) {
|
||||
|
||||
switch ( the_mutex->Attributes.discipline ) {
|
||||
case CORE_MUTEX_DISCIPLINES_FIFO:
|
||||
case CORE_MUTEX_DISCIPLINES_PRIORITY:
|
||||
break;
|
||||
case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
|
||||
case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
|
||||
return( CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( the_mutex->Attributes.only_owner_release ) {
|
||||
if ( !_Thread_Is_executing( holder ) )
|
||||
return( CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE );
|
||||
}
|
||||
|
||||
/* XXX already unlocked -- not right status */
|
||||
@@ -85,9 +74,15 @@ CORE_mutex_Status _CORE_mutex_Surrender(
|
||||
the_mutex->nest_count--;
|
||||
|
||||
if ( the_mutex->nest_count != 0 ) {
|
||||
if ( the_mutex->Attributes.allow_nesting )
|
||||
return( CORE_MUTEX_STATUS_SUCCESSFUL );
|
||||
return( CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED );
|
||||
switch ( the_mutex->Attributes.lock_nesting_behavior ) {
|
||||
case CORE_MUTEX_NESTING_ACQUIRES:
|
||||
return CORE_MUTEX_STATUS_SUCCESSFUL;
|
||||
case CORE_MUTEX_NESTING_IS_ERROR:
|
||||
/* should never occur */
|
||||
return CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
|
||||
case CORE_MUTEX_NESTING_BLOCKS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_Thread_Executing->resource_count--;
|
||||
@@ -106,9 +101,9 @@ CORE_mutex_Status _CORE_mutex_Surrender(
|
||||
break;
|
||||
case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
|
||||
case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
|
||||
if ( executing->resource_count == 0 &&
|
||||
executing->real_priority != executing->current_priority ) {
|
||||
_Thread_Change_priority( executing, executing->real_priority, TRUE );
|
||||
if ( holder->resource_count == 0 &&
|
||||
holder->real_priority != holder->current_priority ) {
|
||||
_Thread_Change_priority( holder, holder->real_priority, TRUE );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -144,7 +144,11 @@ int pthread_mutex_init(
|
||||
|
||||
the_mutex_attr = &the_mutex->Mutex.Attributes;
|
||||
|
||||
the_mutex_attr->allow_nesting = the_attr->recursive;
|
||||
if ( the_attr->recursive )
|
||||
the_mutex_attr->lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
|
||||
else
|
||||
the_mutex_attr->lock_nesting_behavior = CORE_MUTEX_NESTING_IS_ERROR;
|
||||
the_mutex_attr->only_owner_release = TRUE;
|
||||
the_mutex_attr->priority_ceiling =
|
||||
_POSIX_Priority_To_core( the_attr->prio_ceiling );
|
||||
the_mutex_attr->discipline = the_discipline;
|
||||
|
||||
@@ -37,17 +37,16 @@ typedef unsigned32 rtems_attribute;
|
||||
#define RTEMS_FIFO 0x00000000 /* process RTEMS_FIFO */
|
||||
#define RTEMS_PRIORITY 0x00000004 /* process by priority */
|
||||
|
||||
#define RTEMS_COUNTING_SEMAPHORE 0x00000000
|
||||
#define RTEMS_BINARY_SEMAPHORE 0x00000010
|
||||
#define RTEMS_SEMAPHORE_CLASS 0x00000030 /* mask */
|
||||
#define RTEMS_COUNTING_SEMAPHORE 0x00000000
|
||||
#define RTEMS_BINARY_SEMAPHORE 0x00000010
|
||||
#define RTEMS_SIMPLE_BINARY_SEMAPHORE 0x00000020
|
||||
|
||||
#define RTEMS_NO_INHERIT_PRIORITY 0x00000000
|
||||
#define RTEMS_INHERIT_PRIORITY 0x00000020
|
||||
#define RTEMS_INHERIT_PRIORITY 0x00000040
|
||||
|
||||
#define RTEMS_NO_PRIORITY_CEILING 0x00000000
|
||||
#define RTEMS_PRIORITY_CEILING 0x00000040
|
||||
|
||||
#define RTEMS_NESTING_ALLOWED 0x00000000
|
||||
#define RTEMS_NO_NESTING_ALLOWED 0x00000080
|
||||
#define RTEMS_PRIORITY_CEILING 0x00000080
|
||||
|
||||
#define RTEMS_APPLICATION_TASK 0x00000000
|
||||
#define RTEMS_SYSTEM_TASK 0x00000100
|
||||
|
||||
@@ -119,7 +119,42 @@ RTEMS_INLINE_ROUTINE boolean _Attributes_Is_binary_semaphore(
|
||||
rtems_attribute attribute_set
|
||||
)
|
||||
{
|
||||
return ( attribute_set & RTEMS_BINARY_SEMAPHORE );
|
||||
return ((attribute_set & RTEMS_SEMAPHORE_CLASS) == RTEMS_BINARY_SEMAPHORE);
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Attributes_Is_simple_binary_semaphore
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* This function returns TRUE if the simple binary semaphore attribute is
|
||||
* enabled in the attribute_set and FALSE otherwise.
|
||||
*/
|
||||
|
||||
RTEMS_INLINE_ROUTINE boolean _Attributes_Is_simple_binary_semaphore(
|
||||
rtems_attribute attribute_set
|
||||
)
|
||||
{
|
||||
return
|
||||
((attribute_set & RTEMS_SEMAPHORE_CLASS) == RTEMS_SIMPLE_BINARY_SEMAPHORE);
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Attributes_Is_counting_semaphore
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* This function returns TRUE if the counting semaphore attribute is
|
||||
* enabled in the attribute_set and FALSE otherwise.
|
||||
*/
|
||||
|
||||
RTEMS_INLINE_ROUTINE boolean _Attributes_Is_counting_semaphore(
|
||||
rtems_attribute attribute_set
|
||||
)
|
||||
{
|
||||
return ((attribute_set & RTEMS_SEMAPHORE_CLASS) == RTEMS_COUNTING_SEMAPHORE);
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
@@ -156,23 +191,6 @@ RTEMS_INLINE_ROUTINE boolean _Attributes_Is_priority_ceiling(
|
||||
return ( attribute_set & RTEMS_PRIORITY_CEILING );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Attributes_Is_nesting_allowed
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* This function returns TRUE if the nesting allowed attribute
|
||||
* is enabled in the attribute_set and FALSE otherwise.
|
||||
*/
|
||||
|
||||
RTEMS_INLINE_ROUTINE boolean _Attributes_Is_nesting_allowed(
|
||||
rtems_attribute attribute_set
|
||||
)
|
||||
{
|
||||
return ( !(attribute_set & RTEMS_NO_NESTING_ALLOWED) );
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Attributes_Is_system_task
|
||||
|
||||
@@ -68,7 +68,25 @@
|
||||
*/
|
||||
|
||||
#define _Attributes_Is_binary_semaphore( _attribute_set ) \
|
||||
( (_attribute_set) & RTEMS_BINARY_SEMAPHORE )
|
||||
(((_attribute_set) & RTEMS_SEMAPHORE_CLASS) == RTEMS_BINARY_SEMAPHORE)
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Attributes_Is_simple_binary_semaphore
|
||||
*
|
||||
*/
|
||||
|
||||
#define _Attributes_Is_simple_binary_semaphore( _attribute_set ) \
|
||||
(((_attribute_set) & RTEMS_SEMAPHORE_CLASS) == RTEMS_SIMPLE_BINARY_SEMAPHORE)
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Attributes_Is_counting_semaphore
|
||||
*
|
||||
*/
|
||||
|
||||
#define _Attributes_Is_counting_semaphore( _attribute_set ) \
|
||||
(((_attribute_set) & RTEMS_SEMAPHORE_CLASS) == RTEMS_COUNTING_SEMAPHORE)
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
@@ -88,15 +106,6 @@
|
||||
#define _Attributes_Is_priority_ceiling( _attribute_set ) \
|
||||
( (_attribute_set) & RTEMS_PRIORITY_CEILING )
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Attributes_Is_nesting_allowed
|
||||
*
|
||||
*/
|
||||
|
||||
#define _Attributes_Is_nesting_allowed( _attribute_set ) \
|
||||
( !((_attribute_set) & RTEMS_NO_NESTING_ALLOWED) )
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _Attributes_Is_system_task
|
||||
|
||||
@@ -96,13 +96,15 @@ rtems_status_code rtems_semaphore_create(
|
||||
if ( _Attributes_Is_inherit_priority( attribute_set ) ||
|
||||
_Attributes_Is_priority_ceiling( attribute_set ) ) {
|
||||
|
||||
if ( ! ( _Attributes_Is_binary_semaphore( attribute_set ) &&
|
||||
if ( ! ( (_Attributes_Is_binary_semaphore( attribute_set ) ||
|
||||
_Attributes_Is_simple_binary_semaphore( attribute_set )) &&
|
||||
|
||||
_Attributes_Is_priority( attribute_set ) ) )
|
||||
return RTEMS_NOT_DEFINED;
|
||||
|
||||
}
|
||||
|
||||
if ( _Attributes_Is_binary_semaphore( attribute_set ) && ( count > 1 ) )
|
||||
if ( !_Attributes_Is_counting_semaphore( attribute_set ) && ( count > 1 ) )
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
|
||||
_Thread_Disable_dispatch(); /* prevents deletion */
|
||||
@@ -126,7 +128,13 @@ rtems_status_code rtems_semaphore_create(
|
||||
|
||||
the_semaphore->attribute_set = attribute_set;
|
||||
|
||||
if ( _Attributes_Is_binary_semaphore( attribute_set ) ) {
|
||||
/*
|
||||
* If it is not a counting, semaphore, then it is either a
|
||||
* simple binary semaphore or a more powerful lmutex style binary
|
||||
* semaphore.
|
||||
*/
|
||||
|
||||
if ( !_Attributes_Is_counting_semaphore( attribute_set ) ) {
|
||||
if ( _Attributes_Is_inherit_priority( attribute_set ) )
|
||||
the_mutex_attributes.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
|
||||
else if ( _Attributes_Is_priority_ceiling( attribute_set ) )
|
||||
@@ -136,12 +144,24 @@ rtems_status_code rtems_semaphore_create(
|
||||
else
|
||||
the_mutex_attributes.discipline = CORE_MUTEX_DISCIPLINES_FIFO;
|
||||
|
||||
if ( _Attributes_Is_nesting_allowed( attribute_set ) )
|
||||
the_mutex_attributes.allow_nesting = TRUE;
|
||||
else
|
||||
the_mutex_attributes.allow_nesting = FALSE;
|
||||
|
||||
/* Add priority ceiling code here ????? */
|
||||
if ( _Attributes_Is_binary_semaphore( attribute_set ) ) {
|
||||
the_mutex_attributes.lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
|
||||
|
||||
switch ( the_mutex_attributes.discipline ) {
|
||||
case CORE_MUTEX_DISCIPLINES_FIFO:
|
||||
case CORE_MUTEX_DISCIPLINES_PRIORITY:
|
||||
the_mutex_attributes.only_owner_release = FALSE;
|
||||
break;
|
||||
case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
|
||||
case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
|
||||
the_mutex_attributes.only_owner_release = TRUE;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
the_mutex_attributes.lock_nesting_behavior = CORE_MUTEX_NESTING_BLOCKS;
|
||||
the_mutex_attributes.only_owner_release = FALSE;
|
||||
}
|
||||
|
||||
the_mutex_attributes.priority_ceiling = priority_ceiling;
|
||||
|
||||
@@ -161,8 +181,7 @@ rtems_status_code rtems_semaphore_create(
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if ( _Attributes_Is_priority( attribute_set ) )
|
||||
the_semaphore_attributes.discipline = CORE_SEMAPHORE_DISCIPLINES_PRIORITY;
|
||||
else
|
||||
@@ -178,7 +197,7 @@ rtems_status_code rtems_semaphore_create(
|
||||
* The following are just to make Purify happy.
|
||||
*/
|
||||
|
||||
the_mutex_attributes.allow_nesting = TRUE;
|
||||
the_mutex_attributes.lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
|
||||
the_mutex_attributes.priority_ceiling = PRIORITY_MINIMUM;
|
||||
|
||||
_CORE_semaphore_Initialize(
|
||||
|
||||
@@ -81,7 +81,7 @@ rtems_status_code rtems_semaphore_delete(
|
||||
return RTEMS_INVALID_ID;
|
||||
|
||||
case OBJECTS_LOCAL:
|
||||
if ( _Attributes_Is_binary_semaphore( the_semaphore->attribute_set) ) {
|
||||
if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) {
|
||||
if ( _CORE_mutex_Is_locked( &the_semaphore->Core_control.mutex ) ) {
|
||||
_Thread_Enable_dispatch();
|
||||
return RTEMS_RESOURCE_IN_USE;
|
||||
|
||||
@@ -77,7 +77,7 @@ rtems_status_code rtems_semaphore_flush(
|
||||
return RTEMS_INVALID_ID;
|
||||
|
||||
case OBJECTS_LOCAL:
|
||||
if ( _Attributes_Is_binary_semaphore(the_semaphore->attribute_set) ) {
|
||||
if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) {
|
||||
_CORE_mutex_Flush(
|
||||
&the_semaphore->Core_control.mutex,
|
||||
SEND_OBJECT_WAS_DELETED,
|
||||
|
||||
@@ -92,7 +92,7 @@ rtems_status_code rtems_semaphore_obtain(
|
||||
else
|
||||
wait = TRUE;
|
||||
|
||||
if ( _Attributes_Is_binary_semaphore( the_semaphore->attribute_set ) ) {
|
||||
if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) {
|
||||
_CORE_mutex_Seize(
|
||||
&the_semaphore->Core_control.mutex,
|
||||
id,
|
||||
|
||||
@@ -85,7 +85,7 @@ rtems_status_code rtems_semaphore_release(
|
||||
return RTEMS_INVALID_ID;
|
||||
|
||||
case OBJECTS_LOCAL:
|
||||
if ( _Attributes_Is_binary_semaphore( the_semaphore->attribute_set ) ) {
|
||||
if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) {
|
||||
mutex_status = _CORE_mutex_Surrender(
|
||||
&the_semaphore->Core_control.mutex,
|
||||
id,
|
||||
|
||||
@@ -62,6 +62,35 @@ typedef enum {
|
||||
CORE_MUTEX_STATUS_CEILING_VIOLATED
|
||||
} CORE_mutex_Status;
|
||||
|
||||
/*
|
||||
* Mutex lock nesting behavior
|
||||
*
|
||||
* CORE_MUTEX_NESTING_ACQUIRES:
|
||||
* This sequence has no blocking or errors:
|
||||
* lock(m)
|
||||
* lock(m)
|
||||
* unlock(m)
|
||||
* unlock(m)
|
||||
*
|
||||
* CORE_MUTEX_NESTING_IS_ERROR
|
||||
* This sequence returns an error at the indicated point:
|
||||
* lock(m)
|
||||
* lock(m) - already locked error
|
||||
* unlock(m)
|
||||
*
|
||||
* CORE_MUTEX_NESTING_BLOCKS
|
||||
* This sequence performs as indicated:
|
||||
* lock(m)
|
||||
* lock(m) - deadlocks or timeouts
|
||||
* unlock(m) - releases
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
CORE_MUTEX_NESTING_ACQUIRES,
|
||||
CORE_MUTEX_NESTING_IS_ERROR,
|
||||
CORE_MUTEX_NESTING_BLOCKS
|
||||
} CORE_mutex_Nesting_behaviors;
|
||||
|
||||
/*
|
||||
* Locked and unlocked values
|
||||
*/
|
||||
@@ -75,9 +104,10 @@ typedef enum {
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
boolean allow_nesting;
|
||||
CORE_mutex_Disciplines discipline;
|
||||
Priority_Control priority_ceiling;
|
||||
CORE_mutex_Nesting_behaviors lock_nesting_behavior;
|
||||
boolean only_owner_release;
|
||||
CORE_mutex_Disciplines discipline;
|
||||
Priority_Control priority_ceiling;
|
||||
} CORE_mutex_Attributes;
|
||||
|
||||
/*
|
||||
|
||||
@@ -53,7 +53,8 @@ typedef enum {
|
||||
INTERNAL_ERROR_OUT_OF_GLOBAL_OBJECTS,
|
||||
INTERNAL_ERROR_OUT_OF_PROXIES,
|
||||
INTERNAL_ERROR_INVALID_GLOBAL_ID,
|
||||
INTERNAL_ERROR_BAD_STACK_HOOK
|
||||
INTERNAL_ERROR_BAD_STACK_HOOK,
|
||||
INTERNAL_ERROR_BAD_ATTRIBUTES
|
||||
} Internal_errors_Core_list;
|
||||
|
||||
/*
|
||||
|
||||
@@ -101,23 +101,5 @@ RTEMS_INLINE_ROUTINE boolean _CORE_mutex_Is_priority_ceiling(
|
||||
return the_attribute->discipline == CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _CORE_mutex_Is_nesting_allowed
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* This routine returns TRUE if the mutex allows a task to obtain a
|
||||
* semaphore more than once and nest.
|
||||
*/
|
||||
|
||||
RTEMS_INLINE_ROUTINE boolean _CORE_mutex_Is_nesting_allowed(
|
||||
CORE_mutex_Attributes *the_attribute
|
||||
)
|
||||
{
|
||||
return the_attribute->allow_nesting == TRUE;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
/* end of include file */
|
||||
|
||||
@@ -63,14 +63,5 @@
|
||||
#define _CORE_mutex_Is_priority_ceiling( _the_attribute )\
|
||||
( (_the_attribute)->discipline == CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING )
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* _CORE_mutex_Is_nesting_allowed
|
||||
*
|
||||
*/
|
||||
|
||||
#define _CORE_mutex_Is_nesting_allowed( _the_attribute ) \
|
||||
( (_the_attribute)->allow_nesting == TRUE )
|
||||
|
||||
#endif
|
||||
/* end of include file */
|
||||
|
||||
@@ -55,7 +55,18 @@ void _CORE_mutex_Initialize(
|
||||
*/
|
||||
|
||||
the_mutex->Attributes = *the_mutex_attributes;
|
||||
the_mutex->lock = initial_lock;
|
||||
the_mutex->lock = initial_lock;
|
||||
|
||||
#if 0
|
||||
if ( !the_mutex_attributes->only_owner_release &&
|
||||
the_mutex_attributes->nesting_allowed ) {
|
||||
_Internal_error_Occurred(
|
||||
INTERNAL_ERROR_CORE,
|
||||
TRUE,
|
||||
INTERNAL_ERROR_BAD_ATTRIBUTES
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( initial_lock == CORE_MUTEX_LOCKED ) {
|
||||
the_mutex->nest_count = 1;
|
||||
|
||||
@@ -94,15 +94,19 @@ void _CORE_mutex_Seize(
|
||||
return;
|
||||
}
|
||||
|
||||
if ( _Objects_Are_ids_equal(
|
||||
_Thread_Executing->Object.id, the_mutex->holder_id ) ) {
|
||||
if ( _CORE_mutex_Is_nesting_allowed( &the_mutex->Attributes ) )
|
||||
the_mutex->nest_count++;
|
||||
else
|
||||
executing->Wait.return_code = CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
|
||||
|
||||
_ISR_Enable( level );
|
||||
return;
|
||||
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;
|
||||
case CORE_MUTEX_NESTING_IS_ERROR:
|
||||
executing->Wait.return_code = CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
|
||||
_ISR_Enable( level );
|
||||
return;
|
||||
case CORE_MUTEX_NESTING_BLOCKS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !wait ) {
|
||||
|
||||
@@ -49,9 +49,9 @@ CORE_mutex_Status _CORE_mutex_Surrender(
|
||||
)
|
||||
{
|
||||
Thread_Control *the_thread;
|
||||
Thread_Control *executing;
|
||||
Thread_Control *holder;
|
||||
|
||||
executing = _Thread_Executing;
|
||||
holder = the_mutex->holder;
|
||||
|
||||
/*
|
||||
* The following code allows a thread (or ISR) other than the thread
|
||||
@@ -61,20 +61,9 @@ CORE_mutex_Status _CORE_mutex_Surrender(
|
||||
* must be released by the thread which acquired them.
|
||||
*/
|
||||
|
||||
if ( the_mutex->Attributes.allow_nesting ) {
|
||||
if ( !_Objects_Are_ids_equal(
|
||||
_Thread_Executing->Object.id, the_mutex->holder_id ) ) {
|
||||
|
||||
switch ( the_mutex->Attributes.discipline ) {
|
||||
case CORE_MUTEX_DISCIPLINES_FIFO:
|
||||
case CORE_MUTEX_DISCIPLINES_PRIORITY:
|
||||
break;
|
||||
case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
|
||||
case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
|
||||
return( CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( the_mutex->Attributes.only_owner_release ) {
|
||||
if ( !_Thread_Is_executing( holder ) )
|
||||
return( CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE );
|
||||
}
|
||||
|
||||
/* XXX already unlocked -- not right status */
|
||||
@@ -85,9 +74,15 @@ CORE_mutex_Status _CORE_mutex_Surrender(
|
||||
the_mutex->nest_count--;
|
||||
|
||||
if ( the_mutex->nest_count != 0 ) {
|
||||
if ( the_mutex->Attributes.allow_nesting )
|
||||
return( CORE_MUTEX_STATUS_SUCCESSFUL );
|
||||
return( CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED );
|
||||
switch ( the_mutex->Attributes.lock_nesting_behavior ) {
|
||||
case CORE_MUTEX_NESTING_ACQUIRES:
|
||||
return CORE_MUTEX_STATUS_SUCCESSFUL;
|
||||
case CORE_MUTEX_NESTING_IS_ERROR:
|
||||
/* should never occur */
|
||||
return CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
|
||||
case CORE_MUTEX_NESTING_BLOCKS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_Thread_Executing->resource_count--;
|
||||
@@ -106,9 +101,9 @@ CORE_mutex_Status _CORE_mutex_Surrender(
|
||||
break;
|
||||
case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
|
||||
case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
|
||||
if ( executing->resource_count == 0 &&
|
||||
executing->real_priority != executing->current_priority ) {
|
||||
_Thread_Change_priority( executing, executing->real_priority, TRUE );
|
||||
if ( holder->resource_count == 0 &&
|
||||
holder->real_priority != holder->current_priority ) {
|
||||
_Thread_Change_priority( holder, holder->real_priority, TRUE );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user