score: Fine grained locking for semaphores

Update #2273.
This commit is contained in:
Sebastian Huber
2015-05-01 20:52:51 +02:00
parent cc18d7bec7
commit e76c517d07
7 changed files with 75 additions and 34 deletions

View File

@@ -89,6 +89,20 @@ RTEMS_INLINE_ROUTINE POSIX_Semaphore_Control *_POSIX_Semaphore_Get (
_Objects_Get( &_POSIX_Semaphore_Information, (Objects_Id)*id, location );
}
RTEMS_INLINE_ROUTINE POSIX_Semaphore_Control *
_POSIX_Semaphore_Get_interrupt_disable(
sem_t *id,
Objects_Locations *location,
ISR_lock_Context *lock_context
)
{
return (POSIX_Semaphore_Control *) _Objects_Get_isr_disable(
&_POSIX_Semaphore_Information,
(Objects_Id)*id,
location,
lock_context
);
}
/**
* @brief POSIX Semaphore Create Support

View File

@@ -37,8 +37,13 @@ int sem_post(
{
POSIX_Semaphore_Control *the_semaphore;
Objects_Locations location;
ISR_lock_Context lock_context;
the_semaphore = _POSIX_Semaphore_Get( sem, &location );
the_semaphore = _POSIX_Semaphore_Get_interrupt_disable(
sem,
&location,
&lock_context
);
switch ( location ) {
case OBJECTS_LOCAL:
@@ -46,12 +51,12 @@ int sem_post(
&the_semaphore->Semaphore,
the_semaphore->Object.id,
#if defined(RTEMS_MULTIPROCESSING)
NULL /* POSIX Semaphores are local only */
NULL, /* POSIX Semaphores are local only */
#else
NULL
NULL,
#endif
&lock_context
);
_Objects_Put( &the_semaphore->Object );
return 0;
#if defined(RTEMS_MULTIPROCESSING)

View File

