score: Add Thread_queue_Control::Lock

Move the complete thread queue enqueue procedure into
_Thread_queue_Enqueue_critical().  It is possible to use the thread
queue lock to protect state of the object embedding the thread queue.
This enables per object fine grained locking in the future.

Delete _Thread_queue_Enter_critical_section().

Update #2273.
This commit is contained in:
Sebastian Huber
2015-05-19 12:00:45 +02:00
parent 08fe84b5d7
commit 02c4c441a5
35 changed files with 261 additions and 169 deletions
@@ -80,6 +80,7 @@ RTEMS_INLINE_ROUTINE void _POSIX_Barrier_Free (
POSIX_Barrier_Control *the_barrier
)
{
_CORE_barrier_Destroy( &the_barrier->Barrier );
_Objects_Free( &_POSIX_Barrier_Information, &the_barrier->Object );
}
@@ -19,6 +19,7 @@
#include <rtems/posix/cond.h>
#include <rtems/score/objectimpl.h>
#include <rtems/score/threadqimpl.h>
#include <rtems/score/watchdog.h>
#ifdef __cplusplus
@@ -72,6 +73,7 @@ RTEMS_INLINE_ROUTINE void _POSIX_Condition_variables_Free (
POSIX_Condition_variables_Control *the_condition_variable
)
{
_Thread_queue_Destroy( &the_condition_variable->Wait_queue );
_Objects_Free(
&_POSIX_Condition_variables_Information,
&the_condition_variable->Object
@@ -72,6 +72,7 @@ RTEMS_INLINE_ROUTINE void _POSIX_Mutex_Free(
POSIX_Mutex_Control *the_mutex
)
{
_CORE_mutex_Destroy( &the_mutex->Mutex );
_Objects_Free( &_POSIX_Mutex_Information, &the_mutex->Object );
}
@@ -33,7 +33,7 @@
#include <rtems/posix/sigset.h>
#include <rtems/score/apiext.h>
#include <rtems/score/isrlock.h>
#include <rtems/score/threadq.h>
#include <rtems/score/threadqimpl.h>
#define _States_Is_interruptible_signal( _states ) \
( ((_states) & \
@@ -55,8 +55,6 @@
* Variables
*/
extern ISR_lock_Control _POSIX_signals_Lock;
extern sigset_t _POSIX_signals_Pending;
extern const struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ];
@@ -79,10 +77,10 @@ extern Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
void _POSIX_signals_Manager_Initialization(void);
#define _POSIX_signals_Acquire( lock_context ) \
_ISR_lock_ISR_disable_and_acquire( &_POSIX_signals_Lock, lock_context )
_Thread_queue_Acquire( &_POSIX_signals_Wait_queue, lock_context )
#define _POSIX_signals_Release( lock_context ) \
_ISR_lock_Release_and_ISR_enable( &_POSIX_signals_Lock, lock_context )
_Thread_queue_Release( &_POSIX_signals_Wait_queue, lock_context )
void _POSIX_signals_Action_handler(
Thread_Control *executing,
@@ -89,6 +89,7 @@ RTEMS_INLINE_ROUTINE void _POSIX_RWLock_Free (
POSIX_RWLock_Control *the_RWLock
)
{
_CORE_RWLock_Destroy( &the_RWLock->RWLock );
_Objects_Free( &_POSIX_RWLock_Information, &the_RWLock->Object );
}
@@ -65,6 +65,7 @@ RTEMS_INLINE_ROUTINE void _POSIX_Semaphore_Free (
POSIX_Semaphore_Control *the_semaphore
)
{
_CORE_semaphore_Destroy( &the_semaphore->Semaphore );
_Objects_Free( &_POSIX_Semaphore_Information, &the_semaphore->Object );
}
-2
View File
@@ -74,10 +74,8 @@ int _POSIX_Condition_variables_Wait_support(
if ( !already_timedout ) {
the_cond->Mutex = *mutex;
_Thread_queue_Enter_critical_section( &the_cond->Wait_queue );
executing = _Thread_Executing;
executing->Wait.return_code = 0;
executing->Wait.queue = &the_cond->Wait_queue;
executing->Wait.id = *cond;
_Thread_queue_Enqueue(
-2
View File
@@ -45,8 +45,6 @@ RTEMS_STATIC_ASSERT(
/*** PROCESS WIDE STUFF ****/
ISR_lock_Control _POSIX_signals_Lock = ISR_LOCK_INITIALIZER("POSIX signals");
sigset_t _POSIX_signals_Pending;
void _POSIX_signals_Abnormal_termination_handler(
+2
View File
@@ -288,6 +288,8 @@ static void _POSIX_Threads_Terminate_extension(
if ( api->schedpolicy == SCHED_SPORADIC )
_Watchdog_Remove_ticks( &api->Sporadic_timer );
_Thread_queue_Destroy( &api->Join_List );
_Thread_Enable_dispatch();
}
-1
View File
@@ -67,7 +67,6 @@ on_EINTR:
_Thread_Clear_state( the_thread, STATES_WAITING_FOR_JOIN_AT_EXIT );
} else {
executing->Wait.return_argument = &return_pointer;
_Thread_queue_Enter_critical_section( &api->Join_List );
_Thread_queue_Enqueue(
&api->Join_List,
executing,
+3 -5
View File
@@ -152,17 +152,15 @@ int sigtimedwait(
the_info->si_signo = -1;
_Thread_Disable_dispatch();
executing->Wait.queue = &_POSIX_signals_Wait_queue;
executing->Wait.return_code = EINTR;
executing->Wait.option = *set;
executing->Wait.return_argument = the_info;
_Thread_queue_Enter_critical_section( &_POSIX_signals_Wait_queue );
_POSIX_signals_Release( &lock_context );
_Thread_queue_Enqueue(
_Thread_queue_Enqueue_critical(
&_POSIX_signals_Wait_queue,
executing,
STATES_WAITING_FOR_SIGNAL | STATES_INTERRUPTIBLE_BY_SIGNAL,
interval
interval,
&lock_context
);
_Thread_Enable_dispatch();
@@ -86,6 +86,7 @@ RTEMS_INLINE_ROUTINE void _Barrier_Free (
Barrier_Control *the_barrier
)
{
_CORE_barrier_Destroy( &the_barrier->Barrier );
_Objects_Free( &_Barrier_Information, &the_barrier->Object );
}
@@ -18,6 +18,7 @@
#include <rtems/rtems/message.h>
#include <rtems/score/objectimpl.h>
#include <rtems/score/coremsgimpl.h>
#ifdef __cplusplus
extern "C" {
@@ -20,6 +20,7 @@
#include <rtems/rtems/region.h>
#include <rtems/score/heapimpl.h>
#include <rtems/score/objectimpl.h>
#include <rtems/score/threadqimpl.h>
#include <rtems/debug.h>
#ifdef __cplusplus
@@ -84,6 +85,7 @@ RTEMS_INLINE_ROUTINE void _Region_Free (
Region_Control *the_region
)
{
_Thread_queue_Destroy( &the_region->Wait_queue );
_Objects_Free( &_Region_Information, &the_region->Object );
}
+7 -11
View File
@@ -71,6 +71,12 @@ rtems_status_code rtems_region_create(
return_status = RTEMS_TOO_MANY;
else {
_Thread_queue_Initialize(
&the_region->Wait_queue,
_Attributes_Is_priority( attribute_set ) ?
THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO,
RTEMS_TIMEOUT
);
the_region->maximum_segment_size = _Heap_Initialize(
&the_region->Memory, starting_address, length, page_size
@@ -79,23 +85,13 @@ rtems_status_code rtems_region_create(
if ( !the_region->maximum_segment_size ) {
_Region_Free( the_region );
return_status = RTEMS_INVALID_SIZE;
}
else {
} else {
the_region->starting_address = starting_address;
the_region->length = length;
the_region->page_size = page_size;
the_region->attribute_set = attribute_set;
the_region->number_of_used_blocks = 0;
_Thread_queue_Initialize(
&the_region->Wait_queue,
_Attributes_Is_priority( attribute_set ) ?
THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO,
RTEMS_TIMEOUT
);
_Objects_Open(
&_Region_Information,
&the_region->Object,
-3
View File
@@ -79,13 +79,10 @@ rtems_status_code rtems_region_get_segment(
_Thread_Disable_dispatch();
_RTEMS_Unlock_allocator();
executing->Wait.queue = &the_region->Wait_queue;
executing->Wait.id = id;
executing->Wait.count = size;
executing->Wait.return_argument = segment;
_Thread_queue_Enter_critical_section( &the_region->Wait_queue );
_Thread_queue_Enqueue(
&the_region->Wait_queue,
executing,
+2
View File
@@ -76,12 +76,14 @@ rtems_status_code rtems_semaphore_delete(
SEMAPHORE_MP_OBJECT_WAS_DELETED,
CORE_MUTEX_WAS_DELETED
);
_CORE_mutex_Destroy( &the_semaphore->Core_control.mutex );
} else {
_CORE_semaphore_Flush(
&the_semaphore->Core_control.semaphore,
SEMAPHORE_MP_OBJECT_WAS_DELETED,
CORE_SEMAPHORE_WAS_DELETED
);
_CORE_semaphore_Destroy( &the_semaphore->Core_control.semaphore );
}
_Objects_Close( &_Semaphore_Information, &the_semaphore->Object );
@@ -21,6 +21,7 @@
#include <rtems/score/corebarrier.h>
#include <rtems/score/thread.h>
#include <rtems/score/threadqimpl.h>
#include <rtems/score/watchdog.h>
#ifdef __cplusplus
@@ -83,6 +84,13 @@ void _CORE_barrier_Initialize(
CORE_barrier_Attributes *the_barrier_attributes
);
RTEMS_INLINE_ROUTINE void _CORE_barrier_Destroy(
CORE_barrier_Control *the_barrier
)
{
_Thread_queue_Destroy( &the_barrier->Wait_queue );
}
/**
* @brief Wait for the barrier.
*
@@ -119,6 +119,11 @@ CORE_mutex_Status _CORE_mutex_Initialize(
bool initially_locked
);
RTEMS_INLINE_ROUTINE void _CORE_mutex_Destroy( CORE_mutex_Control *the_mutex )
{
_Thread_queue_Destroy( &the_mutex->Wait_queue );
}
/**
* @brief Attempt to receive a unit from the_mutex.
*
@@ -21,6 +21,7 @@
#include <rtems/score/corerwlock.h>
#include <rtems/score/thread.h>
#include <rtems/score/threadqimpl.h>
#include <rtems/score/watchdog.h>
#ifdef __cplusplus
@@ -87,6 +88,13 @@ void _CORE_RWLock_Initialize(
CORE_RWLock_Attributes *the_rwlock_attributes
);
RTEMS_INLINE_ROUTINE void _CORE_RWLock_Destroy(
CORE_RWLock_Control *the_rwlock
)
{
_Thread_queue_Destroy( &the_rwlock->Wait_queue );
}
/**
* @brief Obtain RWLock for reading.
*
+12 -7
View File
@@ -98,6 +98,13 @@ void _CORE_semaphore_Initialize(
uint32_t initial_value
);
RTEMS_INLINE_ROUTINE void _CORE_semaphore_Destroy(
CORE_semaphore_Control *the_semaphore
)
{
_Thread_queue_Destroy( &the_semaphore->Wait_queue );
}
#if defined(RTEMS_SCORE_CORESEM_ENABLE_SEIZE_BODY)
/**
* This routine attempts to receive a unit from @a the_semaphore.
@@ -234,16 +241,14 @@ RTEMS_INLINE_ROUTINE void _CORE_semaphore_Seize_isr_disable(
}
_Thread_Disable_dispatch();
_Thread_queue_Enter_critical_section( &the_semaphore->Wait_queue );
executing->Wait.queue = &the_semaphore->Wait_queue;
executing->Wait.id = id;
_ISR_lock_ISR_enable( lock_context );
_Thread_queue_Enqueue(
executing->Wait.id = id;
_Thread_queue_Acquire_critical( &the_semaphore->Wait_queue, lock_context );
_Thread_queue_Enqueue_critical(
&the_semaphore->Wait_queue,
executing,
STATES_WAITING_FOR_SEMAPHORE,
timeout
timeout,
lock_context
);
_Thread_Enable_dispatch();
}
@@ -20,6 +20,7 @@
#define _RTEMS_SCORE_THREADQ_H
#include <rtems/score/chain.h>
#include <rtems/score/isrlock.h>
#include <rtems/score/states.h>
#include <rtems/score/threadsync.h>
#include <rtems/score/rbtree.h>
@@ -62,6 +63,18 @@ typedef struct {
/** This is the set of threads for priority discipline waiting. */
RBTree_Control Priority;
} Queues;
/**
* @brief Lock to protect this thread queue.
*
* It may be used to protect additional state of the object embedding this
* thread queue.
*
* @see _Thread_queue_Acquire(), _Thread_queue_Acquire_critical() and
* _Thread_queue_Release().
*/
ISR_LOCK_MEMBER( Lock )
/** This field is used to manage the critical section. */
Thread_blocking_operation_States sync_state;
/** This field indicates the thread queue's blocking discipline. */
+86 -28
View File
@@ -31,6 +31,31 @@ extern "C" {
*/
/**@{*/
RTEMS_INLINE_ROUTINE void _Thread_queue_Acquire_critical(
Thread_queue_Control *the_thread_queue,
ISR_lock_Context *lock_context
)
{
_ISR_lock_Acquire( &the_thread_queue->Lock, lock_context );
}
RTEMS_INLINE_ROUTINE void _Thread_queue_Acquire(
Thread_queue_Control *the_thread_queue,
ISR_lock_Context *lock_context
)
{
_ISR_lock_ISR_disable( lock_context );
_Thread_queue_Acquire_critical( the_thread_queue, lock_context );
}
RTEMS_INLINE_ROUTINE void _Thread_queue_Release(
Thread_queue_Control *the_thread_queue,
ISR_lock_Context *lock_context
)
{
_ISR_lock_Release_and_ISR_enable( &the_thread_queue->Lock, lock_context );
}
/**
* The following type defines the callout used when a remote task
* is extracted from a local thread queue.
@@ -55,25 +80,47 @@ Thread_Control *_Thread_queue_Dequeue(
);
/**
* @brief Blocks a thread and places it on a thread.
* @brief Blocks a thread and places it on a thread queue.
*
* This routine blocks a thread, places it on a thread, and optionally
* starts a timeout timer.
* This routine blocks a thread, places it on a thread queue, and optionally
* starts a watchdog in case the timeout interval is not WATCHDOG_NO_TIMEOUT.
*
* @param[in] the_thread_queue pointer to threadq
* @param[in] the_thread the thread to enqueue
* @param[in] state is the new state of the thread
* @param[in] timeout interval to wait
* The caller must be the owner of the thread queue lock. This function will
* release the thread queue lock and register it as the new thread lock.
*
* - INTERRUPT LATENCY:
* + single case
* @param[in] the_thread_queue The thread queue.
* @param[in] the_thread The thread to enqueue.
* @param[in] state The new state of the thread.
* @param[in] timeout Interval to wait. Use WATCHDOG_NO_TIMEOUT to block
* potentially forever.
* @param[in] lock_context The lock context of the lock acquire.
*/
void _Thread_queue_Enqueue(
void _Thread_queue_Enqueue_critical(
Thread_queue_Control *the_thread_queue,
Thread_Control *the_thread,
States_Control state,
Watchdog_Interval timeout,
ISR_lock_Context *lock_context
);
RTEMS_INLINE_ROUTINE void _Thread_queue_Enqueue(
Thread_queue_Control *the_thread_queue,
Thread_Control *the_thread,
States_Control state,
Watchdog_Interval timeout
);
)
{
ISR_lock_Context lock_context;
_Thread_queue_Acquire( the_thread_queue, &lock_context );
_Thread_queue_Enqueue_critical(
the_thread_queue,
the_thread,
state,
timeout,
&lock_context
);
}
/**
* @brief Extracts thread from thread queue.
@@ -116,15 +163,30 @@ void _Thread_queue_Extract_with_proxy(
);
/**
* @brief Gets a pointer to the "first" thread on the_thread_queue.
* @brief Returns the first thread on the thread queue if it exists, otherwise
* @c NULL (locked).
*
* This function returns a pointer to the "first" thread
* on the_thread_queue. The "first" thread is selected
* based on the discipline of the_thread_queue.
* The caller must be the owner of the thread queue lock.
*
* @param[in] the_thread_queue pointer to thread queue
* @param[in] the_thread_queue The thread queue.
*
* @retval first thread or NULL
* @retval NULL No thread is present on the thread queue.
* @retval first The first thread on the thread queue according to the enqueue
* order.
*/
Thread_Control *_Thread_queue_First_locked(
Thread_queue_Control *the_thread_queue
);
/**
* @brief Returns the first thread on the thread queue if it exists, otherwise
* @c NULL.
*
* @param[in] the_thread_queue The thread queue.
*
* @retval NULL No thread is present on the thread queue.
* @retval first The first thread on the thread queue according to the enqueue
* order.
*/
Thread_Control *_Thread_queue_First(
Thread_queue_Control *the_thread_queue
@@ -165,6 +227,13 @@ void _Thread_queue_Initialize(
uint32_t timeout_status
);
RTEMS_INLINE_ROUTINE void _Thread_queue_Destroy(
Thread_queue_Control *the_thread_queue
)
{
_ISR_lock_Destroy( &the_thread_queue->Lock );
}
/**
* @brief Thread queue timeout.
*
@@ -212,17 +281,6 @@ RBTree_Compare_result _Thread_queue_Compare_priority(
const RBTree_Node *right
);
/**
* This routine is invoked to indicate that the specified thread queue is
* entering a critical section.
*/
RTEMS_INLINE_ROUTINE void _Thread_queue_Enter_critical_section (
Thread_queue_Control *the_thread_queue
)
{
the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
}
/**@}*/
#ifdef __cplusplus
+7 -9
View File
@@ -32,30 +32,28 @@ void _CORE_barrier_Wait(
CORE_barrier_API_mp_support_callout api_barrier_mp_support
)
{
ISR_Level level;
ISR_lock_Context lock_context;
executing->Wait.return_code = CORE_BARRIER_STATUS_SUCCESSFUL;
_ISR_Disable( level );
_Thread_queue_Acquire( &the_barrier->Wait_queue, &lock_context );
the_barrier->number_of_waiting_threads++;
if ( _CORE_barrier_Is_automatic( &the_barrier->Attributes ) ) {
if ( the_barrier->number_of_waiting_threads ==
the_barrier->Attributes.maximum_count) {
executing->Wait.return_code = CORE_BARRIER_STATUS_AUTOMATICALLY_RELEASED;
_ISR_Enable( level );
_Thread_queue_Release( &the_barrier->Wait_queue, &lock_context );
_CORE_barrier_Release( the_barrier, id, api_barrier_mp_support );
return;
}
}
_Thread_queue_Enter_critical_section( &the_barrier->Wait_queue );
executing->Wait.queue = &the_barrier->Wait_queue;
executing->Wait.id = id;
_ISR_Enable( level );
executing->Wait.id = id;
_Thread_queue_Enqueue(
_Thread_queue_Enqueue_critical(
&the_barrier->Wait_queue,
executing,
STATES_WAITING_FOR_BARRIER,
timeout
timeout,
&lock_context
);
}
+1
View File
@@ -54,4 +54,5 @@ void _CORE_message_queue_Close(
(void) _Workspace_Free( the_message_queue->message_buffers );
_Thread_queue_Destroy( &the_message_queue->Wait_queue );
}
+7 -9
View File
@@ -36,15 +36,15 @@ void _CORE_message_queue_Seize(
Watchdog_Interval timeout
)
{
ISR_Level level;
ISR_lock_Context lock_context;
CORE_message_queue_Buffer_control *the_message;
executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
_ISR_Disable( level );
_Thread_queue_Acquire( &the_message_queue->Wait_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;
_ISR_Enable( level );
_Thread_queue_Release( &the_message_queue->Wait_queue, &lock_context );
*size_p = the_message->Contents.size;
executing->Wait.count =
@@ -109,23 +109,21 @@ void _CORE_message_queue_Seize(
}
if ( !wait ) {
_ISR_Enable( level );
_Thread_queue_Release( &the_message_queue->Wait_queue, &lock_context );
executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT;
return;
}
_Thread_queue_Enter_critical_section( &the_message_queue->Wait_queue );
executing->Wait.queue = &the_message_queue->Wait_queue;
executing->Wait.id = id;
executing->Wait.return_argument_second.mutable_object = buffer;
executing->Wait.return_argument = size_p;
/* Wait.count will be filled in with the message priority */
_ISR_Enable( level );
_Thread_queue_Enqueue(
_Thread_queue_Enqueue_critical(
&the_message_queue->Wait_queue,
executing,
STATES_WAITING_FOR_MESSAGE,
timeout
timeout,
&lock_context
);
}
-6
View File
@@ -120,16 +120,10 @@ CORE_message_queue_Status _CORE_message_queue_Submit(
* would be to use this variable prior to here.
*/
{
ISR_Level level;
_ISR_Disable( level );
_Thread_queue_Enter_critical_section( &the_message_queue->Wait_queue );
executing->Wait.queue = &the_message_queue->Wait_queue;
executing->Wait.id = id;
executing->Wait.return_argument_second.immutable_object = buffer;
executing->Wait.option = (uint32_t) size;
executing->Wait.count = submit_type;
_ISR_Enable( level );
_Thread_queue_Enqueue(
&the_message_queue->Wait_queue,
+13 -5
View File
@@ -53,27 +53,35 @@ void _CORE_mutex_Seize_interrupt_blocking(
ISR_lock_Context *lock_context
)
{
_Thread_queue_Enter_critical_section( &the_mutex->Wait_queue );
executing->Wait.queue = &the_mutex->Wait_queue;
_Thread_Disable_dispatch();
_ISR_lock_ISR_enable( lock_context );
if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ) {
Thread_Control *holder = the_mutex->holder;
/*
* To enable interrupts here works only since we own the Giant lock and
* only threads are allowed to seize and surrender mutexes with the
* priority inheritance protocol.
*/
_ISR_lock_ISR_enable( lock_context );
_Scheduler_Change_priority_if_higher(
_Scheduler_Get( holder ),
holder,
executing->current_priority,
false
);
_ISR_lock_ISR_disable( lock_context );
}
_Thread_queue_Enqueue(
_Thread_queue_Acquire_critical( &the_mutex->Wait_queue, lock_context );
_Thread_queue_Enqueue_critical(
&the_mutex->Wait_queue,
executing,
STATES_WAITING_FOR_MUTEX,
timeout
timeout,
lock_context
);
_Thread_Enable_dispatch();
+9 -11
View File
@@ -32,7 +32,7 @@ void _CORE_RWLock_Obtain_for_reading(
CORE_RWLock_API_mp_support_callout api_rwlock_mp_support
)
{
ISR_Level level;
ISR_lock_Context lock_context;
/*
* If unlocked, then OK to read.
@@ -40,21 +40,21 @@ void _CORE_RWLock_Obtain_for_reading(
* If any thread is waiting, then we wait.
*/
_ISR_Disable( level );
_Thread_queue_Acquire( &the_rwlock->Wait_queue, &lock_context );
switch ( the_rwlock->current_state ) {
case CORE_RWLOCK_UNLOCKED:
the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_READING;
the_rwlock->number_of_readers += 1;
_ISR_Enable( level );
_Thread_queue_Release( &the_rwlock->Wait_queue, &lock_context );
executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
return;
case CORE_RWLOCK_LOCKED_FOR_READING: {
Thread_Control *waiter;
waiter = _Thread_queue_First( &the_rwlock->Wait_queue );
waiter = _Thread_queue_First_locked( &the_rwlock->Wait_queue );
if ( !waiter ) {
the_rwlock->number_of_readers += 1;
_ISR_Enable( level );
_Thread_queue_Release( &the_rwlock->Wait_queue, &lock_context );
executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
return;
}
@@ -69,7 +69,7 @@ void _CORE_RWLock_Obtain_for_reading(
*/
if ( !wait ) {
_ISR_Enable( level );
_Thread_queue_Release( &the_rwlock->Wait_queue, &lock_context );
executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE;
return;
}
@@ -78,18 +78,16 @@ void _CORE_RWLock_Obtain_for_reading(
* We need to wait to enter this critical section
*/
_Thread_queue_Enter_critical_section( &the_rwlock->Wait_queue );
executing->Wait.queue = &the_rwlock->Wait_queue;
executing->Wait.id = id;
executing->Wait.option = CORE_RWLOCK_THREAD_WAITING_FOR_READ;
executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
_ISR_Enable( level );
_Thread_queue_Enqueue(
_Thread_queue_Enqueue_critical(
&the_rwlock->Wait_queue,
executing,
STATES_WAITING_FOR_RWLOCK,
timeout
timeout,
&lock_context
);
/* return to API level so it can dispatch and we block */
+10 -12
View File
@@ -32,7 +32,7 @@ void _CORE_RWLock_Obtain_for_writing(
CORE_RWLock_API_mp_support_callout api_rwlock_mp_support
)
{
ISR_Level level;
ISR_lock_Context lock_context;
/*
* If unlocked, then OK to read.
@@ -41,13 +41,13 @@ void _CORE_RWLock_Obtain_for_writing(
* If any thread is waiting, then we wait.
*/
_ISR_Disable( level );
_Thread_queue_Acquire( &the_rwlock->Wait_queue, &lock_context );
switch ( the_rwlock->current_state ) {
case CORE_RWLOCK_UNLOCKED:
the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_WRITING;
_ISR_Enable( level );
executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
return;
the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_WRITING;
_Thread_queue_Release( &the_rwlock->Wait_queue, &lock_context );
executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
return;
case CORE_RWLOCK_LOCKED_FOR_READING:
case CORE_RWLOCK_LOCKED_FOR_WRITING:
@@ -59,7 +59,7 @@ void _CORE_RWLock_Obtain_for_writing(
*/
if ( !wait ) {
_ISR_Enable( level );
_Thread_queue_Release( &the_rwlock->Wait_queue, &lock_context );
executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE;
return;
}
@@ -68,18 +68,16 @@ void _CORE_RWLock_Obtain_for_writing(
* We need to wait to enter this critical section
*/
_Thread_queue_Enter_critical_section( &the_rwlock->Wait_queue );
executing->Wait.queue = &the_rwlock->Wait_queue;
executing->Wait.id = id;
executing->Wait.option = CORE_RWLOCK_THREAD_WAITING_FOR_WRITE;
executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
_ISR_Enable( level );
_Thread_queue_Enqueue(
_Thread_queue_Enqueue_critical(
&the_rwlock->Wait_queue,
executing,
STATES_WAITING_FOR_RWLOCK,
timeout
timeout,
&lock_context
);
/* return to API level so it can dispatch and we block */
+8 -10
View File
@@ -34,13 +34,13 @@ void _CORE_semaphore_Seize(
Watchdog_Interval timeout
)
{
ISR_Level level;
ISR_lock_Context lock_context;
executing->Wait.return_code = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
_ISR_Disable( level );
_Thread_queue_Acquire( &the_semaphore->Wait_queue, &lock_context );
if ( the_semaphore->count != 0 ) {
the_semaphore->count -= 1;
_ISR_Enable( level );
_Thread_queue_Release( &the_semaphore->Wait_queue, &lock_context );
return;
}
@@ -50,7 +50,7 @@ void _CORE_semaphore_Seize(
* the semaphore was not available and the caller never blocked.
*/
if ( !wait ) {
_ISR_Enable( level );
_Thread_queue_Release( &the_semaphore->Wait_queue, &lock_context );
executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
return;
}
@@ -59,15 +59,13 @@ void _CORE_semaphore_Seize(
* If the semaphore is not available and the caller is willing to
* block, then we now block the caller with optional timeout.
*/
_Thread_queue_Enter_critical_section( &the_semaphore->Wait_queue );
executing->Wait.queue = &the_semaphore->Wait_queue;
executing->Wait.id = id;
_ISR_Enable( level );
_Thread_queue_Enqueue(
executing->Wait.id = id;
_Thread_queue_Enqueue_critical(
&the_semaphore->Wait_queue,
executing,
STATES_WAITING_FOR_SEMAPHORE,
timeout
timeout,
&lock_context
);
}
#endif
-2
View File
@@ -206,8 +206,6 @@ uint32_t _MPCI_Send_request_packet (
(*_MPCI_table->send_packet)( destination, the_packet );
_Thread_queue_Enter_critical_section( &_MPCI_Remote_blocked_threads );
/*
* See if we need a default timeout
*/
+2 -1
View File
@@ -55,10 +55,11 @@ void _Thread_queue_Initialize(
the_thread_queue->timeout_status = timeout_status;
the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
_ISR_lock_Initialize( &the_thread_queue->Lock, "Thread Queue" );
if ( the_discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY ) {
_RBTree_Initialize_empty( &the_thread_queue->Queues.Priority );
} else { /* must be THREAD_QUEUE_DISCIPLINE_FIFO */
_Chain_Initialize_empty( &the_thread_queue->Queues.Fifo );
}
}
+30 -33
View File
@@ -24,18 +24,6 @@
#include <rtems/score/threadimpl.h>
#include <rtems/score/watchdogimpl.h>
ISR_LOCK_DEFINE( static, _Thread_queue_Lock, "Thread Queue" )
static void _Thread_queue_Acquire( ISR_lock_Context *lock_context )
{
_ISR_lock_ISR_disable_and_acquire( &_Thread_queue_Lock, lock_context );
}
static void _Thread_queue_Release( ISR_lock_Context *lock_context )
{
_ISR_lock_Release_and_ISR_enable( &_Thread_queue_Lock, lock_context );
}
/**
* @brief Finalize a blocking operation.
*
@@ -50,8 +38,9 @@ static void _Thread_queue_Release( ISR_lock_Context *lock_context )
* @param[in] lock_context is the previous ISR disable level
*/
static void _Thread_blocking_operation_Finalize(
Thread_Control *the_thread,
ISR_lock_Context *lock_context
Thread_queue_Control *the_thread_queue,
Thread_Control *the_thread,
ISR_lock_Context *lock_context
)
{
/*
@@ -59,16 +48,18 @@ static void _Thread_blocking_operation_Finalize(
*/
the_thread->Wait.queue = NULL;
_Thread_Lock_restore_default( the_thread );
/*
* If the sync state is timed out, this is very likely not needed.
* But better safe than sorry when it comes to critical sections.
*/
if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
_Watchdog_Deactivate( &the_thread->Timer );
_Thread_queue_Release( lock_context );
_Thread_queue_Release( the_thread_queue, lock_context );
_Watchdog_Remove_ticks( &the_thread->Timer );
} else
_Thread_queue_Release( lock_context );
_Thread_queue_Release( the_thread_queue, lock_context );
/*
* Global objects with thread queue's should not be operated on from an
@@ -101,16 +92,23 @@ static void _Thread_queue_Requeue_priority(
);
}
void _Thread_queue_Enqueue(
void _Thread_queue_Enqueue_critical(
Thread_queue_Control *the_thread_queue,
Thread_Control *the_thread,
States_Control state,
Watchdog_Interval timeout
Watchdog_Interval timeout,
ISR_lock_Context *lock_context
)
{
ISR_lock_Context lock_context;
Thread_blocking_operation_States sync_state;
_Thread_Lock_set( the_thread, &the_thread_queue->Lock );
the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
the_thread->Wait.queue = the_thread_queue;
_Thread_queue_Release( the_thread_queue, lock_context );
#if defined(RTEMS_MULTIPROCESSING)
if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet )
the_thread = _Thread_MP_Allocate_proxy( state );
@@ -140,7 +138,7 @@ void _Thread_queue_Enqueue(
* should be completed or the thread has had its blocking condition
* satisfied before we got here.
*/
_Thread_queue_Acquire( &lock_context );
_Thread_queue_Acquire( the_thread_queue, lock_context );
sync_state = the_thread_queue->sync_state;
the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
@@ -155,7 +153,6 @@ void _Thread_queue_Enqueue(
&the_thread->Object.Node
);
} else { /* must be THREAD_QUEUE_DISCIPLINE_PRIORITY */
_Thread_Lock_set( the_thread, &_Thread_queue_Lock );
_Thread_Priority_set_change_handler(
the_thread,
_Thread_queue_Requeue_priority,
@@ -169,9 +166,8 @@ void _Thread_queue_Enqueue(
);
}
the_thread->Wait.queue = the_thread_queue;
the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
_Thread_queue_Release( &lock_context );
_Thread_queue_Release( the_thread_queue, lock_context );
} else {
/* Cancel a blocking operation due to ISR */
@@ -180,7 +176,7 @@ void _Thread_queue_Enqueue(
sync_state == THREAD_BLOCKING_OPERATION_SATISFIED
);
_Thread_blocking_operation_Finalize( the_thread, &lock_context );
_Thread_blocking_operation_Finalize( the_thread_queue, the_thread, lock_context );
}
}
@@ -190,16 +186,19 @@ void _Thread_queue_Extract_with_return_code(
)
{
Thread_queue_Control *the_thread_queue;
ISR_lock_Context lock_context;
ISR_lock_Control *lock;
ISR_lock_Context lock_context;
_Thread_queue_Acquire( &lock_context );
lock = _Thread_Lock_acquire( the_thread, &lock_context );
the_thread_queue = the_thread->Wait.queue;
if ( the_thread_queue == NULL ) {
_Thread_queue_Release( &lock_context );
_Thread_Lock_release( lock, &lock_context );
return;
}
_SMP_Assert( lock == &the_thread_queue->Lock );
if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_FIFO ) {
_Chain_Extract_unprotected( &the_thread->Object.Node );
} else { /* must be THREAD_QUEUE_DISCIPLINE_PRIORITY */
@@ -208,7 +207,6 @@ void _Thread_queue_Extract_with_return_code(
&the_thread->RBNode
);
_Thread_Priority_restore_default_change_handler( the_thread );
_Thread_Lock_restore_default( the_thread );
}
the_thread->Wait.return_code = return_code;
@@ -218,7 +216,7 @@ void _Thread_queue_Extract_with_return_code(
*
* NOTE: This is invoked with interrupts still disabled.
*/
_Thread_blocking_operation_Finalize( the_thread, &lock_context );
_Thread_blocking_operation_Finalize( the_thread_queue, the_thread, &lock_context );
}
void _Thread_queue_Extract( Thread_Control *the_thread )
@@ -238,7 +236,7 @@ Thread_Control *_Thread_queue_Dequeue(
Thread_blocking_operation_States sync_state;
the_thread = NULL;
_Thread_queue_Acquire( &lock_context );
_Thread_queue_Acquire( the_thread_queue, &lock_context );
/*
* Invoke the discipline specific dequeue method.
@@ -255,7 +253,6 @@ Thread_Control *_Thread_queue_Dequeue(
if ( first ) {
the_thread = THREAD_RBTREE_NODE_TO_THREAD( first );
_Thread_Priority_restore_default_change_handler( the_thread );
_Thread_Lock_restore_default( the_thread );
}
}
@@ -270,7 +267,7 @@ Thread_Control *_Thread_queue_Dequeue(
the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SATISFIED;
the_thread = _Thread_Executing;
} else {
_Thread_queue_Release( &lock_context );
_Thread_queue_Release( the_thread_queue, &lock_context );
return NULL;
}
}
@@ -280,7 +277,7 @@ Thread_Control *_Thread_queue_Dequeue(
*
* NOTE: This is invoked with interrupts still disabled.
*/
_Thread_blocking_operation_Finalize( the_thread, &lock_context );
_Thread_blocking_operation_Finalize( the_thread_queue, the_thread, &lock_context );
return the_thread;
}
+15 -7
View File
@@ -20,20 +20,16 @@
#include <rtems/score/threadqimpl.h>
#include <rtems/score/chainimpl.h>
#include <rtems/score/isrlevel.h>
#include <rtems/score/threadimpl.h>
Thread_Control *_Thread_queue_First(
Thread_Control *_Thread_queue_First_locked(
Thread_queue_Control *the_thread_queue
)
{
ISR_Level level;
Thread_Control *thread;
thread = NULL;
_ISR_Disable( level );
if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_FIFO ) {
if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) )
thread = (Thread_Control *) _Chain_First(&the_thread_queue->Queues.Fifo);
@@ -45,7 +41,19 @@ Thread_Control *_Thread_queue_First(
thread = THREAD_RBTREE_NODE_TO_THREAD( first );
}
_ISR_Enable( level );
return thread;
}
Thread_Control *_Thread_queue_First(
Thread_queue_Control *the_thread_queue
)
{
Thread_Control *the_thread;
ISR_lock_Context lock_context;
_Thread_queue_Acquire( the_thread_queue, &lock_context );
the_thread = _Thread_queue_First_locked( the_thread_queue );
_Thread_queue_Release( the_thread_queue, &lock_context );
return the_thread;
}