Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:13

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreThreadQueue
0007  *
0008  * @brief This header file provides interfaces of the
0009  *   @ref RTEMSScoreThreadQueue which are only used by the implementation.
0010  */
0011 
0012 /*
0013  *  COPYRIGHT (c) 1989-2014.
0014  *  On-Line Applications Research Corporation (OAR).
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 #ifndef _RTEMS_SCORE_THREADQIMPL_H
0039 #define _RTEMS_SCORE_THREADQIMPL_H
0040 
0041 #include <rtems/score/threadq.h>
0042 #include <rtems/score/chainimpl.h>
0043 #include <rtems/score/priorityimpl.h>
0044 #include <rtems/score/scheduler.h>
0045 #include <rtems/score/smp.h>
0046 #include <rtems/score/status.h>
0047 #include <rtems/score/thread.h>
0048 #include <rtems/score/threaddispatch.h>
0049 
0050 #if defined(RTEMS_DEBUG)
0051 #include <string.h>
0052 #endif
0053 
0054 #ifdef __cplusplus
0055 extern "C" {
0056 #endif
0057 
0058 /**
0059  *  @addtogroup RTEMSScoreThreadQueue
0060  *
0061  * @{
0062  */
0063 
0064 #define THREAD_QUEUE_LINK_OF_PATH_NODE( node ) \
0065   RTEMS_CONTAINER_OF( node, Thread_queue_Link, Path_node );
0066 
0067 /**
0068  * @brief Thread queue with a layout compatible to struct _Thread_queue_Queue
0069  * defined in Newlib <sys/lock.h>.
0070  */
0071 typedef struct {
0072 #if !defined(RTEMS_SMP)
0073   /*
0074    * The struct _Thread_queue_Queue definition is independent of the RTEMS
0075    * build configuration.  Thus, the storage space for the SMP lock is always
0076    * present.  In SMP configurations, the SMP lock is contained in the
0077    * Thread_queue_Queue.
0078    */
0079   unsigned int reserved[2];
0080 #endif
0081 
0082   Thread_queue_Queue Queue;
0083 } Thread_queue_Syslock_queue;
0084 
0085 /**
0086  * @brief Does nothing.
0087  *
0088  * @param queue This parameter is unused.
0089  * @param the_thread This parameter is unused.
0090  * @param cpu_self This parameter is unused.
0091  * @param queue_context This parameter is unused.
0092  */
0093 void _Thread_queue_Enqueue_do_nothing_extra(
0094   Thread_queue_Queue   *queue,
0095   Thread_Control       *the_thread,
0096   Per_CPU_Control      *cpu_self,
0097   Thread_queue_Context *queue_context
0098 );
0099 
0100 /**
0101  * @brief Adds timeout ticks of the queue to the thread.
0102  *
0103  * @param queue This parameter is unused.
0104  * @param[in, out] the_thread The thread to add timeout ticks to.
0105  * @param cpu_self The cpu for the operation.
0106  * @param queue_context The thread queue context.
0107  */
0108 void _Thread_queue_Add_timeout_ticks(
0109   Thread_queue_Queue   *queue,
0110   Thread_Control       *the_thread,
0111   Per_CPU_Control      *cpu_self,
0112   Thread_queue_Context *queue_context
0113 );
0114 
0115 /**
0116  * @brief Adds a monotonic timespec to the thread and sets the watchdog header
0117  *      to monotonic.
0118  *
0119  * @param queue This parameter is unused.
0120  * @param[in, out] the_thread The thread to add the timeout and set watchdog header to
0121  *      monotonic.
0122  * @param cpu_self The cpu to get the monotonic watchdog header from.
0123  * @param queue_context The thread queue context.
0124  */
0125 void _Thread_queue_Add_timeout_monotonic_timespec(
0126   Thread_queue_Queue   *queue,
0127   Thread_Control       *the_thread,
0128   Per_CPU_Control      *cpu_self,
0129   Thread_queue_Context *queue_context
0130 );
0131 
0132 /**
0133  * @brief Adds a monotonic timespec to the thread and sets the watchdog header
0134  *      to realtime.
0135  *
0136  * @param queue This parameter is unused.
0137  * @param[in, out] the_thread The thread to add the timeout and set watchdog header to
0138  *      realtime.
0139  * @param cpu_self The cpu to get the realtime watchdog header from.
0140  * @param queue_context The thread queue context.
0141  */
0142 void _Thread_queue_Add_timeout_realtime_timespec(
0143   Thread_queue_Queue   *queue,
0144   Thread_Control       *the_thread,
0145   Per_CPU_Control      *cpu_self,
0146   Thread_queue_Context *queue_context
0147 );
0148 
0149 /**
0150  * @brief Sets the thread wait return code to STATUS_DEADLOCK.
0151  *
0152  * @param[out] the_thread The thread to set the wait return code to
0153  *      STATUS_DEADLOCK.
0154  */
0155 void _Thread_queue_Deadlock_status( Thread_Control *the_thread );
0156 
0157 /**
0158  * @brief Results in an INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK fatal error.
0159  *
0160  * @param the_thread The thread for the operation.
0161  */
0162 void _Thread_queue_Deadlock_fatal( Thread_Control *the_thread );
0163 
0164 /**
0165  * @brief Initializes a thread queue context.
0166  *
0167  * @param[out] queue_context The thread queue context to initialize.
0168  */
0169 static inline void _Thread_queue_Context_initialize(
0170   Thread_queue_Context *queue_context
0171 )
0172 {
0173 #if defined(RTEMS_DEBUG)
0174   memset( queue_context, 0x7f, sizeof( *queue_context ) );
0175 #if defined(RTEMS_SMP)
0176   _Chain_Initialize_node( &queue_context->Lock_context.Wait.Gate.Node );
0177 #endif
0178   queue_context->enqueue_callout = NULL;
0179   queue_context->deadlock_callout = NULL;
0180 #else
0181   (void) queue_context;
0182 #endif
0183 }
0184 
0185 /**
0186  * @brief Sets the thread state for the thread to enqueue in the thread queue
0187  * context.
0188  *
0189  * @param[out] queue_context The thread queue context.
0190  * @param state The thread state.
0191  *
0192  * @see _Thread_queue_Enqueue().
0193  */
0194 static inline void
0195 _Thread_queue_Context_set_thread_state(
0196   Thread_queue_Context *queue_context,
0197   States_Control        thread_state
0198 )
0199 {
0200   queue_context->thread_state = thread_state;
0201 }
0202 
0203 /**
0204  * @brief Sets the timeout ticks in the thread queue context.
0205  *
0206  * @param[out] queue_context The thread queue context.
0207  * @param ticks The timeout in ticks.
0208  *
0209  * @see _Thread_queue_Enqueue().
0210  */
0211 static inline void
0212 _Thread_queue_Context_set_timeout_ticks(
0213   Thread_queue_Context *queue_context,
0214   Watchdog_Interval     ticks
0215 )
0216 {
0217   queue_context->Timeout.ticks = ticks;
0218 }
0219 
0220 /**
0221  * @brief Sets the timeout argument in the thread queue context.
0222  *
0223  * @param[out] queue_context is the thread queue context.
0224  *
0225  * @param arg is the timeout argument.
0226  *
0227  * @param absolute is true, if the timeout shall be absolute, otherwise it
0228  *   shall be relative to the current time of the clock.
0229  *
0230  * @see _Thread_queue_Enqueue().
0231  */
0232 static inline void
0233 _Thread_queue_Context_set_timeout_argument(
0234   Thread_queue_Context *queue_context,
0235   const void           *arg,
0236   bool                  absolute
0237 )
0238 {
0239   queue_context->Timeout.arg = arg;
0240   queue_context->timeout_absolute = absolute;
0241 }
0242 
0243 /**
0244  * @brief Sets the enqueue callout in the thread queue context.
0245  *
0246  * @param[out] queue_context The thread queue context.
0247  * @param enqueue_callout The enqueue callout.
0248  *
0249  * @see _Thread_queue_Enqueue().
0250  */
0251 static inline void
0252 _Thread_queue_Context_set_enqueue_callout(
0253   Thread_queue_Context         *queue_context,
0254   Thread_queue_Enqueue_callout  enqueue_callout
0255 )
0256 {
0257   queue_context->enqueue_callout = enqueue_callout;
0258 }
0259 
0260 /**
0261  * @brief Sets the do nothing enqueue callout in the thread queue context.
0262  *
0263  * @param[out] queue_context The thread queue context.
0264  *
0265  * @see _Thread_queue_Enqueue().
0266  */
0267 static inline void
0268 _Thread_queue_Context_set_enqueue_do_nothing_extra(
0269   Thread_queue_Context *queue_context
0270 )
0271 {
0272   queue_context->enqueue_callout = _Thread_queue_Enqueue_do_nothing_extra;
0273 }
0274 
0275 /**
0276  * @brief Sets the enqueue callout to add a relative monotonic timeout in
0277  * ticks.
0278  *
0279  * @param[out] queue_context The thread queue context.
0280  * @param ticks The timeout in ticks.
0281  *
0282  * @see _Thread_queue_Enqueue().
0283  */
0284 static inline void
0285 _Thread_queue_Context_set_enqueue_timeout_ticks(
0286   Thread_queue_Context *queue_context,
0287   Watchdog_Interval     ticks
0288 )
0289 {
0290   queue_context->Timeout.ticks = ticks;
0291   queue_context->enqueue_callout = _Thread_queue_Add_timeout_ticks;
0292 }
0293 
0294 /**
0295  * @brief Sets the enqueue callout to add a timeout in timespec format using
0296  *   CLOCK_MONOTONIC.
0297  *
0298  * @param[out] queue_context is the thread queue context.
0299  *
0300  * @param timeout is the absolute or relative timeout.
0301  *
0302  * @param absolute is true, if the timeout shall be absolute, otherwise it
0303  *   shall be relative to the current time of the clock.
0304  *
0305  * @see _Thread_queue_Enqueue().
0306  */
0307 static inline void
0308 _Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
0309   Thread_queue_Context  *queue_context,
0310   const struct timespec *timeout,
0311   bool                   absolute
0312 )
0313 {
0314   queue_context->Timeout.arg = timeout;
0315   queue_context->timeout_absolute = absolute;
0316   queue_context->enqueue_callout =
0317     _Thread_queue_Add_timeout_monotonic_timespec;
0318 }
0319 
0320 /**
0321  * @brief Sets the enqueue callout to add a timeout in timespec format using
0322  *   CLOCK_REALTIME.
0323  *
0324  * @param[out] queue_context is the thread queue context.
0325  *
0326  * @param timeout is the absolute or relative timeout.
0327  *
0328  * @param absolute is true, if the timeout shall be absolute, otherwise it
0329  *   shall be relative to the current time of the clock.
0330  *
0331  * @see _Thread_queue_Enqueue().
0332  */
0333 static inline void
0334 _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
0335   Thread_queue_Context  *queue_context,
0336   const struct timespec *timeout,
0337   bool                   absolute
0338 )
0339 {
0340   queue_context->Timeout.arg = timeout;
0341   queue_context->timeout_absolute = absolute;
0342   queue_context->enqueue_callout = _Thread_queue_Add_timeout_realtime_timespec;
0343 }
0344 
0345 /**
0346  * @brief Sets the deadlock callout in the thread queue
0347  * context.
0348  *
0349  * A deadlock callout must be provided for _Thread_queue_Enqueue()
0350  * operations that operate on thread queues which may have an owner, e.g. mutex
0351  * objects.  Available deadlock callouts are _Thread_queue_Deadlock_status()
0352  * and _Thread_queue_Deadlock_fatal().
0353  *
0354  * @param[out] queue_context The thread queue context.
0355  * @param deadlock_callout The deadlock callout.
0356  *
0357  * @see _Thread_queue_Enqueue().
0358  */
0359 static inline void _Thread_queue_Context_set_deadlock_callout(
0360   Thread_queue_Context          *queue_context,
0361   Thread_queue_Deadlock_callout  deadlock_callout
0362 )
0363 {
0364   queue_context->deadlock_callout = deadlock_callout;
0365 }
0366 
0367 /**
0368  * @brief Clears the priority update count of the thread queue context.
0369  *
0370  * @param[out] queue_context The thread queue context to clear the priority
0371  * update count.
0372  */
0373 static inline void _Thread_queue_Context_clear_priority_updates(
0374   Thread_queue_Context *queue_context
0375 )
0376 {
0377   queue_context->Priority.update_count = 0;
0378 }
0379 
0380 /**
0381  * @brief Returns the priority update count of the thread queue context.
0382  *
0383  * @param queue_context The thread queue context to get the priority update
0384  *      count of.
0385  *
0386  * @return The priority update count of @a queue_context.
0387  */
0388 static inline size_t _Thread_queue_Context_get_priority_updates(
0389   const Thread_queue_Context *queue_context
0390 )
0391 {
0392   return queue_context->Priority.update_count;
0393 }
0394 
0395 /**
0396  * @brief Sets the priority update count of the thread queue context.
0397  *
0398  * @param[out] queue_context The thread queue context to set the priority
0399  *      update count of.
0400  * @param update_count The priority update count.
0401  */
0402 static inline void _Thread_queue_Context_restore_priority_updates(
0403   Thread_queue_Context *queue_context,
0404   size_t                update_count
0405 )
0406 {
0407   queue_context->Priority.update_count = update_count;
0408 }
0409 
0410 /**
0411  * @brief Adds a priority update of the thread to the thread queue context.
0412  *
0413  * @param[in, out] queue_context The thread queue context to increase the
0414  *      priority update count of and set the_thread in its Priority update
0415  *      array.
0416  * @param the_thread The thread for the priority update.
0417  */
0418 static inline void _Thread_queue_Context_add_priority_update(
0419   Thread_queue_Context *queue_context,
0420   Thread_Control       *the_thread
0421 )
0422 {
0423   size_t n;
0424 
0425   n = queue_context->Priority.update_count;
0426   _Assert( n < RTEMS_ARRAY_SIZE( queue_context->Priority.update ) );
0427 
0428   queue_context->Priority.update_count = n + 1;
0429   queue_context->Priority.update[ n ] = the_thread;
0430 }
0431 
0432 #define _Thread_queue_Context_ISR_disable( queue_context, level ) \
0433   do { \
0434     _ISR_Local_disable( level ); \
0435     _ISR_lock_ISR_disable_profile( \
0436       &( queue_context )->Lock_context.Lock_context \
0437     ) \
0438   } while ( 0 )
0439 
0440 /**
0441  * @brief Sets the thread queue context ISR level.
0442  *
0443  * @param[out] queue_context The thread queue context to set the ISR level of.
0444  * @param level The ISR level to set @a queue_context to.
0445  */
0446 static inline void _Thread_queue_Context_set_ISR_level(
0447   Thread_queue_Context *queue_context,
0448   ISR_Level             level
0449 )
0450 {
0451   _ISR_lock_Context_set_level(
0452     &queue_context->Lock_context.Lock_context,
0453     level
0454   );
0455 }
0456 
0457 /**
0458  * @brief Disables dispatching in a critical section.
0459  *
0460  * @param queue_context The thread queue context to get the lock context from.
0461  *
0462  * @return The current processor.
0463  */
0464 static inline Per_CPU_Control *_Thread_queue_Dispatch_disable(
0465   Thread_queue_Context *queue_context
0466 )
0467 {
0468   return _Thread_Dispatch_disable_critical(
0469     &queue_context->Lock_context.Lock_context
0470   );
0471 }
0472 
0473 /**
0474  * @brief Sets the MP callout in the thread queue context.
0475  *
0476  * @param[out] queue_context The thread queue context.
0477  * @param mp_callout Callout to unblock the thread in case it is actually a
0478  *   thread proxy.  This parameter is only used on multiprocessing
0479  *   configurations.  Used by thread queue extract and unblock methods for
0480  *   objects with multiprocessing (MP) support.
0481  */
0482 #if defined(RTEMS_MULTIPROCESSING)
0483 static inline void _Thread_queue_Context_set_MP_callout(
0484   Thread_queue_Context    *queue_context,
0485   Thread_queue_MP_callout  mp_callout
0486 )
0487 {
0488   queue_context->mp_callout = mp_callout;
0489 }
0490 #else
0491 #define _Thread_queue_Context_set_MP_callout( queue_context, mp_callout ) \
0492   do { \
0493     (void) queue_context; \
0494   } while ( 0 )
0495 #endif
0496 
0497 #if defined(RTEMS_SMP)
0498 /**
0499  * @brief Closes the gate.
0500  *
0501  * @param[out] gate The gate to close.
0502  */
0503 static inline void _Thread_queue_Gate_close(
0504   Thread_queue_Gate *gate
0505 )
0506 {
0507   _Atomic_Store_uint( &gate->go_ahead, 0, ATOMIC_ORDER_RELAXED );
0508 }
0509 
0510 /**
0511  * @brief Adds the gate to the chain.
0512  *
0513  * @param[in, out] chain The chain to add the gate to.
0514  * @param gate The gate to add to the chain.
0515  */
0516 static inline void _Thread_queue_Gate_add(
0517   Chain_Control     *chain,
0518   Thread_queue_Gate *gate
0519 )
0520 {
0521   _Chain_Append_unprotected( chain, &gate->Node );
0522 }
0523 
0524 /**
0525  * @brief Opens the gate.
0526  *
0527  * @param[out] gate The gate to open.
0528  */
0529 static inline void _Thread_queue_Gate_open(
0530   Thread_queue_Gate *gate
0531 )
0532 {
0533   _Atomic_Store_uint( &gate->go_ahead, 1, ATOMIC_ORDER_RELAXED );
0534 }
0535 
0536 /**
0537  * @brief Waits on a gate to open.
0538  *
0539  * Performs busy waiting.
0540  *
0541  * @param gate The gate to wait for.
0542  */
0543 static inline void _Thread_queue_Gate_wait(
0544   Thread_queue_Gate *gate
0545 )
0546 {
0547   while ( _Atomic_Load_uint( &gate->go_ahead, ATOMIC_ORDER_RELAXED ) == 0 ) {
0548     /* Wait */
0549   }
0550 }
0551 #endif
0552 
0553 /**
0554  * @brief Initializes the thread queue heads.
0555  *
0556  * @param[out] heads The thread queue heads to initialize.
0557  */
0558 static inline void _Thread_queue_Heads_initialize(
0559   Thread_queue_Heads *heads
0560 )
0561 {
0562 #if defined(RTEMS_SMP)
0563   size_t i;
0564 
0565   for ( i = 0; i < _Scheduler_Count; ++i ) {
0566     _Chain_Initialize_node( &heads->Priority[ i ].Node );
0567     _Priority_Initialize_empty( &heads->Priority[ i ].Queue );
0568     heads->Priority[ i ].Queue.scheduler = &_Scheduler_Table[ i ];
0569   }
0570 #endif
0571 
0572   _Chain_Initialize_empty( &heads->Free_chain );
0573   _Chain_Initialize_node( &heads->Free_node );
0574 }
0575 
0576 /**
0577  * @brief Initializes the thread queue queue with the given name.
0578  *
0579  * @param[out] queue The thread queue queue to initialize.
0580  * @param name The name for the @a queue.
0581  */
0582 static inline void _Thread_queue_Queue_initialize(
0583   Thread_queue_Queue *queue,
0584   const char         *name
0585 )
0586 {
0587 #if defined(RTEMS_SMP)
0588   _SMP_ticket_lock_Initialize( &queue->Lock );
0589 #endif
0590   queue->heads = NULL;
0591   queue->owner = NULL;
0592   queue->name = name;
0593 }
0594 
0595 /**
0596  * @brief Acquires the thread queue queue in a critical section.
0597  *
0598  * @param queue The thread queue queue to acquire in a critical section.
0599  * @param lock_stats The lock statistics.
0600  * @param[out] lock_context The interrupt lock context.
0601  */
0602 static inline void _Thread_queue_Queue_do_acquire_critical(
0603   Thread_queue_Queue *queue,
0604 #if defined(RTEMS_SMP) && defined(RTEMS_PROFILING)
0605   SMP_lock_Stats     *lock_stats,
0606 #endif
0607   ISR_lock_Context   *lock_context
0608 )
0609 {
0610 #if defined(RTEMS_SMP)
0611   _SMP_ticket_lock_Acquire(
0612     &queue->Lock,
0613     lock_stats,
0614     &lock_context->Lock_context.Stats_context
0615   );
0616 #else
0617   (void) queue;
0618   (void) lock_context;
0619 #endif
0620 }
0621 
0622 #if defined(RTEMS_SMP) && defined( RTEMS_PROFILING )
0623   #define \
0624     _Thread_queue_Queue_acquire_critical( queue, lock_stats, lock_context ) \
0625     _Thread_queue_Queue_do_acquire_critical( queue, lock_stats, lock_context )
0626 #else
0627   #define \
0628     _Thread_queue_Queue_acquire_critical( queue, lock_stats, lock_context ) \
0629     _Thread_queue_Queue_do_acquire_critical( queue, lock_context )
0630 #endif
0631 
0632 /**
0633  * @brief Releases the thread queue queue in a critical section.
0634  *
0635  * @param queue The thread queue queue to release in a critical section.
0636  * @param[out] lock_context The interrupt lock context.
0637  */
0638 static inline void _Thread_queue_Queue_release_critical(
0639   Thread_queue_Queue *queue,
0640   ISR_lock_Context   *lock_context
0641 )
0642 {
0643 #if defined(RTEMS_SMP)
0644   _SMP_ticket_lock_Release(
0645     &queue->Lock,
0646     &lock_context->Lock_context.Stats_context
0647   );
0648 #else
0649   (void) queue;
0650   (void) lock_context;
0651 #endif
0652 }
0653 
0654 /**
0655  * @brief Releases the thread queue queue and enables interrupts.
0656  *
0657  * @param queue The thread queue queue to release.
0658  * @param[out] lock_context The interrupt lock context to enable interrupts.
0659  */
0660 static inline void _Thread_queue_Queue_release(
0661   Thread_queue_Queue *queue,
0662   ISR_lock_Context   *lock_context
0663 )
0664 {
0665   _Thread_queue_Queue_release_critical( queue, lock_context );
0666   _ISR_lock_ISR_enable( lock_context );
0667 }
0668 
0669 /**
0670  * @brief Copies the thread queue name to the specified buffer.
0671  *
0672  * @param queue The actual thread queue.
0673  * @param[out] buffer The buffer for the thread queue name copy.
0674  * @param buffer_size The buffer size in characters.
0675  * @param id The object identifier in case the thread queue is embedded in
0676  *   an object with identifier, otherwise it is set to 0.
0677  *
0678  * @return The length of the thread queue name.  May be greater than or equal
0679  *  to the buffer size if truncation occurred.
0680  */
0681 size_t _Thread_queue_Queue_get_name_and_id(
0682   const Thread_queue_Queue *queue,
0683   char                     *buffer,
0684   size_t                    buffer_size,
0685   Objects_Id               *id
0686 );
0687 
0688 /**
0689  * @brief Acquires the thread queue control in a critical section.
0690  *
0691  * @param the_thread_queue The thread queue control to acquire.
0692  * @param[out] lock_context The interrupt lock context.
0693  */
0694 #if defined(RTEMS_SMP)
0695 void _Thread_queue_Do_acquire_critical(
0696   Thread_queue_Control *the_thread_queue,
0697   ISR_lock_Context     *lock_context
0698 );
0699 #else
0700 static inline void _Thread_queue_Do_acquire_critical(
0701   Thread_queue_Control *the_thread_queue,
0702   ISR_lock_Context     *lock_context
0703 )
0704 {
0705   (void) the_thread_queue;
0706   (void) lock_context;
0707 }
0708 #endif
0709 
0710 /**
0711  * @brief Acquires the thread queue control in a critical section.
0712  *
0713  * @param the_thread_queue The thread queue control to acquire.
0714  * @param[out] lock_context The interrupt lock context.
0715  */
0716 static inline void _Thread_queue_Acquire_critical(
0717   Thread_queue_Control *the_thread_queue,
0718   Thread_queue_Context *queue_context
0719 )
0720 {
0721   _Thread_queue_Do_acquire_critical(
0722     the_thread_queue,
0723     &queue_context->Lock_context.Lock_context
0724   );
0725 }
0726 
0727 /**
0728  * @brief Acquires the thread queue control in a critical section.
0729  *
0730  * @param the_thread_queue The thread queue control to acquire.
0731  * @param[out] queue_context The thread queue context.
0732  */
0733 #if defined(RTEMS_SMP)
0734 void _Thread_queue_Acquire(
0735   Thread_queue_Control *the_thread_queue,
0736   Thread_queue_Context *queue_context
0737 );
0738 #else
0739 static inline void _Thread_queue_Acquire(
0740   Thread_queue_Control *the_thread_queue,
0741   Thread_queue_Context *queue_context
0742 )
0743 {
0744   (void) the_thread_queue;
0745   _ISR_lock_ISR_disable( &queue_context->Lock_context.Lock_context );
0746 }
0747 #endif
0748 
0749 /**
0750  * @brief Checks if the thread queue control is the owner of the lock.
0751  *
0752  * @param the_thread_queue The thread queue control for the verification.
0753  *
0754  * @retval true The thread queue control is the owner of the lock.
0755  * @retval false The thread queue control is not the owner of the lock.
0756  */
0757 #if defined(RTEMS_DEBUG)
0758 static inline bool _Thread_queue_Is_lock_owner(
0759   const Thread_queue_Control *the_thread_queue
0760 )
0761 {
0762 #if defined(RTEMS_SMP)
0763   return the_thread_queue->owner == _SMP_lock_Who_am_I();
0764 #else
0765   return _ISR_Get_level() != 0;
0766 #endif
0767 }
0768 #endif
0769 
0770 /**
0771  * @brief Releases the thread queue control in a critical section.
0772  *
0773  * @param the_thread_queue The thread queue control to release.
0774  * @param[out] lock_context The interrupt lock context.
0775  */
0776 #if defined(RTEMS_SMP)
0777 void _Thread_queue_Do_release_critical(
0778   Thread_queue_Control *the_thread_queue,
0779   ISR_lock_Context     *lock_context
0780 );
0781 #else
0782 static inline void _Thread_queue_Do_release_critical(
0783   Thread_queue_Control *the_thread_queue,
0784   ISR_lock_Context     *lock_context
0785 )
0786 {
0787   (void) the_thread_queue;
0788   (void) lock_context;
0789   _Assert( _Thread_queue_Is_lock_owner( the_thread_queue ) );
0790 }
0791 #endif
0792 
0793 /**
0794  * @brief Releases the thread queue control in a critical section.
0795  *
0796  * @param the_thread_queue The thread queue control to release.
0797  * @param[out] queue_context The thread queue context.
0798  */
0799 static inline void _Thread_queue_Release_critical(
0800   Thread_queue_Control *the_thread_queue,
0801   Thread_queue_Context *queue_context
0802 )
0803 {
0804   _Thread_queue_Do_release_critical(
0805     the_thread_queue,
0806     &queue_context->Lock_context.Lock_context
0807   );
0808 }
0809 
0810 /**
0811  * @brief Releases the thread queue control and enables interrupts.
0812  *
0813  * @param the_thread_queue The thread queue control to release.
0814  * @param[out] queue_context The thread queue context.
0815  */
0816 #if defined(RTEMS_SMP)
0817 void _Thread_queue_Release(
0818   Thread_queue_Control *the_thread_queue,
0819   Thread_queue_Context *queue_context
0820 );
0821 #else
0822 static inline void _Thread_queue_Release(
0823   Thread_queue_Control *the_thread_queue,
0824   Thread_queue_Context *queue_context
0825 )
0826 {
0827   (void) the_thread_queue;
0828   _Assert( _Thread_queue_Is_lock_owner( the_thread_queue ) );
0829   _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context );
0830 }
0831 #endif
0832 
0833 /**
0834  * @brief Blocks the thread and places it on the thread queue.
0835  *
0836  * This enqueues the thread on the thread queue, blocks the thread, and
0837  * optionally starts the thread timer in case the timeout discipline is not
0838  * WATCHDOG_NO_TIMEOUT. Timeout discipline and value are in the queue_context.
0839  *
0840  * The caller must be the owner of the thread queue lock.  This function will
0841  * release the thread queue lock and register it as the new thread lock.
0842  * Thread dispatching is disabled before the thread queue lock is released.
0843  * Thread dispatching is enabled once the sequence to block the thread is
0844  * complete.  The operation to enqueue the thread on the queue is protected by
0845  * the thread queue lock.  This makes it possible to use the thread queue lock
0846  * to protect the state of objects embedding the thread queue and directly
0847  * enter _Thread_queue_Enqueue() in case the thread must block.
0848  *
0849  * The thread queue context must be set up with the following functions,
0850  * otherwise the behaviour is unpredictable
0851  *
0852  * - _Thread_queue_Context_set_thread_state(),
0853  *
0854  * - _Thread_queue_Context_set_enqueue_callout() or
0855  *   _Thread_queue_Context_set_enqueue_do_nothing_extra() or
0856  *   _Thread_queue_Context_set_enqueue_timeout_ticks() or
0857  *   _Thread_queue_Context_set_enqueue_timeout_monotonic_timespec() or
0858  *   _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(),
0859  *
0860  * - _Thread_queue_Context_set_deadlock_callout().
0861  *
0862  * @code
0863  * #include <rtems/score/threadqimpl.h>
0864  * #include <rtems/score/statesimpl.h>
0865  *
0866  * #define MUTEX_TQ_OPERATIONS &_Thread_queue_Operations_priority
0867  *
0868  * typedef struct {
0869  *   Thread_queue_Control Queue;
0870  * } Mutex;
0871  *
0872  * void _Mutex_Obtain( Mutex *mutex )
0873  * {
0874  *   Thread_queue_Context  queue_context;
0875  *   Thread_Control       *executing;
0876  *
0877  *   _Thread_queue_Context_initialize( &queue_context );
0878  *   _Thread_queue_Acquire( &mutex->Queue, queue_context );
0879  *
0880  *   executing = _Thread_Executing;
0881  *
0882  *   if ( mutex->Queue.owner == NULL ) {
0883  *     mutex->Queue.owner = executing;
0884  *     _Thread_queue_Release( &mutex->Queue, queue_context );
0885  *   } else {
0886  *     _Thread_queue_Context_set_thread_state(
0887  *       &queue_context,
0888  *       STATES_WAITING_FOR_MUTEX
0889  *     );
0890  *     _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
0891  *     _Thread_queue_Context_set_deadlock_callout(
0892  *       queue_context,
0893  *       _Thread_queue_Deadlock_fatal
0894  *     );
0895  *     _Thread_queue_Enqueue(
0896  *       &mutex->Queue.Queue,
0897  *       MUTEX_TQ_OPERATIONS,
0898  *       executing,
0899  *       &queue_context
0900  *     );
0901  *   }
0902  * }
0903  * @endcode
0904  *
0905  * @param queue The actual thread queue.
0906  * @param operations The thread queue operations.
0907  * @param[in, out] the_thread The thread to enqueue.
0908  * @param[in, out] queue_context The thread queue context of the lock acquire.
0909  */
0910 void _Thread_queue_Enqueue(
0911   Thread_queue_Queue            *queue,
0912   const Thread_queue_Operations *operations,
0913   Thread_Control                *the_thread,
0914   Thread_queue_Context          *queue_context
0915 );
0916 
0917 #if defined(RTEMS_SMP)
0918 /**
0919  * @brief Enqueues the thread on the thread queue and busy waits for dequeue.
0920  *
0921  * Optionally starts the thread timer in case the timeout discipline is not
0922  * WATCHDOG_NO_TIMEOUT. Timeout discipline and value are in the queue_context.
0923  *
0924  * The caller must be the owner of the thread queue lock.  This function will
0925  * release the thread queue lock and register it as the new thread lock.
0926  *
0927  * The thread priorities of the owner and the are updated with respect to the
0928  * scheduler.  The sticky level of the thread is incremented.  A thread
0929  * dispatch is performed if necessary.
0930  *
0931  * Afterwards, the thread busy waits on the thread wait flags until a timeout
0932  * occurs or the thread queue is surrendered to this thread.  So, it sticks to
0933  * the processor instead of blocking with respect to the scheduler.
0934  *
0935  * @param queue The actual thread queue.
0936  * @param operations The thread queue operations.
0937  * @param[in, out] the_thread The thread to enqueue.
0938  * @param[in, out] queue_context The thread queue context of the lock acquire.
0939  */
0940 Status_Control _Thread_queue_Enqueue_sticky(
0941   Thread_queue_Queue            *queue,
0942   const Thread_queue_Operations *operations,
0943   Thread_Control                *the_thread,
0944   Thread_queue_Context          *queue_context
0945 );
0946 #endif
0947 
0948 /**
0949  * @brief Extracts the thread from the thread queue, restores the default wait
0950  * operations and restores the default thread lock.
0951  *
0952  * The caller must be the owner of the thread queue lock.  The thread queue
0953  * lock is not released.
0954  *
0955  * @param queue The actual thread queue.
0956  * @param operations The thread queue operations.
0957  * @param[in, out] the_thread The thread to extract.
0958  * @param[in, out] queue_context The thread queue context.
0959  *
0960  * @return Returns the unblock indicator.  True indicates, that this thread
0961  * must be unblocked by the scheduler using _Thread_Remove_timer_and_unblock(),
0962  * and false otherwise.  In case false is returned, then the thread queue
0963  * enqueue procedure was interrupted.  Thus it will unblock itself and the
0964  * thread wait information is no longer accessible, since this thread may
0965  * already block on another resource in an SMP configuration.
0966  */
0967 bool _Thread_queue_Extract_locked(
0968   Thread_queue_Queue            *queue,
0969   const Thread_queue_Operations *operations,
0970   Thread_Control                *the_thread,
0971   Thread_queue_Context          *queue_context
0972 );
0973 
0974 /**
0975  * @brief Resumes the extracted or surrendered thread.
0976  *
0977  * This function makes the thread ready again.  If necessary, the thread is
0978  * unblocked and its thread timer removed.
0979  *
0980  * The thread shall have been extracted from the thread queue or surrendered by
0981  * the thread queue right before the call to this function.  The caller shall
0982  * be the owner of the thread queue lock.
0983  *
0984  * @param queue is the actual thread queue.
0985  * @param[in, out] the_thread is the thread to make ready and unblock.
0986  * @param[in, out] queue_context is the thread queue context.
0987  */
0988 void _Thread_queue_Resume(
0989   Thread_queue_Queue   *queue,
0990   Thread_Control       *the_thread,
0991   Thread_queue_Context *queue_context
0992 );
0993 
0994 /**
0995  * @brief Extracts thread from thread queue.
0996  *
0997  * This routine removes @a the_thread its thread queue
0998  * and cancels any timeouts associated with this blocking.
0999  *
1000  * @param[in, out] the_thread The pointer to a thread control block that
1001  *     is to be removed
1002  */
1003 void _Thread_queue_Extract( Thread_Control *the_thread );
1004 
1005 /**
1006  * @brief Surrenders the thread queue previously owned by the thread to the
1007  * first enqueued thread.
1008  *
1009  * The owner of the thread queue must be set to NULL by the caller.
1010  *
1011  * This function releases the thread queue lock.  In addition it performs a
1012  * thread dispatch if necessary.
1013  *
1014  * @param[in, out] queue The actual thread queue.
1015  * @param heads The thread queue heads.  It must not be NULL.
1016  * @param previous_owner The previous owner thread surrendering the thread
1017  *   queue.
1018  * @param queue_context The thread queue context of the lock acquire.
1019  * @param operations The thread queue operations.
1020  */
1021 void _Thread_queue_Surrender(
1022   Thread_queue_Queue            *queue,
1023   Thread_queue_Heads            *heads,
1024   Thread_Control                *previous_owner,
1025   Thread_queue_Context          *queue_context,
1026   const Thread_queue_Operations *operations
1027 );
1028 
1029 /**
1030  * @brief Surrenders the thread queue previously owned by the thread to the
1031  * first enqueued thread.
1032  *
1033  * The owner of the thread queue must be set to NULL by the caller.
1034  *
1035  * This function releases the thread queue lock.  In addition it performs a
1036  * thread dispatch if necessary.
1037  *
1038  * @param[in, out] queue The actual thread queue.
1039  * @param heads The thread queue heads.  It must not be NULL.
1040  * @param queue_context The thread queue context of the lock acquire.
1041  * @param operations The thread queue operations.
1042  */
1043 void _Thread_queue_Surrender_no_priority(
1044   Thread_queue_Queue            *queue,
1045   Thread_queue_Heads            *heads,
1046   Thread_queue_Context          *queue_context,
1047   const Thread_queue_Operations *operations
1048 );
1049 
1050 /**
1051  * @brief Surrenders the thread queue previously owned by the thread to the
1052  * first enqueued thread.
1053  *
1054  * The owner of the thread queue must be set to NULL by the caller.
1055  *
1056  * This function releases the thread queue lock.  In addition it performs a
1057  * thread dispatch if necessary.
1058  *
1059  * @param[in, out] queue The actual thread queue.
1060  * @param heads The thread queue heads.  It must not be NULL.
1061  * @param queue_context The thread queue context of the lock acquire.
1062  * @param operations The thread queue operations.
1063  */
1064 Status_Control _Thread_queue_Surrender_priority_ceiling(
1065   Thread_queue_Queue            *queue,
1066   Thread_Control                *executing,
1067   Priority_Node                 *ceiling_priority,
1068   Thread_queue_Context          *queue_context,
1069   const Thread_queue_Operations *operations
1070 );
1071 
1072 #if defined(RTEMS_SMP)
1073 /**
1074  * @brief Surrenders the thread queue previously owned by the thread to the
1075  * first enqueued thread.
1076  *
1077  * The owner of the thread queue must be set to NULL by the caller.
1078  *
1079  * The caller must be the owner of the thread queue lock.  This function will
1080  * release the thread queue.
1081  *
1082  * The thread priorities of the previous owner and the new owner are updated.  The
1083  * sticky level of the previous owner is decremented.  A thread dispatch is
1084  * performed if necessary.
1085  *
1086  * @param[in, out] queue The actual thread queue.
1087  * @param heads The thread queue heads.  It must not be NULL.
1088  * @param[in, out] previous_owner The previous owner thread surrendering the thread
1089  *   queue.
1090  * @param queue_context The thread queue context of the lock acquire.
1091  * @param operations The thread queue operations.
1092  */
1093 void _Thread_queue_Surrender_sticky(
1094   Thread_queue_Queue            *queue,
1095   Thread_queue_Heads            *heads,
1096   Thread_Control                *previous_owner,
1097   Thread_queue_Context          *queue_context,
1098   const Thread_queue_Operations *operations
1099 );
1100 #endif
1101 
1102 /**
1103  * @brief Checks if the thread queue queue is empty.
1104  *
1105  * @param queue The thread queue for the verification.
1106  *
1107  * @retval true @a queue is empty.
1108  * @retval false @a queue is not empty.
1109  */
1110 static inline bool _Thread_queue_Is_empty(
1111   const Thread_queue_Queue *queue
1112 )
1113 {
1114   return queue->heads == NULL;
1115 }
1116 
1117 /**
1118  * @brief Returns the first thread on the thread queue if it exists, otherwise
1119  * @c NULL.
1120  *
1121  * @param the_thread_queue The thread queue.
1122  *
1123  * @retval first The first thread on the thread queue according to the enqueue
1124  * order.
1125  * @retval NULL No thread is present on the thread queue.
1126  */
1127 Thread_Control *_Thread_queue_First(
1128   Thread_queue_Control          *the_thread_queue,
1129   const Thread_queue_Operations *operations
1130 );
1131 
1132 /**
1133  * @brief Thread queue flush filter function.
1134  *
1135  * Called under protection of the thread queue lock by
1136  * _Thread_queue_Flush_critical() to optionally alter the thread wait
1137  * information and control the iteration.
1138  *
1139  * @param the_thread The thread to extract.  This is the first parameter to
1140  *   optimize for architectures that use the same register for the first
1141  *   parameter and the return value.
1142  * @param queue The actual thread queue.
1143  * @param queue_context The thread queue context of the lock acquire.  May be
1144  *   used to pass additional data to the filter function via an overlay
1145  *   structure.  The filter function should not release or acquire the thread
1146  *   queue lock.
1147  *
1148  * @retval the_thread Extract this thread.
1149  * @retval NULL Do not extract this thread and stop the thread queue flush
1150  *   operation.  Threads that are already extracted will complete the flush
1151  *   operation.
1152  */
1153 typedef Thread_Control *( *Thread_queue_Flush_filter )(
1154   Thread_Control       *the_thread,
1155   Thread_queue_Queue   *queue,
1156   Thread_queue_Context *queue_context
1157 );
1158 
1159 /**
1160  * @brief Default thread queue flush filter function.
1161  *
1162  * @param the_thread The thread to extract.
1163  * @param queue This parameter is unused.
1164  * @param queue_context This parameter is unused.
1165  *
1166  * @retval the_thread Extract this thread.
1167  */
1168 Thread_Control *_Thread_queue_Flush_default_filter(
1169   Thread_Control       *the_thread,
1170   Thread_queue_Queue   *queue,
1171   Thread_queue_Context *queue_context
1172 );
1173 
1174 /**
1175  * @brief Status unavailable thread queue flush filter function.
1176  *
1177  * Sets the thread wait return code of the thread to STATUS_UNAVAILABLE.
1178  *
1179  * @param[out] the_thread The thread to extract.
1180  * @param queue This parameter is unused.
1181  * @param queue_context This parameter is unused.
1182  *
1183  * @retval the_thread Extract this thread.
1184  */
1185 Thread_Control *_Thread_queue_Flush_status_unavailable(
1186   Thread_Control       *the_thread,
1187   Thread_queue_Queue   *queue,
1188   Thread_queue_Context *queue_context
1189 );
1190 
1191 /**
1192  * @brief Status object was deleted thread queue flush filter function.
1193  *
1194  * Sets the thread wait return code of the thread to STATUS_OBJECT_WAS_DELETED
1195  *
1196  * @param[out] the_thread The thread to extract.
1197  * @param queue This parameter is unused.
1198  * @param queue_context This parameter is unused.
1199  *
1200  * @retval the_thread Extract this thread.
1201  */
1202 Thread_Control *_Thread_queue_Flush_status_object_was_deleted(
1203   Thread_Control       *the_thread,
1204   Thread_queue_Queue   *queue,
1205   Thread_queue_Context *queue_context
1206 );
1207 
1208 /**
1209  * @brief Unblocks all threads enqueued on the thread queue.
1210  *
1211  * This function iteratively extracts the first enqueued thread of the thread
1212  * queue until the thread queue is empty or the filter function indicates a
1213  * stop.  The thread timers of the extracted threads are cancelled.  The
1214  * extracted threads are unblocked.
1215  *
1216  * @param queue The actual thread queue.
1217  * @param operations The thread queue operations.
1218  * @param filter The filter functions is called for each thread to extract from
1219  *   the thread queue.  It may be used to alter the thread under protection of
1220  *   the thread queue lock, for example to set the thread wait return code.
1221  *   The return value of the filter function controls if the thread queue flush
1222  *   operation should stop or continue.
1223  * @param queue_context The thread queue context of the lock acquire.  May be
1224  *   used to pass additional data to the filter function via an overlay
1225  *   structure.  The filter function should not release or acquire the thread
1226  *   queue lock.
1227  *
1228  * @return The count of extracted threads.
1229  */
1230 size_t _Thread_queue_Flush_critical(
1231   Thread_queue_Queue            *queue,
1232   const Thread_queue_Operations *operations,
1233   Thread_queue_Flush_filter      filter,
1234   Thread_queue_Context          *queue_context
1235 );
1236 
1237 /**
1238  * @brief Initializes the thread queue control to the given name.
1239  *
1240  * @param[out] the_thread_queue The thread queue control to initialize.
1241  * @param name The name for @a the_thread_queue.
1242  */
1243 void _Thread_queue_Initialize(
1244   Thread_queue_Control *the_thread_queue,
1245   const char           *name
1246 );
1247 
1248 #if defined(RTEMS_SMP) && defined(RTEMS_DEBUG) && defined(RTEMS_PROFILING)
1249   #define THREAD_QUEUE_INITIALIZER( _name ) \
1250     { \
1251       .Lock_stats = SMP_LOCK_STATS_INITIALIZER( _name ), \
1252       .owner = SMP_LOCK_NO_OWNER, \
1253       .Queue = { \
1254         .Lock = SMP_TICKET_LOCK_INITIALIZER, \
1255         .heads = NULL, \
1256         .owner = NULL, \
1257         .name = _name \
1258       } \
1259     }
1260 #elif defined(RTEMS_SMP) && defined(RTEMS_DEBUG)
1261   #define THREAD_QUEUE_INITIALIZER( _name ) \
1262     { \
1263       .owner = SMP_LOCK_NO_OWNER, \
1264       .Queue = { \
1265         .Lock = SMP_TICKET_LOCK_INITIALIZER, \
1266         .heads = NULL, \
1267         .owner = NULL, \
1268         .name = _name \
1269       } \
1270     }
1271 #elif defined(RTEMS_SMP) && defined(RTEMS_PROFILING)
1272   #define THREAD_QUEUE_INITIALIZER( _name ) \
1273     { \
1274       .Lock_stats = SMP_LOCK_STATS_INITIALIZER( _name ), \
1275       .Queue = { \
1276         .Lock = SMP_TICKET_LOCK_INITIALIZER, \
1277         .heads = NULL, \
1278         .owner = NULL, \
1279         .name = _name \
1280       } \
1281     }
1282 #elif defined(RTEMS_SMP)
1283   #define THREAD_QUEUE_INITIALIZER( _name ) \
1284     { \
1285       .Queue = { \
1286         .Lock = SMP_TICKET_LOCK_INITIALIZER, \
1287         .heads = NULL, \
1288         .owner = NULL, \
1289         .name = _name \
1290       } \
1291     }
1292 #else
1293   #define THREAD_QUEUE_INITIALIZER( _name ) \
1294     { \
1295       .Queue = { \
1296         .heads = NULL, \
1297         .owner = NULL, \
1298         .name = _name \
1299       } \
1300     }
1301 #endif
1302 
1303 /**
1304  * @brief Destroys the thread queue.
1305  *
1306  * @param[out] the_thread_queue The thread queue to destroy.
1307  */
1308 static inline void _Thread_queue_Destroy(
1309   Thread_queue_Control *the_thread_queue
1310 )
1311 {
1312 #if defined(RTEMS_SMP)
1313   _SMP_ticket_lock_Destroy( &the_thread_queue->Queue.Lock );
1314   _SMP_lock_Stats_destroy( &the_thread_queue->Lock_stats );
1315 #endif
1316 }
1317 
1318 #if defined(RTEMS_MULTIPROCESSING)
1319 /**
1320  * @brief Does nothing.
1321  *
1322  * @param the_proxy This parameter is unused.
1323  * @param mp_id This parameter is unused.
1324  */
1325 void _Thread_queue_MP_callout_do_nothing(
1326   Thread_Control *the_proxy,
1327   Objects_Id      mp_id
1328 );
1329 
1330 bool _Thread_queue_MP_set_callout(
1331   Thread_Control             *the_thread,
1332   const Thread_queue_Context *queue_context
1333 );
1334 
1335 /**
1336  * @brief Unblocks the proxy of the thread.
1337  *
1338  * @param queue The thread queue queue.
1339  * @param the_threat The thread to unblock proxy (after casting it to Thread_Proxy_control *).
1340  */
1341 void _Thread_queue_Unblock_proxy(
1342   Thread_queue_Queue *queue,
1343   Thread_Control     *the_thread
1344 );
1345 #endif
1346 
1347 /**
1348  * @brief This is a status code to indicate if a deadlock was detected or not.
1349  */
1350 typedef enum {
1351   /**
1352    * @brief The operation did not detect a deadlock.
1353    */
1354   THREAD_QUEUE_NO_DEADLOCK,
1355 
1356   /**
1357    * @brief The operation detected a deadlock.
1358    */
1359   THREAD_QUEUE_DEADLOCK_DETECTED
1360 } Thread_queue_Deadlock_status;
1361 
1362 #if defined(RTEMS_SMP)
1363 /**
1364  * @brief Acquires the thread queue path.
1365  *
1366  * The caller must own the thread queue lock.
1367  *
1368  * An acquired thread queue path must be released by calling
1369  * _Thread_queue_Path_release() with the same thread queue context.
1370  *
1371  * @param queue is the thread queue queue.
1372  *
1373  * @param the_thread is the thread for the operation.
1374  *
1375  * @param queue_context is the thread queue context.
1376  *
1377  * @retval THREAD_QUEUE_NO_DEADLOCK No deadlock was detected.
1378  *
1379  * @retval THREAD_QUEUE_DEADLOCK_DETECTED A deadlock was detected while
1380  *   acquiring the thread queue path.  The thread queue path must still be
1381  *   released by _Thread_queue_Path_release() in this case.
1382  */
1383 Thread_queue_Deadlock_status _Thread_queue_Path_acquire(
1384   Thread_queue_Queue   *queue,
1385   Thread_Control       *the_thread,
1386   Thread_queue_Context *queue_context
1387 );
1388 
1389 /**
1390  * @brief Releases the thread queue path.
1391  *
1392  * The caller must have acquired the thread queue path with a corresponding
1393  * _Thread_queue_Path_acquire().
1394  *
1395  * @param queue_context is the thread queue context.
1396  */
1397 void _Thread_queue_Path_release(
1398   Thread_queue_Context *queue_context
1399 );
1400 #endif
1401 
1402 /**
1403  * @brief Helper structure to ensure that all objects containing a thread queue
1404  * have the right layout.
1405  *
1406  * @see _Thread_Wait_get_id() and THREAD_QUEUE_OBJECT_ASSERT().
1407  */
1408 typedef struct {
1409   Objects_Control      Object;
1410   Thread_queue_Control Wait_queue;
1411 } Thread_queue_Object;
1412 
1413 #define THREAD_QUEUE_OBJECT_ASSERT( object_type, wait_queue_member, msg ) \
1414   RTEMS_STATIC_ASSERT( \
1415     offsetof( object_type, wait_queue_member ) \
1416       == offsetof( Thread_queue_Object, Wait_queue ) \
1417     && RTEMS_HAVE_MEMBER_SAME_TYPE( \
1418       object_type, \
1419       wait_queue_member, \
1420       Thread_queue_Object, \
1421       Wait_queue \
1422     ), \
1423     msg \
1424   )
1425 
1426 #define THREAD_QUEUE_QUEUE_TO_OBJECT( queue ) \
1427   RTEMS_CONTAINER_OF( \
1428     queue, \
1429     Thread_queue_Object, \
1430     Wait_queue.Queue \
1431   )
1432 
1433 /**
1434  * @brief The default thread queue operations are used when a thread is not
1435  *   enqueued on a thread queue.
1436  *
1437  * The default operations may be used by _Thread_Priority_apply() and
1438  * _Thread_Continue() if the thread is not enqueued on a thread queue.  The
1439  * default operations do nothing.
1440  */
1441 extern const Thread_queue_Operations _Thread_queue_Operations_default;
1442 
1443 /**
1444  * @brief The FIFO thread queue operations are used when a thread is enqueued
1445  *   on a thread queue and provide FIFO ordering of enqueued threads.
1446  */
1447 extern const Thread_queue_Operations _Thread_queue_Operations_FIFO;
1448 
1449 /**
1450  * @brief The FIFO thread queue operations are used when a thread is enqueued
1451  *   on a thread queue and provide priority ordering of enqueued threads.
1452  */
1453 extern const Thread_queue_Operations _Thread_queue_Operations_priority;
1454 
1455 /**
1456  * @brief The FIFO thread queue operations are used when a thread is enqueued
1457  *   on a thread queue and provide priority ordering of enqueued threads with
1458  *   support for priority inheritance.
1459  */
1460 extern const Thread_queue_Operations _Thread_queue_Operations_priority_inherit;
1461 
1462 /**
1463  * @brief The special thread queue name to indicated that the thread queue is
1464  * embedded in an object with identifier.
1465  *
1466  * @see _Thread_queue_Object_initialize().
1467  */
1468 extern const char _Thread_queue_Object_name[];
1469 
1470 /**
1471  * @brief Initializes a thread queue embedded in an object with identifier.
1472  *
1473  * The object must have the layout specified by Thread_queue_Object.  It should
1474  * be ensured with the THREAD_QUEUE_OBJECT_ASSERT() static assertion.
1475  *
1476  * @param[out] the_thread_queue The thread queue.
1477  */
1478 void _Thread_queue_Object_initialize(
1479   Thread_queue_Control *the_thread_queue
1480 );
1481 
1482 /** @} */
1483 
1484 #ifdef __cplusplus
1485 }
1486 #endif
1487 
1488 #endif
1489 /* end of include file */