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:
Joel Sherrill
2000-01-05 22:19:21 +00:00
parent 5283cc823d
commit 5870ac5567
32 changed files with 354 additions and 228 deletions
+5 -1
View File
@@ -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;
+6 -7
View File
@@ -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
+36 -18
View File
@@ -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
+19 -10
View File
@@ -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
+30 -11
View File
@@ -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(
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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,
+1 -1
View File
@@ -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,
+1 -1
View File
@@ -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 */
+12 -1
View 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;
+13 -9
View File
@@ -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 ) {
+17 -22
View File
@@ -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;
}
+5 -1
View File
@@ -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;
+6 -7
View File
@@ -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
+36 -18
View File
@@ -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
+19 -10
View File
@@ -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
+30 -11
View File
@@ -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(
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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,
+1 -1
View File
@@ -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,
+1 -1
View File
@@ -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,
+33 -3
View File
@@ -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;
/*
+2 -1
View File
@@ -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 */
+12 -1
View 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;
+13 -9
View File
@@ -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 ) {
+17 -22
View File
@@ -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;
}