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 used by the implementation and the
0010  *   @ref RTEMSImplApplConfig.
0011  */
0012 
0013 /*
0014  *  COPYRIGHT (c) 1989-2014.
0015  *  On-Line Applications Research Corporation (OAR).
0016  *
0017  * Redistribution and use in source and binary forms, with or without
0018  * modification, are permitted provided that the following conditions
0019  * are met:
0020  * 1. Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  * 2. Redistributions in binary form must reproduce the above copyright
0023  *    notice, this list of conditions and the following disclaimer in the
0024  *    documentation and/or other materials provided with the distribution.
0025  *
0026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0036  * POSSIBILITY OF SUCH DAMAGE.
0037  */
0038 
0039 #ifndef _RTEMS_SCORE_THREADQ_H
0040 #define _RTEMS_SCORE_THREADQ_H
0041 
0042 #include <rtems/score/chain.h>
0043 #include <rtems/score/isrlock.h>
0044 #include <rtems/score/object.h>
0045 #include <rtems/score/priority.h>
0046 #include <rtems/score/rbtree.h>
0047 #include <rtems/score/states.h>
0048 #include <rtems/score/watchdogticks.h>
0049 
0050 #ifdef __cplusplus
0051 extern "C" {
0052 #endif
0053 
0054 struct Per_CPU_Control;
0055 
0056 struct Scheduler_Node;
0057 
0058 /**
0059  * @defgroup RTEMSScoreThreadQueue Thread Queue Handler
0060  *
0061  * @ingroup RTEMSScore
0062  *
0063  * @brief This group contains the Thread Queue Handler implementation.
0064  *
0065  * This handler provides the capability to have threads block in
0066  * ordered sets. The sets may be ordered using the FIFO or priority
0067  * discipline.
0068  *
0069  * @{
0070  */
0071 
0072 typedef struct _Thread_Control Thread_Control;
0073 
0074 typedef struct Thread_queue_Context Thread_queue_Context;
0075 
0076 typedef struct Thread_queue_Queue Thread_queue_Queue;
0077 
0078 typedef struct Thread_queue_Operations Thread_queue_Operations;
0079 
0080 /**
0081  * @brief Thread queue enqueue callout.
0082  *
0083  * @param[in] queue The actual thread queue.
0084  * @param[in] the_thread The thread to enqueue.
0085  * @param[in] cpu_self The current processor.
0086  * @param[in] queue_context The thread queue context of the lock acquire.
0087  *
0088  * @see _Thread_queue_Context_set_enqueue_callout().
0089  */
0090 typedef void ( *Thread_queue_Enqueue_callout )(
0091   Thread_queue_Queue     *queue,
0092   Thread_Control         *the_thread,
0093   struct Per_CPU_Control *cpu_self,
0094   Thread_queue_Context   *queue_context
0095 );
0096 
0097 /**
0098  * @brief Thread queue deadlock callout.
0099  *
0100  * @param the_thread The thread that detected the deadlock.
0101  *
0102  * @see _Thread_queue_Context_set_deadlock_callout().
0103  */
0104 typedef void ( *Thread_queue_Deadlock_callout )(
0105   Thread_Control *the_thread
0106 );
0107 
0108 #if defined(RTEMS_MULTIPROCESSING)
0109 /**
0110  * @brief Multiprocessing (MP) support callout for thread queue operations.
0111  *
0112  * @param the_proxy The thread proxy of the thread queue operation.  A thread
0113  *   control is actually a thread proxy if and only if
0114  *   _Objects_Is_local_id( the_proxy->Object.id ) is false.
0115  * @param mp_id Object identifier of the object containing the thread queue.
0116  *
0117  * @see _Thread_queue_Context_set_MP_callout().
0118  */
0119 typedef void ( *Thread_queue_MP_callout )(
0120   Thread_Control *the_proxy,
0121   Objects_Id      mp_id
0122 );
0123 #endif
0124 
0125 #if defined(RTEMS_SMP)
0126 /**
0127  * @brief The thread queue gate is an SMP synchronization means.
0128  *
0129  * The gates are added to a list of requests.  A busy wait is performed to make
0130  * sure that preceding requests are carried out.  Each predecessor notifies its
0131  * successor about on request completion.
0132  *
0133  * @see _Thread_queue_Gate_add(), _Thread_queue_Gate_wait(), and
0134  *   _Thread_queue_Gate_open().
0135  */
0136 typedef struct {
0137   Chain_Node Node;
0138 
0139   Atomic_Uint go_ahead;
0140 } Thread_queue_Gate;
0141 #endif
0142 
0143 typedef struct {
0144   /**
0145    * @brief The lock context for the thread queue acquire and release
0146    * operations.
0147    */
0148   ISR_lock_Context Lock_context;
0149 
0150 #if defined(RTEMS_SMP)
0151   /**
0152    * @brief Data to support thread queue enqueue operations.
0153    */
0154   struct {
0155     /**
0156      * @brief Gate to synchronize thread wait lock requests.
0157      *
0158      * @see _Thread_Wait_acquire_critical() and _Thread_Wait_tranquilize().
0159      */
0160     Thread_queue_Gate Gate;
0161 
0162     /**
0163      * @brief The thread queue in case the thread is blocked on a thread queue.
0164      */
0165     Thread_queue_Queue *queue;
0166   } Wait;
0167 #endif
0168 } Thread_queue_Lock_context;
0169 
0170 #if defined(RTEMS_SMP)
0171 /**
0172  * @brief A thread queue link from one thread to another specified by the
0173  * thread queue owner and thread wait queue relationships.
0174  */
0175 typedef struct {
0176   /**
0177    * @brief Node to register this link in the global thread queue links lookup
0178    * tree.
0179    */
0180   RBTree_Node Registry_node;
0181 
0182   /**
0183    * @brief The source thread queue determined by the thread queue owner.
0184    */
0185   Thread_queue_Queue *source;
0186 
0187   /**
0188    * @brief The target thread queue determined by the thread wait queue of the
0189    * source owner.
0190    */
0191   Thread_queue_Queue *target;
0192 
0193   /**
0194    * @brief Node to add this link to a thread queue path.
0195    */
0196   Chain_Node Path_node;
0197 
0198   /**
0199    * @brief The owner of this thread queue link.
0200    */
0201   Thread_Control *owner;
0202 
0203   /**
0204    * @brief The queue lock context used to acquire the thread wait lock of the
0205    * owner.
0206    */
0207   Thread_queue_Lock_context Lock_context;
0208 } Thread_queue_Link;
0209 #endif
0210 
0211 /**
0212  * @brief Thread queue context for the thread queue methods.
0213  *
0214  * @see _Thread_queue_Context_initialize().
0215  */
0216 struct Thread_queue_Context {
0217   /**
0218    * @brief The lock context for the thread queue acquire and release
0219    * operations.
0220    */
0221   Thread_queue_Lock_context Lock_context;
0222 
0223   /**
0224    * @brief The thread state for _Thread_queue_Enqueue().
0225    */
0226   States_Control thread_state;
0227 
0228   /**
0229    * @brief The enqueue callout for _Thread_queue_Enqueue().
0230    *
0231    * The callout is invoked after the release of the thread queue lock with
0232    * thread dispatching disabled.  Afterwards the thread is blocked.  This
0233    * callout must be used to install the thread watchdog for timeout handling.
0234    *
0235    * @see _Thread_queue_Enqueue_do_nothing_extra().
0236    *   _Thread_queue_Add_timeout_ticks(),
0237    *   _Thread_queue_Add_timeout_monotonic_timespec(), and
0238    *   _Thread_queue_Add_timeout_realtime_timespec().
0239    */
0240   Thread_queue_Enqueue_callout enqueue_callout;
0241 
0242   /**
0243    * @brief Interval to wait.
0244    *
0245    * May be used by the enqueue callout to register a timeout handler.
0246    */
0247   union {
0248     /**
0249      * @brief The timeout in ticks.
0250      */
0251     Watchdog_Interval ticks;
0252 
0253     /**
0254      * @brief The timeout argument, e.g. pointer to struct timespec.
0255      */
0256     const void *arg;
0257   } Timeout;
0258 
0259   /**
0260    * @brief If this member is true, the timeout shall be absolute, otherwise it
0261    *   shall be relative to the current time of the clock.
0262    */
0263   bool timeout_absolute;
0264 
0265 #if defined(RTEMS_SMP)
0266   /**
0267    * @brief Representation of a thread queue path from a start thread queue to
0268    * the terminal thread queue.
0269    *
0270    * The start thread queue is determined by the object on which a thread intends
0271    * to block.  The terminal thread queue is the thread queue reachable via
0272    * thread queue links whose owner is not blocked on a thread queue.  The thread
0273    * queue links are determined by the thread queue owner and thread wait queue
0274    * relationships.
0275    */
0276   struct {
0277     /**
0278      * @brief The chain of thread queue links defining the thread queue path.
0279      */
0280     Chain_Control Links;
0281 
0282     /**
0283      * @brief The start of a thread queue path.
0284      */
0285     Thread_queue_Link Start;
0286 
0287     /**
0288      * @brief In case of a deadlock, a link for the first thread on the path
0289      * that tries to enqueue on a thread queue.
0290      */
0291     Thread_queue_Link Deadlock;
0292   } Path;
0293 #endif
0294 
0295   /**
0296    * @brief Block to manage thread priority changes due to a thread queue
0297    * operation.
0298    */
0299   struct {
0300     /**
0301      * @brief A priority action list.
0302      */
0303     Priority_Actions Actions;
0304 
0305     /**
0306      * @brief Count of threads to update the priority via
0307      * _Thread_Priority_update().
0308      */
0309     size_t update_count;
0310 
0311     /**
0312      * @brief Threads to update the priority via _Thread_Priority_update().
0313      *
0314      * Currently, a maximum of two threads need an update in one rush, for
0315      * example the thread of the thread queue operation and the owner of the
0316      * thread queue.
0317      */
0318     Thread_Control *update[ 2 ];
0319   } Priority;
0320 
0321   /**
0322    * @brief Invoked in case of a detected deadlock.
0323    *
0324    * Must be initialized for _Thread_queue_Enqueue() in case the
0325    * thread queue may have an owner, e.g. for mutex objects.
0326    *
0327    * @see _Thread_queue_Context_set_deadlock_callout().
0328    */
0329   Thread_queue_Deadlock_callout deadlock_callout;
0330 
0331 #if defined(RTEMS_MULTIPROCESSING)
0332   /**
0333    * @brief Callout to unblock the thread in case it is actually a thread
0334    * proxy.
0335    *
0336    * This field is only used on multiprocessing configurations.  Used by
0337    * thread queue extract and unblock methods for objects with multiprocessing
0338    * (MP) support.
0339    *
0340    * @see _Thread_queue_Context_set_MP_callout().
0341    */
0342   Thread_queue_MP_callout mp_callout;
0343 #endif
0344 };
0345 
0346 /**
0347  * @brief Thread priority queue.
0348  */
0349 typedef struct {
0350 #if defined(RTEMS_SMP)
0351   /**
0352    * @brief Node to enqueue this queue in the FIFO chain of the corresponding
0353    * heads structure.
0354    *
0355    * @see Thread_queue_Heads::Heads::Fifo.
0356    */
0357   Chain_Node Node;
0358 #endif
0359 
0360   /**
0361    * @brief The actual thread priority queue.
0362    */
0363   Priority_Aggregation Queue;
0364 
0365   /**
0366    * @brief This priority queue is added to a scheduler node of the owner in
0367    * case of priority inheritance.
0368    */
0369   struct Scheduler_Node *scheduler_node;
0370 } Thread_queue_Priority_queue;
0371 
0372 /**
0373  * @brief Thread queue heads.
0374  *
0375  * Each thread is equipped with spare thread queue heads in case it is not
0376  * enqueued on a thread queue.  The first thread enqueued on a thread queue
0377  * will give its spare thread queue heads to that thread queue.  The threads
0378  * arriving at the queue will add their thread queue heads to the free chain of
0379  * the queue heads provided by the first thread enqueued.  Once a thread is
0380  * dequeued it use the free chain to get new spare thread queue heads.
0381  *
0382  * Uses a leading underscore in the structure name to allow forward
0383  * declarations in standard header files provided by Newlib and GCC.
0384  */
0385 typedef struct _Thread_queue_Heads {
0386   /** This union contains the data structures used to manage the blocked
0387    *  set of tasks which varies based upon the discipline.
0388    */
0389   union {
0390     /**
0391      * @brief This is the FIFO discipline list.
0392      *
0393      * On SMP configurations this FIFO is used to enqueue the per scheduler
0394      * instance priority queues of this structure.  This ensures FIFO fairness
0395      * among the highest priority thread of each scheduler instance.
0396      */
0397     Chain_Control Fifo;
0398 
0399 #if !defined(RTEMS_SMP)
0400     /**
0401      * @brief This is the set of threads for priority discipline waiting.
0402      */
0403     Thread_queue_Priority_queue Priority;
0404 #endif
0405   } Heads;
0406 
0407   /**
0408    * @brief A chain with free thread queue heads providing the spare thread
0409    * queue heads for a thread once it is dequeued.
0410    */
0411   Chain_Control Free_chain;
0412 
0413   /**
0414    * @brief A chain node to add these thread queue heads to the free chain of
0415    * the thread queue heads dedicated to the thread queue of an object.
0416    */
0417   Chain_Node Free_node;
0418 
0419 #if defined(RTEMS_SMP)
0420   /**
0421    * @brief One priority queue per scheduler instance.
0422    */
0423   Thread_queue_Priority_queue Priority[ RTEMS_ZERO_LENGTH_ARRAY ];
0424 #endif
0425 } Thread_queue_Heads;
0426 
0427 struct Thread_queue_Queue {
0428 #if defined(RTEMS_SMP)
0429   /**
0430    * @brief Lock to protect this thread queue.
0431    *
0432    * It may be used to protect additional state of the object embedding this
0433    * thread queue.
0434    *
0435    * Must be the first component of this structure to be able to re-use
0436    * implementation parts for structures defined by Newlib <sys/lock.h>.
0437    *
0438    * @see _Thread_queue_Acquire(), _Thread_queue_Acquire_critical() and
0439    * _Thread_queue_Release().
0440    */
0441   SMP_ticket_lock_Control Lock;
0442 #endif
0443 
0444   /**
0445    * @brief The thread queue heads.
0446    *
0447    * This pointer is NULL, if and only if no threads are enqueued.  The first
0448    * thread to enqueue will give its spare thread queue heads to this thread
0449    * queue.
0450    */
0451   Thread_queue_Heads *heads;
0452 
0453   /**
0454    * @brief The thread queue owner.
0455    */
0456   Thread_Control *owner;
0457 
0458   /**
0459    * @brief The thread queue name.
0460    */
0461   const char *name;
0462 };
0463 
0464 /**
0465  * @brief Thread queue action operation.
0466  *
0467  * @param[in] queue The actual thread queue.
0468  * @param[in] the_thread The thread.
0469  * @param[in] queue_context The thread queue context providing the thread queue
0470  *   action set to perform.  Returns the thread queue action set to perform on
0471  *   the thread queue owner or the empty set in case there is nothing to do.
0472  */
0473 typedef void ( *Thread_queue_Priority_actions_operation )(
0474   Thread_queue_Queue   *queue,
0475   Priority_Actions     *priority_actions
0476 );
0477 
0478 /**
0479  * @brief Thread queue enqueue operation.
0480  *
0481  * A potential thread to update the priority due to priority inheritance is
0482  * returned via the thread queue context.  This thread is handed over to
0483  * _Thread_Priority_update().
0484  *
0485  * @param[in] queue The actual thread queue.
0486  * @param[in] the_thread The thread to enqueue on the queue.
0487  */
0488 typedef void ( *Thread_queue_Enqueue_operation )(
0489   Thread_queue_Queue   *queue,
0490   Thread_Control       *the_thread,
0491   Thread_queue_Context *queue_context
0492 );
0493 
0494 /**
0495  * @brief Thread queue extract operation.
0496  *
0497  * @param[in] queue The actual thread queue.
0498  * @param[in] the_thread The thread to extract from the thread queue.
0499  */
0500 typedef void ( *Thread_queue_Extract_operation )(
0501   Thread_queue_Queue   *queue,
0502   Thread_Control       *the_thread,
0503   Thread_queue_Context *queue_context
0504 );
0505 
0506 /**
0507  * @brief Thread queue surrender operation.
0508  *
0509  * This operation must dequeue and return the first thread on the queue.
0510  *
0511  * @param[in] queue The actual thread queue.
0512  * @param[in] heads The thread queue heads.  It must not be NULL.
0513  * @param[in] previous_owner The previous owner of the thread queue.
0514  *
0515  * @return The previous first thread on the queue.
0516  */
0517 typedef Thread_Control *( *Thread_queue_Surrender_operation )(
0518   Thread_queue_Queue   *queue,
0519   Thread_queue_Heads   *heads,
0520   Thread_Control       *previous_owner,
0521   Thread_queue_Context *queue_context
0522 );
0523 
0524 /**
0525  * @brief Gets the first thread on the queue.
0526  *
0527  * @param heads are heads of the thread queue.
0528  *
0529  * @retval NULL No thread is enqueued on the thread queue.
0530  *
0531  * @return Returns the first thread on the thread queue according to the queue
0532  *   order.  This thread remains on the thread queue.
0533  */
0534 typedef Thread_Control *( *Thread_queue_First_operation )(
0535   const Thread_queue_Heads *heads
0536 );
0537 
0538 /**
0539  * @brief The thread queue operations are used to manage the threads of a
0540  *   thread queue.
0541  *
0542  * The standard thread queue operation variants are:
0543  *
0544  * * ::_Thread_queue_Operations_default
0545  *
0546  * * ::_Thread_queue_Operations_FIFO
0547  *
0548  * * ::_Thread_queue_Operations_priority
0549  *
0550  * * ::_Thread_queue_Operations_priority_inherit
0551  *
0552  * @see _Thread_wait_Set_operations().
0553  */
0554 struct Thread_queue_Operations {
0555   /**
0556    * @brief This operation performs the thread queue priority actions.
0557    *
0558    * Priority actions are produced and processed during enqueue, extract, and
0559    * surrender operations.
0560    */
0561   Thread_queue_Priority_actions_operation priority_actions;
0562 
0563   /**
0564    * @brief This operation is used to enqueue the thread on the thread queue.
0565    *
0566    * The enqueue order is defined by the operations variant.
0567    */
0568   Thread_queue_Enqueue_operation enqueue;
0569 
0570   /**
0571    * @brief This operation is used to extract the thread from the thread queue.
0572    *
0573    * The extract operation is intended for timeouts, thread restarts, and
0574    * thread cancellation.  In SMP configurations, the extract operation does
0575    * not ensure FIFO fairness across schedulers for priority queues.  The
0576    * surrender operation should be used to dequeue a thread from the thread
0577    * queue under normal conditions (no timeout, no thread restart, and no
0578    * thread cancellation).
0579    */
0580   Thread_queue_Extract_operation extract;
0581 
0582   /**
0583    * @brief This operation is used to dequeue the thread from the thread queue
0584    *   and optionally surrender the thread queue from a previous owner to the
0585    *   thread.
0586    *
0587    * In addition to the optional surrender, there is a subtle difference
0588    * between the extract and dequeue of a thread from a thread queue.  In SMP
0589    * configurations, FIFO fairness across schedulers for priority queues is
0590    * only ensured by the dequeue done by the surrender operation and not by the
0591    * extract operation.
0592    */
0593   Thread_queue_Surrender_operation surrender;
0594 
0595   /**
0596    * @brief This operation returns the first thread on the thread queue.
0597    *
0598    * This operation may be called only when the thread queue contains at least
0599    * one thread.  Use ::Thread_queue_Queue::heads to determine if a thread
0600    * queue is empty.
0601    */
0602   Thread_queue_First_operation first;
0603 };
0604 
0605 /**
0606  *  This is the structure used to manage sets of tasks which are blocked
0607  *  waiting to acquire a resource.
0608  */
0609 typedef struct {
0610 #if defined(RTEMS_SMP)
0611 #if defined(RTEMS_DEBUG)
0612   /**
0613    * @brief The index of the owning processor of the thread queue lock.
0614    *
0615    * The thread queue lock may be acquired via the thread lock also.  This path
0616    * is not covered by this field.  In case the lock is not owned directly via
0617    * _Thread_queue_Acquire(), then the value of this field is
0618    * SMP_LOCK_NO_OWNER.
0619    *
0620    * Must be before the queue component of this structure to be able to re-use
0621    * implementation parts for structures defined by Newlib <sys/lock.h>.
0622    */
0623   uint32_t owner;
0624 #endif
0625 
0626 #if defined(RTEMS_PROFILING)
0627   /**
0628    * @brief SMP lock statistics in case SMP and profiling are enabled.
0629    *
0630    * Must be before the queue component of this structure to be able to re-use
0631    * implementation parts for structures defined by Newlib <sys/lock.h>.
0632    */
0633   SMP_lock_Stats Lock_stats;
0634 #endif
0635 #endif
0636 
0637   /**
0638    * @brief The actual thread queue.
0639    */
0640   Thread_queue_Queue Queue;
0641 } Thread_queue_Control;
0642 
0643 /** @} */
0644 
0645 #ifdef __cplusplus
0646 }
0647 #endif
0648 
0649 #endif
0650 /* end of include file */