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