@@ -56,10 +56,10 @@ rtems_status_code rtems_semaphore_obtain(
attribute_set = the_semaphore->attribute_set;
wait = !_Options_Is_no_wait( option_set );
#if defined(RTEMS_SMP)
_Thread_Disable_dispatch();
if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) ) {
MRSP_Status mrsp_status;
_Thread_Disable_dispatch();
_ISR_lock_ISR_enable( &lock_context );
mrsp_status = _MRSP_Obtain(
&the_semaphore->Core_control.mrsp,
@@ -73,6 +73,9 @@ rtems_status_code rtems_semaphore_obtain(
} else
#endif
if ( !_Attributes_Is_counting_semaphore( attribute_set ) ) {
#if defined(RTEMS_SMP)
_Thread_Disable_dispatch();
#endif
_CORE_mutex_Seize(
&the_semaphore->Core_control.mutex,
executing,
@@ -98,10 +101,6 @@ rtems_status_code rtems_semaphore_obtain(
timeout,
&lock_context
);
#if defined(RTEMS_SMP)
_Thread_Enable_dispatch();
#endif
_Objects_Put_for_get_isr_disable( &the_semaphore->Object );
return _Semaphore_Translate_core_semaphore_return_code(
executing->Wait.return_code );

View File

@@ -62,37 +62,46 @@ rtems_status_code rtems_semaphore_release(
CORE_mutex_Status mutex_status;
CORE_semaphore_Status semaphore_status;
rtems_attribute attribute_set;
ISR_lock_Context lock_context;
the_semaphore = _Semaphore_Get( id, &location );
the_semaphore = _Semaphore_Get_interrupt_disable(
id,
&location,
&lock_context
);
switch ( location ) {
case OBJECTS_LOCAL:
attribute_set = the_semaphore->attribute_set;
#if defined(RTEMS_SMP)
if ( _Attributes_Is_multiprocessor_resource_sharing( attribute_set ) ) {
_Thread_Disable_dispatch();
_ISR_lock_ISR_enable( &lock_context );
MRSP_Status mrsp_status = _MRSP_Release(
&the_semaphore->Core_control.mrsp,
_Thread_Get_executing()
);
_Objects_Put( &the_semaphore->Object );
_Thread_Enable_dispatch();
return _Semaphore_Translate_MRSP_status_code( mrsp_status );
} else
#endif
if ( !_Attributes_Is_counting_semaphore( attribute_set ) ) {
_Thread_Disable_dispatch();
_ISR_lock_ISR_enable( &lock_context );
mutex_status = _CORE_mutex_Surrender(
&the_semaphore->Core_control.mutex,
id,
MUTEX_MP_SUPPORT
);
_Objects_Put( &the_semaphore->Object );
_Thread_Enable_dispatch();
return _Semaphore_Translate_core_mutex_return_code( mutex_status );
} else {
semaphore_status = _CORE_semaphore_Surrender(
&the_semaphore->Core_control.semaphore,
id,
MUTEX_MP_SUPPORT
MUTEX_MP_SUPPORT,
&lock_context
);
_Objects_Put( &the_semaphore->Object );
return
_Semaphore_Translate_core_semaphore_return_code( semaphore_status );
}

View File

@@ -141,13 +141,16 @@ RTEMS_INLINE_ROUTINE void _CORE_semaphore_Destroy(
* with this instance of a SuperCore Semaphore
* @param[in] api_semaphore_mp_support is the routine to invoke if the
* thread unblocked is remote
* @param[in] lock_context is a temporary variable used to contain the ISR
* disable level cookie
*
* @retval an indication of whether the routine succeeded or failed
*/
CORE_semaphore_Status _CORE_semaphore_Surrender(
CORE_semaphore_Control *the_semaphore,
Objects_Id id,
CORE_semaphore_API_mp_support_callout api_semaphore_mp_support
CORE_semaphore_API_mp_support_callout api_semaphore_mp_support,
ISR_lock_Context *lock_context
);
/**
@@ -228,21 +231,20 @@ RTEMS_INLINE_ROUTINE void _CORE_semaphore_Seize_isr_disable(
/* disabled when you get here */
executing->Wait.return_code = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
_Thread_queue_Acquire_critical( &the_semaphore->Wait_queue, lock_context );
if ( the_semaphore->count != 0 ) {
the_semaphore->count -= 1;
_ISR_lock_ISR_enable( lock_context );
_Thread_queue_Release( &the_semaphore->Wait_queue, lock_context );
return;
}
if ( !wait ) {
_ISR_lock_ISR_enable( lock_context );
_Thread_queue_Release( &the_semaphore->Wait_queue, lock_context );
executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
return;
}
_Thread_Disable_dispatch();
executing->Wait.id = id;
_Thread_queue_Acquire_critical( &the_semaphore->Wait_queue, lock_context );
_Thread_queue_Enqueue_critical(
&the_semaphore->Wait_queue,
executing,
@@ -251,7 +253,6 @@ RTEMS_INLINE_ROUTINE void _CORE_semaphore_Seize_isr_disable(
CORE_SEMAPHORE_TIMEOUT,
lock_context
);
_Thread_Enable_dispatch();
}
/** @} */

View File

@@ -20,34 +20,46 @@
#endif
#include <rtems/score/coresemimpl.h>
#include <rtems/score/objectimpl.h>
CORE_semaphore_Status _CORE_semaphore_Surrender(
CORE_semaphore_Control *the_semaphore,
Objects_Id id,
CORE_semaphore_API_mp_support_callout api_semaphore_mp_support
CORE_semaphore_API_mp_support_callout api_semaphore_mp_support,
ISR_lock_Context *lock_context
)
{
Thread_Control *the_thread;
ISR_Level level;
CORE_semaphore_Status status;
status = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
if ( (the_thread = _Thread_queue_Dequeue(&the_semaphore->Wait_queue)) ) {
_Thread_queue_Acquire_critical( &the_semaphore->Wait_queue, lock_context );
the_thread = _Thread_queue_First_locked( &the_semaphore->Wait_queue );
if ( the_thread != NULL ) {
#if defined(RTEMS_MULTIPROCESSING)
_Thread_Dispatch_disable();
#endif
_Thread_queue_Extract_critical(
&the_semaphore->Wait_queue,
the_thread,
lock_context
);
#if defined(RTEMS_MULTIPROCESSING)
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
(*api_semaphore_mp_support) ( the_thread, id );
#endif
_Thread_Dispatch_enable( _Per_CPU_Get() );
#endif
} else {
_ISR_Disable( level );
if ( the_semaphore->count < the_semaphore->Attributes.maximum_count )
the_semaphore->count += 1;
else
status = CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED;
_ISR_Enable( level );
if ( the_semaphore->count < the_semaphore->Attributes.maximum_count )
the_semaphore->count += 1;
else
status = CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED;
_Thread_queue_Release( &the_semaphore->Wait_queue, lock_context );
}
return status;

View File

@@ -329,9 +329,10 @@ Thread _MPCI_Receive_server(
void _MPCI_Announce ( void )
{
_Thread_Disable_dispatch();
(void) _CORE_semaphore_Surrender( &_MPCI_Semaphore, 0, 0 );
_Thread_Enable_dispatch();
ISR_lock_Context lock_context;
_ISR_lock_ISR_disable( &lock_context );
(void) _CORE_semaphore_Surrender( &_MPCI_Semaphore, 0, 0, &lock_context );
}
void _MPCI_Internal_packets_Send_process_packet (