diff options
Diffstat (limited to 'cpukit/score/include/rtems/score/threadqimpl.h')
-rw-r--r-- | cpukit/score/include/rtems/score/threadqimpl.h | 1265 |
1 files changed, 0 insertions, 1265 deletions
diff --git a/cpukit/score/include/rtems/score/threadqimpl.h b/cpukit/score/include/rtems/score/threadqimpl.h deleted file mode 100644 index ecbd8fd42f..0000000000 --- a/cpukit/score/include/rtems/score/threadqimpl.h +++ /dev/null @@ -1,1265 +0,0 @@ -/** - * @file rtems/score/threadq.h - * - * Constants and Structures Associated with the Manipulation of Objects - * - * This include file contains all the constants and structures associated - * with the manipulation of objects. - */ - -/* - * COPYRIGHT (c) 1989-2014. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#ifndef _RTEMS_SCORE_THREADQIMPL_H -#define _RTEMS_SCORE_THREADQIMPL_H - -#include <rtems/score/threadq.h> -#include <rtems/score/chainimpl.h> -#include <rtems/score/priorityimpl.h> -#include <rtems/score/scheduler.h> -#include <rtems/score/smp.h> -#include <rtems/score/status.h> -#include <rtems/score/thread.h> -#include <rtems/score/threaddispatch.h> - -#if defined(RTEMS_DEBUG) -#include <string.h> -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @addtogroup ScoreThreadQueue - */ -/**@{*/ - -#define THREAD_QUEUE_LINK_OF_PATH_NODE( node ) \ - RTEMS_CONTAINER_OF( node, Thread_queue_Link, Path_node ); - -/** - * @brief Thread queue with a layout compatible to struct _Thread_queue_Queue - * defined in Newlib <sys/lock.h>. - */ -typedef struct { -#if !defined(RTEMS_SMP) - /* - * The struct _Thread_queue_Queue definition is independent of the RTEMS - * build configuration. Thus, the storage space for the SMP lock is always - * present. In SMP configurations, the SMP lock is contained in the - * Thread_queue_Queue. - */ - unsigned int reserved[2]; -#endif - - Thread_queue_Queue Queue; -} Thread_queue_Syslock_queue; - -void _Thread_queue_Enqueue_do_nothing_extra( - Thread_queue_Queue *queue, - Thread_Control *the_thread, - Per_CPU_Control *cpu_self, - Thread_queue_Context *queue_context -); - -void _Thread_queue_Add_timeout_ticks( - Thread_queue_Queue *queue, - Thread_Control *the_thread, - Per_CPU_Control *cpu_self, - Thread_queue_Context *queue_context -); - -void _Thread_queue_Add_timeout_monotonic_timespec( - Thread_queue_Queue *queue, - Thread_Control *the_thread, - Per_CPU_Control *cpu_self, - Thread_queue_Context *queue_context -); - -void _Thread_queue_Add_timeout_realtime_timespec( - Thread_queue_Queue *queue, - Thread_Control *the_thread, - Per_CPU_Control *cpu_self, - Thread_queue_Context *queue_context -); - -/** - * @brief Sets the thread wait return code to STATUS_DEADLOCK. - */ -void _Thread_queue_Deadlock_status( Thread_Control *the_thread ); - -/** - * @brief Results in an INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK fatal error. - */ -void _Thread_queue_Deadlock_fatal( Thread_Control *the_thread ); - -/** - * @brief Initializes a thread queue context. - * - * @param queue_context The thread queue context to initialize. - */ -RTEMS_INLINE_ROUTINE void _Thread_queue_Context_initialize( - Thread_queue_Context *queue_context -) -{ -#if defined(RTEMS_DEBUG) - memset( queue_context, 0x7f, sizeof( *queue_context ) ); -#if defined(RTEMS_SMP) - _Chain_Initialize_node( &queue_context->Lock_context.Wait.Gate.Node ); -#endif - queue_context->enqueue_callout = NULL; - queue_context->deadlock_callout = NULL; -#else - (void) queue_context; -#endif -} - -/** - * @brief Sets the thread state for the thread to enqueue in the thread queue - * context. - * - * @param queue_context The thread queue context. - * @param state The thread state. - * - * @see _Thread_queue_Enqueue(). - */ -RTEMS_INLINE_ROUTINE void -_Thread_queue_Context_set_thread_state( - Thread_queue_Context *queue_context, - States_Control thread_state -) -{ - queue_context->thread_state = thread_state; -} - -/** - * @brief Sets the timeout ticks in the thread queue context. - * - * @param queue_context The thread queue context. - * @param ticks The timeout in ticks. - * - * @see _Thread_queue_Enqueue(). - */ -RTEMS_INLINE_ROUTINE void -_Thread_queue_Context_set_timeout_ticks( - Thread_queue_Context *queue_context, - Watchdog_Interval ticks -) -{ - queue_context->Timeout.ticks = ticks; -} - -/** - * @brief Sets the timeout argument in the thread queue context. - * - * @param queue_context The thread queue context. - * @param arg The timeout argument. - * - * @see _Thread_queue_Enqueue(). - */ -RTEMS_INLINE_ROUTINE void -_Thread_queue_Context_set_timeout_argument( - Thread_queue_Context *queue_context, - const void *arg -) -{ - queue_context->Timeout.arg = arg; -} - -/** - * @brief Sets the enqueue callout in the thread queue context. - * - * @param queue_context The thread queue context. - * @param enqueue_callout The enqueue callout. - * - * @see _Thread_queue_Enqueue(). - */ -RTEMS_INLINE_ROUTINE void -_Thread_queue_Context_set_enqueue_callout( - Thread_queue_Context *queue_context, - Thread_queue_Enqueue_callout enqueue_callout -) -{ - queue_context->enqueue_callout = enqueue_callout; -} - -/** - * @brief Sets the do nothing enqueue callout in the thread queue context. - * - * @param queue_context The thread queue context. - * - * @see _Thread_queue_Enqueue(). - */ -RTEMS_INLINE_ROUTINE void -_Thread_queue_Context_set_enqueue_do_nothing_extra( - Thread_queue_Context *queue_context -) -{ - queue_context->enqueue_callout = _Thread_queue_Enqueue_do_nothing_extra; -} - -/** - * @brief Sets the enqueue callout to add a relative monotonic timeout in - * ticks. - * - * @param queue_context The thread queue context. - * @param ticks The timeout in ticks. - * - * @see _Thread_queue_Enqueue(). - */ -RTEMS_INLINE_ROUTINE void -_Thread_queue_Context_set_enqueue_timeout_ticks( - Thread_queue_Context *queue_context, - Watchdog_Interval ticks -) -{ - queue_context->Timeout.ticks = ticks; - queue_context->enqueue_callout = _Thread_queue_Add_timeout_ticks; -} - -/** - * @brief Sets the enqueue callout to add an absolute monotonic timeout in - * timespec format. - * - * @param queue_context The thread queue context. - * @param abstime The absolute monotonic timeout. - * - * @see _Thread_queue_Enqueue(). - */ -RTEMS_INLINE_ROUTINE void -_Thread_queue_Context_set_enqueue_timeout_monotonic_timespec( - Thread_queue_Context *queue_context, - const struct timespec *abstime -) -{ - queue_context->Timeout.arg = abstime; - queue_context->enqueue_callout = - _Thread_queue_Add_timeout_monotonic_timespec; -} - -/** - * @brief Sets the enqueue callout to add an absolute realtime timeout in - * timespec format. - * - * @param queue_context The thread queue context. - * @param abstime The absolute realtime timeout. - * - * @see _Thread_queue_Enqueue(). - */ -RTEMS_INLINE_ROUTINE void -_Thread_queue_Context_set_enqueue_timeout_realtime_timespec( - Thread_queue_Context *queue_context, - const struct timespec *abstime -) -{ - queue_context->Timeout.arg = abstime; - queue_context->enqueue_callout = _Thread_queue_Add_timeout_realtime_timespec; -} - -/** - * @brief Sets the deadlock callout in the thread queue - * context. - * - * A deadlock callout must be provided for _Thread_queue_Enqueue() - * operations that operate on thread queues which may have an owner, e.g. mutex - * objects. Available deadlock callouts are _Thread_queue_Deadlock_status() - * and _Thread_queue_Deadlock_fatal(). - * - * @param queue_context The thread queue context. - * @param deadlock_callout The deadlock callout. - * - * @see _Thread_queue_Enqueue(). - */ -RTEMS_INLINE_ROUTINE void _Thread_queue_Context_set_deadlock_callout( - Thread_queue_Context *queue_context, - Thread_queue_Deadlock_callout deadlock_callout -) -{ - queue_context->deadlock_callout = deadlock_callout; -} - -RTEMS_INLINE_ROUTINE void _Thread_queue_Context_clear_priority_updates( - Thread_queue_Context *queue_context -) -{ - queue_context->Priority.update_count = 0; -} - -RTEMS_INLINE_ROUTINE size_t _Thread_queue_Context_save_priority_updates( - Thread_queue_Context *queue_context -) -{ - return queue_context->Priority.update_count; -} - -RTEMS_INLINE_ROUTINE void _Thread_queue_Context_restore_priority_updates( - Thread_queue_Context *queue_context, - size_t update_count -) -{ - queue_context->Priority.update_count = update_count; -} - -RTEMS_INLINE_ROUTINE void _Thread_queue_Context_add_priority_update( - Thread_queue_Context *queue_context, - Thread_Control *the_thread -) -{ - size_t n; - - n = queue_context->Priority.update_count; - _Assert( n < RTEMS_ARRAY_SIZE( queue_context->Priority.update ) ); - - queue_context->Priority.update_count = n + 1; - queue_context->Priority.update[ n ] = the_thread; -} - -#define _Thread_queue_Context_ISR_disable( queue_context, level ) \ - do { \ - _ISR_Local_disable( level ); \ - _ISR_lock_ISR_disable_profile( \ - &( queue_context )->Lock_context.Lock_context \ - ) \ - } while ( 0 ) - -RTEMS_INLINE_ROUTINE void _Thread_queue_Context_set_ISR_level( - Thread_queue_Context *queue_context, - ISR_Level level -) -{ - _ISR_lock_Context_set_level( - &queue_context->Lock_context.Lock_context, - level - ); -} - -RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_queue_Dispatch_disable( - Thread_queue_Context *queue_context -) -{ - return _Thread_Dispatch_disable_critical( - &queue_context->Lock_context.Lock_context - ); -} - -/** - * @brief Sets the MP callout in the thread queue context. - * - * @param queue_context The thread queue context. - * @param mp_callout Callout to unblock the thread in case it is actually a - * thread proxy. This parameter is only used on multiprocessing - * configurations. Used by thread queue extract and unblock methods for - * objects with multiprocessing (MP) support. - */ -#if defined(RTEMS_MULTIPROCESSING) -RTEMS_INLINE_ROUTINE void _Thread_queue_Context_set_MP_callout( - Thread_queue_Context *queue_context, - Thread_queue_MP_callout mp_callout -) -{ - queue_context->mp_callout = mp_callout; -} -#else -#define _Thread_queue_Context_set_MP_callout( queue_context, mp_callout ) \ - do { \ - (void) queue_context; \ - } while ( 0 ) -#endif - -#if defined(RTEMS_SMP) -RTEMS_INLINE_ROUTINE void _Thread_queue_Gate_close( - Thread_queue_Gate *gate -) -{ - _Atomic_Store_uint( &gate->go_ahead, 0, ATOMIC_ORDER_RELAXED ); -} - -RTEMS_INLINE_ROUTINE void _Thread_queue_Gate_add( - Chain_Control *chain, - Thread_queue_Gate *gate -) -{ - _Chain_Append_unprotected( chain, &gate->Node ); -} - -RTEMS_INLINE_ROUTINE void _Thread_queue_Gate_open( - Thread_queue_Gate *gate -) -{ - _Atomic_Store_uint( &gate->go_ahead, 1, ATOMIC_ORDER_RELAXED ); -} - -RTEMS_INLINE_ROUTINE void _Thread_queue_Gate_wait( - Thread_queue_Gate *gate -) -{ - while ( _Atomic_Load_uint( &gate->go_ahead, ATOMIC_ORDER_RELAXED ) == 0 ) { - /* Wait */ - } -} -#endif - -RTEMS_INLINE_ROUTINE void _Thread_queue_Heads_initialize( - Thread_queue_Heads *heads -) -{ -#if defined(RTEMS_SMP) - size_t i; - - for ( i = 0; i < _Scheduler_Count; ++i ) { - _Chain_Initialize_node( &heads->Priority[ i ].Node ); - _Priority_Initialize_empty( &heads->Priority[ i ].Queue ); - heads->Priority[ i ].Queue.scheduler = &_Scheduler_Table[ i ]; - } -#endif - - _Chain_Initialize_empty( &heads->Free_chain ); - _Chain_Initialize_node( &heads->Free_node ); -} - -RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_initialize( - Thread_queue_Queue *queue, - const char *name -) -{ -#if defined(RTEMS_SMP) - _SMP_ticket_lock_Initialize( &queue->Lock ); -#endif - queue->heads = NULL; - queue->owner = NULL; - queue->name = name; -} - -RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_do_acquire_critical( - Thread_queue_Queue *queue, -#if defined(RTEMS_SMP) && defined(RTEMS_PROFILING) - SMP_lock_Stats *lock_stats, -#endif - ISR_lock_Context *lock_context -) -{ -#if defined(RTEMS_SMP) - _SMP_ticket_lock_Acquire( - &queue->Lock, - lock_stats, - &lock_context->Lock_context.Stats_context - ); -#else - (void) queue; - (void) lock_context; -#endif -} - -#if defined(RTEMS_SMP) && defined( RTEMS_PROFILING ) - #define \ - _Thread_queue_Queue_acquire_critical( queue, lock_stats, lock_context ) \ - _Thread_queue_Queue_do_acquire_critical( queue, lock_stats, lock_context ) -#else - #define \ - _Thread_queue_Queue_acquire_critical( queue, lock_stats, lock_context ) \ - _Thread_queue_Queue_do_acquire_critical( queue, lock_context ) -#endif - -RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_release_critical( - Thread_queue_Queue *queue, - ISR_lock_Context *lock_context -) -{ -#if defined(RTEMS_SMP) - _SMP_ticket_lock_Release( - &queue->Lock, - &lock_context->Lock_context.Stats_context - ); -#else - (void) queue; - (void) lock_context; -#endif -} - -RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_release( - Thread_queue_Queue *queue, - ISR_lock_Context *lock_context -) -{ - _Thread_queue_Queue_release_critical( queue, lock_context ); - _ISR_lock_ISR_enable( lock_context ); -} - -/** - * @brief Copies the thread queue name to the specified buffer. - * - * @param[in] queue The actual thread queue. - * @param[in] buffer The buffer for the thread queue name copy. - * @param[in] buffer_size The buffer size in characters. - * @param[in] id The object identifier in case the thread queue is embedded in - * an object with identifier, otherwise it is set to 0. - * - * @retval The length of the thread queue name. May be greater than or equal - * to the buffer size if truncation occurred. - */ -size_t _Thread_queue_Queue_get_name_and_id( - const Thread_queue_Queue *queue, - char *buffer, - size_t buffer_size, - Objects_Id *id -); - -#if defined(RTEMS_SMP) -void _Thread_queue_Do_acquire_critical( - Thread_queue_Control *the_thread_queue, - ISR_lock_Context *lock_context -); -#else -RTEMS_INLINE_ROUTINE void _Thread_queue_Do_acquire_critical( - Thread_queue_Control *the_thread_queue, - ISR_lock_Context *lock_context -) -{ - (void) the_thread_queue; - (void) lock_context; -} -#endif - -RTEMS_INLINE_ROUTINE void _Thread_queue_Acquire_critical( - Thread_queue_Control *the_thread_queue, - Thread_queue_Context *queue_context -) -{ - _Thread_queue_Do_acquire_critical( - the_thread_queue, - &queue_context->Lock_context.Lock_context - ); -} - -#if defined(RTEMS_SMP) -void _Thread_queue_Acquire( - Thread_queue_Control *the_thread_queue, - Thread_queue_Context *queue_context -); -#else -RTEMS_INLINE_ROUTINE void _Thread_queue_Acquire( - Thread_queue_Control *the_thread_queue, - Thread_queue_Context *queue_context -) -{ - (void) the_thread_queue; - _ISR_lock_ISR_disable( &queue_context->Lock_context.Lock_context ); -} -#endif - -#if defined(RTEMS_DEBUG) -RTEMS_INLINE_ROUTINE bool _Thread_queue_Is_lock_owner( - const Thread_queue_Control *the_thread_queue -) -{ -#if defined(RTEMS_SMP) - return the_thread_queue->owner == _SMP_lock_Who_am_I(); -#else - return _ISR_Get_level() != 0; -#endif -} -#endif - -#if defined(RTEMS_SMP) -void _Thread_queue_Do_release_critical( - Thread_queue_Control *the_thread_queue, - ISR_lock_Context *lock_context -); -#else -RTEMS_INLINE_ROUTINE void _Thread_queue_Do_release_critical( - Thread_queue_Control *the_thread_queue, - ISR_lock_Context *lock_context -) -{ - (void) the_thread_queue; - (void) lock_context; - _Assert( _Thread_queue_Is_lock_owner( the_thread_queue ) ); -} -#endif - -RTEMS_INLINE_ROUTINE void _Thread_queue_Release_critical( - Thread_queue_Control *the_thread_queue, - Thread_queue_Context *queue_context -) -{ - _Thread_queue_Do_release_critical( - the_thread_queue, - &queue_context->Lock_context.Lock_context - ); -} - -#if defined(RTEMS_SMP) -void _Thread_queue_Release( - Thread_queue_Control *the_thread_queue, - Thread_queue_Context *queue_context -); -#else -RTEMS_INLINE_ROUTINE void _Thread_queue_Release( - Thread_queue_Control *the_thread_queue, - Thread_queue_Context *queue_context -) -{ - (void) the_thread_queue; - _Assert( _Thread_queue_Is_lock_owner( the_thread_queue ) ); - _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context ); -} -#endif - -Thread_Control *_Thread_queue_Do_dequeue( - Thread_queue_Control *the_thread_queue, - const Thread_queue_Operations *operations -#if defined(RTEMS_MULTIPROCESSING) - , - Thread_queue_MP_callout mp_callout -#endif -); - -/** - * @brief Gets a pointer to a thread waiting on the_thread_queue. - * - * This function returns a pointer to a thread waiting on - * the_thread_queue. The selection of this thread is based on - * the discipline of the_thread_queue. If no threads are waiting - * on the_thread_queue, then NULL is returned. - * - * - INTERRUPT LATENCY: - * + single case - */ -#if defined(RTEMS_MULTIPROCESSING) - #define _Thread_queue_Dequeue( \ - the_thread_queue, \ - operations, \ - mp_callout \ - ) \ - _Thread_queue_Do_dequeue( \ - the_thread_queue, \ - operations, \ - mp_callout \ - ) -#else - #define _Thread_queue_Dequeue( \ - the_thread_queue, \ - operations, \ - mp_callout \ - ) \ - _Thread_queue_Do_dequeue( \ - the_thread_queue, \ - operations \ - ) -#endif - -/** - * @brief Blocks the thread and places it on the thread queue. - * - * This enqueues the thread on the thread queue, blocks the thread, and - * optionally starts the thread timer in case the timeout discipline is not - * WATCHDOG_NO_TIMEOUT. Timeout discipline and value are in the queue_context. - * - * 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. - * Thread dispatching is disabled before the thread queue lock is released. - * Thread dispatching is enabled once the sequence to block the thread is - * complete. The operation to enqueue the thread on the queue is protected by - * the thread queue lock. This makes it possible to use the thread queue lock - * to protect the state of objects embedding the thread queue and directly - * enter _Thread_queue_Enqueue() in case the thread must block. - * - * The thread queue context must be set up with the following functions, - * otherwise the behaviour is unpredictable - * - * - _Thread_queue_Context_set_thread_state(), - * - * - _Thread_queue_Context_set_enqueue_callout() or - * _Thread_queue_Context_set_enqueue_do_nothing_extra() or - * _Thread_queue_Context_set_enqueue_timeout_ticks() or - * _Thread_queue_Context_set_enqueue_timeout_monotonic_timespec() or - * _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(), - * - * - _Thread_queue_Context_set_deadlock_callout(). - * - * @code - * #include <rtems/score/threadqimpl.h> - * #include <rtems/score/statesimpl.h> - * - * #define MUTEX_TQ_OPERATIONS &_Thread_queue_Operations_priority - * - * typedef struct { - * Thread_queue_Control Queue; - * } Mutex; - * - * void _Mutex_Obtain( Mutex *mutex ) - * { - * Thread_queue_Context queue_context; - * Thread_Control *executing; - * - * _Thread_queue_Context_initialize( &queue_context ); - * _Thread_queue_Acquire( &mutex->Queue, queue_context ); - * - * executing = _Thread_Executing; - * - * if ( mutex->Queue.owner == NULL ) { - * mutex->Queue.owner = executing; - * _Thread_queue_Release( &mutex->Queue, queue_context ); - * } else { - * _Thread_queue_Context_set_thread_state( - * &queue_context, - * STATES_WAITING_FOR_MUTEX - * ); - * _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context ); - * _Thread_queue_Context_set_deadlock_callout( - * queue_context, - * _Thread_queue_Deadlock_fatal - * ); - * _Thread_queue_Enqueue( - * &mutex->Queue.Queue, - * MUTEX_TQ_OPERATIONS, - * executing, - * &queue_context - * ); - * } - * } - * @endcode - * - * @param[in] queue The actual thread queue. - * @param[in] operations The thread queue operations. - * @param[in] the_thread The thread to enqueue. - * @param[in] queue_context The thread queue context of the lock acquire. - */ -void _Thread_queue_Enqueue( - Thread_queue_Queue *queue, - const Thread_queue_Operations *operations, - Thread_Control *the_thread, - Thread_queue_Context *queue_context -); - -#if defined(RTEMS_SMP) -/** - * @brief Enqueues the thread on the thread queue and busy waits for dequeue. - * - * Optionally starts the thread timer in case the timeout discipline is not - * WATCHDOG_NO_TIMEOUT. Timeout discipline and value are in the queue_context. - * - * 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. - * - * The thread priorities of the owner and the are updated with respect to the - * scheduler. The sticky level of the thread is incremented. A thread - * dispatch is performed if necessary. - * - * Afterwards, the thread busy waits on the thread wait flags until a timeout - * occurs or the thread queue is surrendered to this thread. So, it sticks to - * the processor instead of blocking with respect to the scheduler. - * - * @param[in] queue The actual thread queue. - * @param[in] operations The thread queue operations. - * @param[in] the_thread The thread to enqueue. - * @param[in] queue_context The thread queue context of the lock acquire. - */ -Status_Control _Thread_queue_Enqueue_sticky( - Thread_queue_Queue *queue, - const Thread_queue_Operations *operations, - Thread_Control *the_thread, - Thread_queue_Context *queue_context -); -#endif - -/** - * @brief Extracts the thread from the thread queue, restores the default wait - * operations and restores the default thread lock. - * - * The caller must be the owner of the thread queue lock. The thread queue - * lock is not released. - * - * @param[in] queue The actual thread queue. - * @param[in] operations The thread queue operations. - * @param[in] the_thread The thread to extract. - * @param[in] queue_context The thread queue context. - * - * @return Returns the unblock indicator for _Thread_queue_Unblock_critical(). - * True indicates, that this thread must be unblocked by the scheduler later in - * _Thread_queue_Unblock_critical(), and false otherwise. In case false is - * returned, then the thread queue enqueue procedure was interrupted. Thus it - * will unblock itself and the thread wait information is no longer accessible, - * since this thread may already block on another resource in an SMP - * configuration. - */ -bool _Thread_queue_Extract_locked( - Thread_queue_Queue *queue, - const Thread_queue_Operations *operations, - Thread_Control *the_thread, - Thread_queue_Context *queue_context -); - -/** - * @brief Unblocks the thread which was on the thread queue before. - * - * The caller must be the owner of the thread queue lock. This function will - * release the thread queue lock. Thread dispatching is disabled before the - * thread queue lock is released and an unblock is necessary. Thread - * dispatching is enabled once the sequence to unblock the thread is complete. - * - * @param[in] unblock The unblock indicator returned by - * _Thread_queue_Extract_locked(). - * @param[in] queue The actual thread queue. - * @param[in] the_thread The thread to extract. - * @param[in] lock_context The lock context of the lock acquire. - */ -void _Thread_queue_Unblock_critical( - bool unblock, - Thread_queue_Queue *queue, - Thread_Control *the_thread, - ISR_lock_Context *lock_context -); - -/** - * @brief Extracts the thread from the thread queue and unblocks it. - * - * The caller must be the owner of the thread queue lock. This function will - * release the thread queue lock and restore the default thread lock. Thread - * dispatching is disabled before the thread queue lock is released and an - * unblock is necessary. Thread dispatching is enabled once the sequence to - * unblock the thread is complete. This makes it possible to use the thread - * queue lock to protect the state of objects embedding the thread queue and - * directly enter _Thread_queue_Extract_critical() to finalize an operation in - * case a waiting thread exists. - * - * @code - * #include <rtems/score/threadqimpl.h> - * - * typedef struct { - * Thread_queue_Control Queue; - * Thread_Control *owner; - * } Mutex; - * - * void _Mutex_Release( Mutex *mutex ) - * { - * Thread_queue_Context queue_context; - * Thread_Control *first; - * - * _Thread_queue_Context_initialize( &queue_context, NULL ); - * _Thread_queue_Acquire( &mutex->Queue, queue_context ); - * - * first = _Thread_queue_First_locked( &mutex->Queue ); - * mutex->owner = first; - * - * if ( first != NULL ) { - * _Thread_queue_Extract_critical( - * &mutex->Queue.Queue, - * mutex->Queue.operations, - * first, - * &queue_context - * ); - * } - * @endcode - * - * @param[in] queue The actual thread queue. - * @param[in] operations The thread queue operations. - * @param[in] the_thread The thread to extract. - * @param[in] queue_context The thread queue context of the lock acquire. - */ -void _Thread_queue_Extract_critical( - Thread_queue_Queue *queue, - const Thread_queue_Operations *operations, - Thread_Control *the_thread, - Thread_queue_Context *queue_context -); - -/** - * @brief Extracts thread from thread queue. - * - * This routine removes @a the_thread its thread queue - * and cancels any timeouts associated with this blocking. - * - * @param[in] the_thread is the pointer to a thread control block that - * is to be removed - */ -void _Thread_queue_Extract( Thread_Control *the_thread ); - -/** - * @brief Extracts the_thread from the_thread_queue. - * - * This routine extracts the_thread from the_thread_queue - * and ensures that if there is a proxy for this task on - * another node, it is also dealt with. - */ -void _Thread_queue_Extract_with_proxy( - Thread_Control *the_thread -); - -/** - * @brief Surrenders the thread queue previously owned by the thread to the - * first enqueued thread. - * - * The owner of the thread queue must be set to NULL by the caller. - * - * This function releases the thread queue lock. In addition it performs a - * thread dispatch if necessary. - * - * @param[in] queue The actual thread queue. - * @param[in] heads The thread queue heads. It must not be NULL. - * @param[in] previous_owner The previous owner thread surrendering the thread - * queue. - * @param[in] queue_context The thread queue context of the lock acquire. - * @param[in] operations The thread queue operations. - */ -void _Thread_queue_Surrender( - Thread_queue_Queue *queue, - Thread_queue_Heads *heads, - Thread_Control *previous_owner, - Thread_queue_Context *queue_context, - const Thread_queue_Operations *operations -); - -#if defined(RTEMS_SMP) -/** - * @brief Surrenders the thread queue previously owned by the thread to the - * first enqueued thread. - * - * The owner of the thread queue must be set to NULL by the caller. - * - * The caller must be the owner of the thread queue lock. This function will - * release the thread queue. - * - * The thread priorities of the previous owner and the new owner are updated. The - * sticky level of the previous owner is decremented. A thread dispatch is - * performed if necessary. - * - * @param[in] queue The actual thread queue. - * @param[in] heads The thread queue heads. It must not be NULL. - * @param[in] previous_owner The previous owner thread surrendering the thread - * queue. - * @param[in] queue_context The thread queue context of the lock acquire. - * @param[in] operations The thread queue operations. - */ -void _Thread_queue_Surrender_sticky( - Thread_queue_Queue *queue, - Thread_queue_Heads *heads, - Thread_Control *previous_owner, - Thread_queue_Context *queue_context, - const Thread_queue_Operations *operations -); -#endif - -RTEMS_INLINE_ROUTINE bool _Thread_queue_Is_empty( - const Thread_queue_Queue *queue -) -{ - return queue->heads == NULL; -} - -/** - * @brief Returns the first thread on the thread queue if it exists, otherwise - * @c NULL. - * - * The caller must be the owner of the thread queue lock. The thread queue - * lock is not released. - * - * @param[in] the_thread_queue The thread queue. - * @param[in] operations The thread queue operations. - * - * @retval NULL No thread is present on the thread queue. - * @retval first The first thread on the thread queue according to the enqueue - * order. - */ -RTEMS_INLINE_ROUTINE Thread_Control *_Thread_queue_First_locked( - Thread_queue_Control *the_thread_queue, - const Thread_queue_Operations *operations -) -{ - Thread_queue_Heads *heads = the_thread_queue->Queue.heads; - - if ( heads != NULL ) { - return ( *operations->first )( heads ); - } else { - return NULL; - } -} - -/** - * @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, - const Thread_queue_Operations *operations -); - -/** - * @brief Thread queue flush filter function. - * - * Called under protection of the thread queue lock by - * _Thread_queue_Flush_critical() to optionally alter the thread wait - * information and control the iteration. - * - * @param the_thread The thread to extract. This is the first parameter to - * optimize for architectures that use the same register for the first - * parameter and the return value. - * @param queue The actual thread queue. - * @param queue_context The thread queue context of the lock acquire. May be - * used to pass additional data to the filter function via an overlay - * structure. The filter function should not release or acquire the thread - * queue lock. - * - * @retval the_thread Extract this thread. - * @retval NULL Do not extract this thread and stop the thread queue flush - * operation. Threads that are already extracted will complete the flush - * operation. - */ -typedef Thread_Control *( *Thread_queue_Flush_filter )( - Thread_Control *the_thread, - Thread_queue_Queue *queue, - Thread_queue_Context *queue_context -); - -/** - * @brief Default thread queue flush filter function. - * - * @param the_thread The thread to extract. - * @param queue Unused. - * @param queue_context Unused. - * - * @retval the_thread Extract this thread. - */ -Thread_Control *_Thread_queue_Flush_default_filter( - Thread_Control *the_thread, - Thread_queue_Queue *queue, - Thread_queue_Context *queue_context -); - -/** - * @brief Status unavailable thread queue flush filter function. - * - * Sets the thread wait return code of the thread to STATUS_UNAVAILABLE. - * - * @param the_thread The thread to extract. - * @param queue Unused. - * @param queue_context Unused. - * - * @retval the_thread Extract this thread. - */ -Thread_Control *_Thread_queue_Flush_status_unavailable( - Thread_Control *the_thread, - Thread_queue_Queue *queue, - Thread_queue_Context *queue_context -); - -/** - * @brief Status object was deleted thread queue flush filter function. - * - * Sets the thread wait return code of the thread to STATUS_OBJECT_WAS_DELETED - * - * @param the_thread The thread to extract. - * @param queue Unused. - * @param queue_context Unused. - * - * @retval the_thread Extract this thread. - */ -Thread_Control *_Thread_queue_Flush_status_object_was_deleted( - Thread_Control *the_thread, - Thread_queue_Queue *queue, - Thread_queue_Context *queue_context -); - -/** - * @brief Unblocks all threads enqueued on the thread queue. - * - * This function iteratively extracts the first enqueued thread of the thread - * queue until the thread queue is empty or the filter function indicates a - * stop. The thread timers of the extracted threads are cancelled. The - * extracted threads are unblocked. - * - * @param queue The actual thread queue. - * @param operations The thread queue operations. - * @param filter The filter functions is called for each thread to extract from - * the thread queue. It may be used to alter the thread under protection of - * the thread queue lock, for example to set the thread wait return code. - * The return value of the filter function controls if the thread queue flush - * operation should stop or continue. - * @param queue_context The thread queue context of the lock acquire. May be - * used to pass additional data to the filter function via an overlay - * structure. The filter function should not release or acquire the thread - * queue lock. - * - * @return The count of extracted threads. - */ -size_t _Thread_queue_Flush_critical( - Thread_queue_Queue *queue, - const Thread_queue_Operations *operations, - Thread_queue_Flush_filter filter, - Thread_queue_Context *queue_context -); - -void _Thread_queue_Initialize( - Thread_queue_Control *the_thread_queue, - const char *name -); - -#if defined(RTEMS_SMP) && defined(RTEMS_DEBUG) && defined(RTEMS_PROFILING) - #define THREAD_QUEUE_INITIALIZER( _name ) \ - { \ - .Lock_stats = SMP_LOCK_STATS_INITIALIZER( _name ), \ - .owner = SMP_LOCK_NO_OWNER, \ - .Queue = { \ - .Lock = SMP_TICKET_LOCK_INITIALIZER, \ - .heads = NULL, \ - .owner = NULL, \ - .name = _name \ - } \ - } -#elif defined(RTEMS_SMP) && defined(RTEMS_DEBUG) - #define THREAD_QUEUE_INITIALIZER( _name ) \ - { \ - .owner = SMP_LOCK_NO_OWNER, \ - .Queue = { \ - .Lock = SMP_TICKET_LOCK_INITIALIZER, \ - .heads = NULL, \ - .owner = NULL, \ - .name = _name \ - } \ - } -#elif defined(RTEMS_SMP) && defined(RTEMS_PROFILING) - #define THREAD_QUEUE_INITIALIZER( _name ) \ - { \ - .Lock_stats = SMP_LOCK_STATS_INITIALIZER( _name ), \ - .Queue = { \ - .Lock = SMP_TICKET_LOCK_INITIALIZER, \ - .heads = NULL, \ - .owner = NULL, \ - .name = _name \ - } \ - } -#elif defined(RTEMS_SMP) - #define THREAD_QUEUE_INITIALIZER( _name ) \ - { \ - .Queue = { \ - .Lock = SMP_TICKET_LOCK_INITIALIZER, \ - .heads = NULL, \ - .owner = NULL, \ - .name = _name \ - } \ - } -#else - #define THREAD_QUEUE_INITIALIZER( _name ) \ - { \ - .Queue = { \ - .heads = NULL, \ - .owner = NULL, \ - .name = _name \ - } \ - } -#endif - -RTEMS_INLINE_ROUTINE void _Thread_queue_Destroy( - Thread_queue_Control *the_thread_queue -) -{ -#if defined(RTEMS_SMP) - _SMP_ticket_lock_Destroy( &the_thread_queue->Queue.Lock ); - _SMP_lock_Stats_destroy( &the_thread_queue->Lock_stats ); -#endif -} - -#if defined(RTEMS_MULTIPROCESSING) -void _Thread_queue_MP_callout_do_nothing( - Thread_Control *the_proxy, - Objects_Id mp_id -); - -void _Thread_queue_Unblock_proxy( - Thread_queue_Queue *queue, - Thread_Control *the_thread -); -#endif - -#if defined(RTEMS_SMP) -bool _Thread_queue_Path_acquire_critical( - Thread_queue_Queue *queue, - Thread_Control *the_thread, - Thread_queue_Context *queue_context -); - -void _Thread_queue_Path_release_critical( - Thread_queue_Context *queue_context -); -#endif - -/** - * @brief Helper structure to ensure that all objects containing a thread queue - * have the right layout. - * - * @see _Thread_Wait_get_id() and THREAD_QUEUE_OBJECT_ASSERT(). - */ -typedef struct { - Objects_Control Object; - Thread_queue_Control Wait_queue; -} Thread_queue_Object; - -#define THREAD_QUEUE_OBJECT_ASSERT( object_type, wait_queue_member ) \ - RTEMS_STATIC_ASSERT( \ - offsetof( object_type, wait_queue_member ) \ - == offsetof( Thread_queue_Object, Wait_queue ) \ - && RTEMS_HAVE_MEMBER_SAME_TYPE( \ - object_type, \ - wait_queue_member, \ - Thread_queue_Object, \ - Wait_queue \ - ), \ - object_type \ - ) - -#define THREAD_QUEUE_QUEUE_TO_OBJECT( queue ) \ - RTEMS_CONTAINER_OF( \ - queue, \ - Thread_queue_Object, \ - Wait_queue.Queue \ - ) - -extern const Thread_queue_Operations _Thread_queue_Operations_default; - -extern const Thread_queue_Operations _Thread_queue_Operations_FIFO; - -extern const Thread_queue_Operations _Thread_queue_Operations_priority; - -extern const Thread_queue_Operations _Thread_queue_Operations_priority_inherit; - -/** - * @brief The special thread queue name to indicated that the thread queue is - * embedded in an object with identifier. - * - * @see _Thread_queue_Object_initialize(). - */ -extern const char _Thread_queue_Object_name[]; - -/** - * @brief Initializes a thread queue embedded in an object with identifier. - * - * The object must have the layout specified by Thread_queue_Object. It should - * be ensured with the THREAD_QUEUE_OBJECT_ASSERT() static assertion. - * - * @param[in] the_thread_queue The thread queue. - */ -void _Thread_queue_Object_initialize( - Thread_queue_Control *the_thread_queue -); - -/**@}*/ - -#ifdef __cplusplus -} -#endif - -#endif -/* end of include file */ |