From cc18d7bec7b3c5515cb9e6cd9771d4b94309b3bd Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 30 Apr 2015 13:12:54 +0200 Subject: score: Fine grained locking for message queues Aggregate several critical sections into a bigger one. Sending and receiving messages is now protected by an ISR lock. Thread dispatching is only disabled in case a blocking operation is necessary. The message copy procedure is done inside the critical section (interrupts disabled). Thus this change may have a negative impact on the interrupt latency in case very large messages are transferred. Update #2273. --- cpukit/score/src/coremsgseize.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'cpukit/score/src/coremsgseize.c') diff --git a/cpukit/score/src/coremsgseize.c b/cpukit/score/src/coremsgseize.c index ec6cf8c52e..0d1c36fe47 100644 --- a/cpukit/score/src/coremsgseize.c +++ b/cpukit/score/src/coremsgseize.c @@ -33,18 +33,17 @@ void _CORE_message_queue_Seize( void *buffer, size_t *size_p, bool wait, - Watchdog_Interval timeout + Watchdog_Interval timeout, + ISR_lock_Context *lock_context ) { - ISR_lock_Context lock_context; CORE_message_queue_Buffer_control *the_message; executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL; - _Thread_queue_Acquire( &the_message_queue->Wait_queue, &lock_context ); + _CORE_message_queue_Acquire_critical( the_message_queue, lock_context ); the_message = _CORE_message_queue_Get_pending_message( the_message_queue ); if ( the_message != NULL ) { the_message_queue->number_of_pending_messages -= 1; - _Thread_queue_Release( &the_message_queue->Wait_queue, &lock_context ); *size_p = the_message->Contents.size; executing->Wait.count = @@ -61,6 +60,7 @@ void _CORE_message_queue_Seize( * So return immediately. */ _CORE_message_queue_Free_message_buffer(the_message_queue, the_message); + _CORE_message_queue_Release( the_message_queue, lock_context ); return; #else { @@ -73,12 +73,15 @@ void _CORE_message_queue_Seize( * NOTE: If we note that the queue was not full before this receive, * then we can avoid this dequeue. */ - the_thread = _Thread_queue_Dequeue( &the_message_queue->Wait_queue ); - if ( !the_thread ) { + the_thread = _Thread_queue_First_locked( + &the_message_queue->Wait_queue + ); + if ( the_thread == NULL ) { _CORE_message_queue_Free_message_buffer( the_message_queue, the_message ); + _CORE_message_queue_Release( the_message_queue, lock_context ); return; } @@ -103,13 +106,21 @@ void _CORE_message_queue_Seize( the_message, _CORE_message_queue_Get_message_priority( the_message ) ); + _Thread_queue_Extract_critical( + &the_message_queue->Wait_queue, + the_thread, + lock_context + ); + #if defined(RTEMS_MULTIPROCESSING) + _Thread_Dispatch_enable( _Per_CPU_Get() ); + #endif return; } #endif } if ( !wait ) { - _Thread_queue_Release( &the_message_queue->Wait_queue, &lock_context ); + _CORE_message_queue_Release( the_message_queue, lock_context ); executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT; return; } @@ -125,6 +136,9 @@ void _CORE_message_queue_Seize( STATES_WAITING_FOR_MESSAGE, timeout, CORE_MESSAGE_QUEUE_STATUS_TIMEOUT, - &lock_context + lock_context ); + #if defined(RTEMS_MULTIPROCESSING) + _Thread_Dispatch_enable( _Per_CPU_Get() ); + #endif } -- cgit v1.2.3