![]() |
|
|||
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 */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |