source: rtems/cpukit/include/rtems/score/threadqimpl.h @ 9278f3d

Last change on this file since 9278f3d was 9278f3d, checked in by Sebastian Huber <sebastian.huber@…>, on 11/27/20 at 16:21:23

score: Canonicalize Doxygen @file comments

Use common phrases for the file brief descriptions.

Update #3706.

  • Property mode set to 100644
File size: 42.8 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMSScoreThreadQueue
5 *
6 * @brief This header file provides interfaces of the
7 *   @ref RTEMSScoreThreadQueue which are only used by the implementation.
8 */
9
10/*
11 *  COPYRIGHT (c) 1989-2014.
12 *  On-Line Applications Research Corporation (OAR).
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.org/license/LICENSE.
17 */
18
19#ifndef _RTEMS_SCORE_THREADQIMPL_H
20#define _RTEMS_SCORE_THREADQIMPL_H
21
22#include <rtems/score/threadq.h>
23#include <rtems/score/chainimpl.h>
24#include <rtems/score/priorityimpl.h>
25#include <rtems/score/scheduler.h>
26#include <rtems/score/smp.h>
27#include <rtems/score/status.h>
28#include <rtems/score/thread.h>
29#include <rtems/score/threaddispatch.h>
30
31#if defined(RTEMS_DEBUG)
32#include <string.h>
33#endif
34
35#ifdef __cplusplus
36extern "C" {
37#endif
38
39/**
40 *  @addtogroup RTEMSScoreThreadQueue
41 *
42 * @{
43 */
44
45#define THREAD_QUEUE_LINK_OF_PATH_NODE( node ) \
46  RTEMS_CONTAINER_OF( node, Thread_queue_Link, Path_node );
47
48/**
49 * @brief Thread queue with a layout compatible to struct _Thread_queue_Queue
50 * defined in Newlib <sys/lock.h>.
51 */
52typedef struct {
53#if !defined(RTEMS_SMP)
54  /*
55   * The struct _Thread_queue_Queue definition is independent of the RTEMS
56   * build configuration.  Thus, the storage space for the SMP lock is always
57   * present.  In SMP configurations, the SMP lock is contained in the
58   * Thread_queue_Queue.
59   */
60  unsigned int reserved[2];
61#endif
62
63  Thread_queue_Queue Queue;
64} Thread_queue_Syslock_queue;
65
66/**
67 * @brief Does nothing.
68 *
69 * @param queue This parameter is unused.
70 * @param the_thread This parameter is unused.
71 * @param cpu_self This parameter is unused.
72 * @param queue_context This parameter is unused.
73 */
74void _Thread_queue_Enqueue_do_nothing_extra(
75  Thread_queue_Queue   *queue,
76  Thread_Control       *the_thread,
77  Per_CPU_Control      *cpu_self,
78  Thread_queue_Context *queue_context
79);
80
81/**
82 * @brief Adds timeout ticks of the queue to the thread.
83 *
84 * @param queue This parameter is unused.
85 * @param[in, out] the_thread The thread to add timeout ticks to.
86 * @param cpu_self The cpu for the operation.
87 * @param queue_context The thread queue context.
88 */
89void _Thread_queue_Add_timeout_ticks(
90  Thread_queue_Queue   *queue,
91  Thread_Control       *the_thread,
92  Per_CPU_Control      *cpu_self,
93  Thread_queue_Context *queue_context
94);
95
96/**
97 * @brief Adds a monotonic timespec to the thread and sets the watchdog header
98 *      to monotonic.
99 *
100 * @param queue This parameter is unused.
101 * @param[in, out] the_thread The thread to add the timeout and set watchdog header to
102 *      monotonic.
103 * @param cpu_self The cpu to get the monotonic watchdog header from.
104 * @param queue_context The thread queue context.
105 */
106void _Thread_queue_Add_timeout_monotonic_timespec(
107  Thread_queue_Queue   *queue,
108  Thread_Control       *the_thread,
109  Per_CPU_Control      *cpu_self,
110  Thread_queue_Context *queue_context
111);
112
113/**
114 * @brief Adds a monotonic timespec to the thread and sets the watchdog header
115 *      to realtime.
116 *
117 * @param queue This parameter is unused.
118 * @param[in, out] the_thread The thread to add the timeout and set watchdog header to
119 *      realtime.
120 * @param cpu_self The cpu to get the realtime watchdog header from.
121 * @param queue_context The thread queue context.
122 */
123void _Thread_queue_Add_timeout_realtime_timespec(
124  Thread_queue_Queue   *queue,
125  Thread_Control       *the_thread,
126  Per_CPU_Control      *cpu_self,
127  Thread_queue_Context *queue_context
128);
129
130/**
131 * @brief Sets the thread wait return code to STATUS_DEADLOCK.
132 *
133 * @param[out] the_thread The thread to set the wait return code to
134 *      STATUS_DEADLOCK.
135 */
136void _Thread_queue_Deadlock_status( Thread_Control *the_thread );
137
138/**
139 * @brief Results in an INTERNAL_ERROR_THREAD_QUEUE_DEADLOCK fatal error.
140 *
141 * @param the_thread The thread for the operation.
142 */
143void _Thread_queue_Deadlock_fatal( Thread_Control *the_thread );
144
145/**
146 * @brief Initializes a thread queue context.
147 *
148 * @param[out] queue_context The thread queue context to initialize.
149 */
150RTEMS_INLINE_ROUTINE void _Thread_queue_Context_initialize(
151  Thread_queue_Context *queue_context
152)
153{
154#if defined(RTEMS_DEBUG)
155  memset( queue_context, 0x7f, sizeof( *queue_context ) );
156#if defined(RTEMS_SMP)
157  _Chain_Initialize_node( &queue_context->Lock_context.Wait.Gate.Node );
158#endif
159  queue_context->enqueue_callout = NULL;
160  queue_context->deadlock_callout = NULL;
161#else
162  (void) queue_context;
163#endif
164}
165
166/**
167 * @brief Sets the thread state for the thread to enqueue in the thread queue
168 * context.
169 *
170 * @param[out] queue_context The thread queue context.
171 * @param state The thread state.
172 *
173 * @see _Thread_queue_Enqueue().
174 */
175RTEMS_INLINE_ROUTINE void
176_Thread_queue_Context_set_thread_state(
177  Thread_queue_Context *queue_context,
178  States_Control        thread_state
179)
180{
181  queue_context->thread_state = thread_state;
182}
183
184/**
185 * @brief Sets the timeout ticks in the thread queue context.
186 *
187 * @param[out] queue_context The thread queue context.
188 * @param ticks The timeout in ticks.
189 *
190 * @see _Thread_queue_Enqueue().
191 */
192RTEMS_INLINE_ROUTINE void
193_Thread_queue_Context_set_timeout_ticks(
194  Thread_queue_Context *queue_context,
195  Watchdog_Interval     ticks
196)
197{
198  queue_context->Timeout.ticks = ticks;
199}
200
201/**
202 * @brief Sets the timeout argument in the thread queue context.
203 *
204 * @param[out] queue_context The thread queue context.
205 * @param arg The timeout argument.
206 *
207 * @see _Thread_queue_Enqueue().
208 */
209RTEMS_INLINE_ROUTINE void
210_Thread_queue_Context_set_timeout_argument(
211  Thread_queue_Context *queue_context,
212  const void           *arg
213)
214{
215  queue_context->Timeout.arg = arg;
216}
217
218/**
219 * @brief Sets the enqueue callout in the thread queue context.
220 *
221 * @param[out] queue_context The thread queue context.
222 * @param enqueue_callout The enqueue callout.
223 *
224 * @see _Thread_queue_Enqueue().
225 */
226RTEMS_INLINE_ROUTINE void
227_Thread_queue_Context_set_enqueue_callout(
228  Thread_queue_Context         *queue_context,
229  Thread_queue_Enqueue_callout  enqueue_callout
230)
231{
232  queue_context->enqueue_callout = enqueue_callout;
233}
234
235/**
236 * @brief Sets the do nothing enqueue callout in the thread queue context.
237 *
238 * @param[out] queue_context The thread queue context.
239 *
240 * @see _Thread_queue_Enqueue().
241 */
242RTEMS_INLINE_ROUTINE void
243_Thread_queue_Context_set_enqueue_do_nothing_extra(
244  Thread_queue_Context *queue_context
245)
246{
247  queue_context->enqueue_callout = _Thread_queue_Enqueue_do_nothing_extra;
248}
249
250/**
251 * @brief Sets the enqueue callout to add a relative monotonic timeout in
252 * ticks.
253 *
254 * @param[out] queue_context The thread queue context.
255 * @param ticks The timeout in ticks.
256 *
257 * @see _Thread_queue_Enqueue().
258 */
259RTEMS_INLINE_ROUTINE void
260_Thread_queue_Context_set_enqueue_timeout_ticks(
261  Thread_queue_Context *queue_context,
262  Watchdog_Interval     ticks
263)
264{
265  queue_context->Timeout.ticks = ticks;
266  queue_context->enqueue_callout = _Thread_queue_Add_timeout_ticks;
267}
268
269/**
270 * @brief Sets the enqueue callout to add an absolute monotonic timeout in
271 * timespec format.
272 *
273 * @param[out] queue_context The thread queue context.
274 * @param abstime The absolute monotonic timeout.
275 *
276 * @see _Thread_queue_Enqueue().
277 */
278RTEMS_INLINE_ROUTINE void
279_Thread_queue_Context_set_enqueue_timeout_monotonic_timespec(
280  Thread_queue_Context  *queue_context,
281  const struct timespec *abstime
282)
283{
284  queue_context->Timeout.arg = abstime;
285  queue_context->enqueue_callout =
286    _Thread_queue_Add_timeout_monotonic_timespec;
287}
288
289/**
290 * @brief Sets the enqueue callout to add an absolute realtime timeout in
291 * timespec format.
292 *
293 * @param[out] queue_context The thread queue context.
294 * @param abstime The absolute realtime timeout.
295 *
296 * @see _Thread_queue_Enqueue().
297 */
298RTEMS_INLINE_ROUTINE void
299_Thread_queue_Context_set_enqueue_timeout_realtime_timespec(
300  Thread_queue_Context  *queue_context,
301  const struct timespec *abstime
302)
303{
304  queue_context->Timeout.arg = abstime;
305  queue_context->enqueue_callout = _Thread_queue_Add_timeout_realtime_timespec;
306}
307
308/**
309 * @brief Sets the deadlock callout in the thread queue
310 * context.
311 *
312 * A deadlock callout must be provided for _Thread_queue_Enqueue()
313 * operations that operate on thread queues which may have an owner, e.g. mutex
314 * objects.  Available deadlock callouts are _Thread_queue_Deadlock_status()
315 * and _Thread_queue_Deadlock_fatal().
316 *
317 * @param[out] queue_context The thread queue context.
318 * @param deadlock_callout The deadlock callout.
319 *
320 * @see _Thread_queue_Enqueue().
321 */
322RTEMS_INLINE_ROUTINE void _Thread_queue_Context_set_deadlock_callout(
323  Thread_queue_Context          *queue_context,
324  Thread_queue_Deadlock_callout  deadlock_callout
325)
326{
327  queue_context->deadlock_callout = deadlock_callout;
328}
329
330/**
331 * @brief Clears the priority update count of the thread queue context.
332 *
333 * @param[out] queue_context The thread queue context to clear the priority
334 * update count.
335 */
336RTEMS_INLINE_ROUTINE void _Thread_queue_Context_clear_priority_updates(
337  Thread_queue_Context *queue_context
338)
339{
340  queue_context->Priority.update_count = 0;
341}
342
343/**
344 * @brief Returns the priority update count of the thread queue context.
345 *
346 * @param queue_context The thread queue context to get the priority update
347 *      count of.
348 *
349 * @return The priority update count of @a queue_context.
350 */
351RTEMS_INLINE_ROUTINE size_t _Thread_queue_Context_save_priority_updates(
352  Thread_queue_Context *queue_context
353)
354{
355  return queue_context->Priority.update_count;
356}
357
358/**
359 * @brief Sets the priority update count of the thread queue context.
360 *
361 * @param[out] queue_context The thread queue context to set the priority
362 *      update count of.
363 * @param update_count The priority update count.
364 */
365RTEMS_INLINE_ROUTINE void _Thread_queue_Context_restore_priority_updates(
366  Thread_queue_Context *queue_context,
367  size_t                update_count
368)
369{
370  queue_context->Priority.update_count = update_count;
371}
372
373/**
374 * @brief Adds a priority update of the thread to the thread queue context.
375 *
376 * @param[in, out] queue_context The thread queue context to increase the
377 *      priority update count of and set the_thread in its Priority update
378 *      array.
379 * @param the_thread The thread for the priority update.
380 */
381RTEMS_INLINE_ROUTINE void _Thread_queue_Context_add_priority_update(
382  Thread_queue_Context *queue_context,
383  Thread_Control       *the_thread
384)
385{
386  size_t n;
387
388  n = queue_context->Priority.update_count;
389  _Assert( n < RTEMS_ARRAY_SIZE( queue_context->Priority.update ) );
390
391  queue_context->Priority.update_count = n + 1;
392  queue_context->Priority.update[ n ] = the_thread;
393}
394
395#define _Thread_queue_Context_ISR_disable( queue_context, level ) \
396  do { \
397    _ISR_Local_disable( level ); \
398    _ISR_lock_ISR_disable_profile( \
399      &( queue_context )->Lock_context.Lock_context \
400    ) \
401  } while ( 0 )
402
403/**
404 * @brief Sets the thread queue context ISR level.
405 *
406 * @param[out] queue_context The thread queue context to set the ISR level of.
407 * @param level The ISR level to set @a queue_context to.
408 */
409RTEMS_INLINE_ROUTINE void _Thread_queue_Context_set_ISR_level(
410  Thread_queue_Context *queue_context,
411  ISR_Level             level
412)
413{
414  _ISR_lock_Context_set_level(
415    &queue_context->Lock_context.Lock_context,
416    level
417  );
418}
419
420/**
421 * @brief Disables dispatching in a critical section.
422 *
423 * @param queue_context The thread queue context to get the lock context from.
424 *
425 * @return The current processor.
426 */
427RTEMS_INLINE_ROUTINE Per_CPU_Control *_Thread_queue_Dispatch_disable(
428  Thread_queue_Context *queue_context
429)
430{
431  return _Thread_Dispatch_disable_critical(
432    &queue_context->Lock_context.Lock_context
433  );
434}
435
436/**
437 * @brief Sets the MP callout in the thread queue context.
438 *
439 * @param[out] queue_context The thread queue context.
440 * @param mp_callout Callout to unblock the thread in case it is actually a
441 *   thread proxy.  This parameter is only used on multiprocessing
442 *   configurations.  Used by thread queue extract and unblock methods for
443 *   objects with multiprocessing (MP) support.
444 */
445#if defined(RTEMS_MULTIPROCESSING)
446RTEMS_INLINE_ROUTINE void _Thread_queue_Context_set_MP_callout(
447  Thread_queue_Context    *queue_context,
448  Thread_queue_MP_callout  mp_callout
449)
450{
451  queue_context->mp_callout = mp_callout;
452}
453#else
454#define _Thread_queue_Context_set_MP_callout( queue_context, mp_callout ) \
455  do { \
456    (void) queue_context; \
457  } while ( 0 )
458#endif
459
460#if defined(RTEMS_SMP)
461/**
462 * @brief Closes the gate.
463 *
464 * @param[out] gate The gate to close.
465 */
466RTEMS_INLINE_ROUTINE void _Thread_queue_Gate_close(
467  Thread_queue_Gate *gate
468)
469{
470  _Atomic_Store_uint( &gate->go_ahead, 0, ATOMIC_ORDER_RELAXED );
471}
472
473/**
474 * @brief Adds the gate to the chain.
475 *
476 * @param[in, out] chain The chain to add the gate to.
477 * @param gate The gate to add to the chain.
478 */
479RTEMS_INLINE_ROUTINE void _Thread_queue_Gate_add(
480  Chain_Control     *chain,
481  Thread_queue_Gate *gate
482)
483{
484  _Chain_Append_unprotected( chain, &gate->Node );
485}
486
487/**
488 * @brief Opens the gate.
489 *
490 * @param[out] gate The gate to open.
491 */
492RTEMS_INLINE_ROUTINE void _Thread_queue_Gate_open(
493  Thread_queue_Gate *gate
494)
495{
496  _Atomic_Store_uint( &gate->go_ahead, 1, ATOMIC_ORDER_RELAXED );
497}
498
499/**
500 * @brief Waits on a gate to open.
501 *
502 * Performs busy waiting.
503 *
504 * @param gate The gate to wait for.
505 */
506RTEMS_INLINE_ROUTINE void _Thread_queue_Gate_wait(
507  Thread_queue_Gate *gate
508)
509{
510  while ( _Atomic_Load_uint( &gate->go_ahead, ATOMIC_ORDER_RELAXED ) == 0 ) {
511    /* Wait */
512  }
513}
514#endif
515
516/**
517 * @brief Initializes the thread queue heads.
518 *
519 * @param[out] heads The thread queue heads to initialize.
520 */
521RTEMS_INLINE_ROUTINE void _Thread_queue_Heads_initialize(
522  Thread_queue_Heads *heads
523)
524{
525#if defined(RTEMS_SMP)
526  size_t i;
527
528  for ( i = 0; i < _Scheduler_Count; ++i ) {
529    _Chain_Initialize_node( &heads->Priority[ i ].Node );
530    _Priority_Initialize_empty( &heads->Priority[ i ].Queue );
531    heads->Priority[ i ].Queue.scheduler = &_Scheduler_Table[ i ];
532  }
533#endif
534
535  _Chain_Initialize_empty( &heads->Free_chain );
536  _Chain_Initialize_node( &heads->Free_node );
537}
538
539/**
540 * @brief Initializes the thread queue queue with the given name.
541 *
542 * @param[out] queue The thread queue queue to initialize.
543 * @param name The name for the @a queue.
544 */
545RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_initialize(
546  Thread_queue_Queue *queue,
547  const char         *name
548)
549{
550#if defined(RTEMS_SMP)
551  _SMP_ticket_lock_Initialize( &queue->Lock );
552#endif
553  queue->heads = NULL;
554  queue->owner = NULL;
555  queue->name = name;
556}
557
558/**
559 * @brief Acquires the thread queue queue in a critical section.
560 *
561 * @param queue The thread queue queue to acquire in a critical section.
562 * @param lock_stats The lock statistics.
563 * @param[out] lock_context The interrupt lock context.
564 */
565RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_do_acquire_critical(
566  Thread_queue_Queue *queue,
567#if defined(RTEMS_SMP) && defined(RTEMS_PROFILING)
568  SMP_lock_Stats     *lock_stats,
569#endif
570  ISR_lock_Context   *lock_context
571)
572{
573#if defined(RTEMS_SMP)
574  _SMP_ticket_lock_Acquire(
575    &queue->Lock,
576    lock_stats,
577    &lock_context->Lock_context.Stats_context
578  );
579#else
580  (void) queue;
581  (void) lock_context;
582#endif
583}
584
585#if defined(RTEMS_SMP) && defined( RTEMS_PROFILING )
586  #define \
587    _Thread_queue_Queue_acquire_critical( queue, lock_stats, lock_context ) \
588    _Thread_queue_Queue_do_acquire_critical( queue, lock_stats, lock_context )
589#else
590  #define \
591    _Thread_queue_Queue_acquire_critical( queue, lock_stats, lock_context ) \
592    _Thread_queue_Queue_do_acquire_critical( queue, lock_context )
593#endif
594
595/**
596 * @brief Releases the thread queue queue in a critical section.
597 *
598 * @param queue The thread queue queue to release in a critical section.
599 * @param[out] lock_context The interrupt lock context.
600 */
601RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_release_critical(
602  Thread_queue_Queue *queue,
603  ISR_lock_Context   *lock_context
604)
605{
606#if defined(RTEMS_SMP)
607  _SMP_ticket_lock_Release(
608    &queue->Lock,
609    &lock_context->Lock_context.Stats_context
610  );
611#else
612  (void) queue;
613  (void) lock_context;
614#endif
615}
616
617/**
618 * @brief Releases the thread queue queue and enables interrupts.
619 *
620 * @param queue The thread queue queue to release.
621 * @param[out] lock_context The interrupt lock context to enable interrupts.
622 */
623RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_release(
624  Thread_queue_Queue *queue,
625  ISR_lock_Context   *lock_context
626)
627{
628  _Thread_queue_Queue_release_critical( queue, lock_context );
629  _ISR_lock_ISR_enable( lock_context );
630}
631
632/**
633 * @brief Copies the thread queue name to the specified buffer.
634 *
635 * @param queue The actual thread queue.
636 * @param[out] buffer The buffer for the thread queue name copy.
637 * @param buffer_size The buffer size in characters.
638 * @param id The object identifier in case the thread queue is embedded in
639 *   an object with identifier, otherwise it is set to 0.
640 *
641 * @return The length of the thread queue name.  May be greater than or equal
642 *  to the buffer size if truncation occurred.
643 */
644size_t _Thread_queue_Queue_get_name_and_id(
645  const Thread_queue_Queue *queue,
646  char                     *buffer,
647  size_t                    buffer_size,
648  Objects_Id               *id
649);
650
651/**
652 * @brief Acquires the thread queue control in a critical section.
653 *
654 * @param the_thread_queue The thread queue control to acquire.
655 * @param[out] lock_context The interrupt lock context.
656 */
657#if defined(RTEMS_SMP)
658void _Thread_queue_Do_acquire_critical(
659  Thread_queue_Control *the_thread_queue,
660  ISR_lock_Context     *lock_context
661);
662#else
663RTEMS_INLINE_ROUTINE void _Thread_queue_Do_acquire_critical(
664  Thread_queue_Control *the_thread_queue,
665  ISR_lock_Context     *lock_context
666)
667{
668  (void) the_thread_queue;
669  (void) lock_context;
670}
671#endif
672
673/**
674 * @brief Acquires the thread queue control in a critical section.
675 *
676 * @param the_thread_queue The thread queue control to acquire.
677 * @param[out] lock_context The interrupt lock context.
678 */
679RTEMS_INLINE_ROUTINE void _Thread_queue_Acquire_critical(
680  Thread_queue_Control *the_thread_queue,
681  Thread_queue_Context *queue_context
682)
683{
684  _Thread_queue_Do_acquire_critical(
685    the_thread_queue,
686    &queue_context->Lock_context.Lock_context
687  );
688}
689
690/**
691 * @brief Acquires the thread queue control in a critical section.
692 *
693 * @param the_thread_queue The thread queue control to acquire.
694 * @param[out] queue_context The thread queue context.
695 */
696#if defined(RTEMS_SMP)
697void _Thread_queue_Acquire(
698  Thread_queue_Control *the_thread_queue,
699  Thread_queue_Context *queue_context
700);
701#else
702RTEMS_INLINE_ROUTINE void _Thread_queue_Acquire(
703  Thread_queue_Control *the_thread_queue,
704  Thread_queue_Context *queue_context
705)
706{
707  (void) the_thread_queue;
708  _ISR_lock_ISR_disable( &queue_context->Lock_context.Lock_context );
709}
710#endif
711
712/**
713 * @brief Checks if the thread queue control is the owner of the lock.
714 *
715 * @param the_thread_queue The thread queue control for the verification.
716 *
717 * @retval true The thread queue control is the owner of the lock.
718 * @retval false The thread queue control is not the owner of the lock.
719 */
720#if defined(RTEMS_DEBUG)
721RTEMS_INLINE_ROUTINE bool _Thread_queue_Is_lock_owner(
722  const Thread_queue_Control *the_thread_queue
723)
724{
725#if defined(RTEMS_SMP)
726  return the_thread_queue->owner == _SMP_lock_Who_am_I();
727#else
728  return _ISR_Get_level() != 0;
729#endif
730}
731#endif
732
733/**
734 * @brief Releases the thread queue control in a critical section.
735 *
736 * @param the_thread_queue The thread queue control to release.
737 * @param[out] lock_context The interrupt lock context.
738 */
739#if defined(RTEMS_SMP)
740void _Thread_queue_Do_release_critical(
741  Thread_queue_Control *the_thread_queue,
742  ISR_lock_Context     *lock_context
743);
744#else
745RTEMS_INLINE_ROUTINE void _Thread_queue_Do_release_critical(
746  Thread_queue_Control *the_thread_queue,
747  ISR_lock_Context     *lock_context
748)
749{
750  (void) the_thread_queue;
751  (void) lock_context;
752  _Assert( _Thread_queue_Is_lock_owner( the_thread_queue ) );
753}
754#endif
755
756/**
757 * @brief Releases the thread queue control in a critical section.
758 *
759 * @param the_thread_queue The thread queue control to release.
760 * @param[out] queue_context The thread queue context.
761 */
762RTEMS_INLINE_ROUTINE void _Thread_queue_Release_critical(
763  Thread_queue_Control *the_thread_queue,
764  Thread_queue_Context *queue_context
765)
766{
767  _Thread_queue_Do_release_critical(
768    the_thread_queue,
769    &queue_context->Lock_context.Lock_context
770  );
771}
772
773/**
774 * @brief Releases the thread queue control and enables interrupts.
775 *
776 * @param the_thread_queue The thread queue control to release.
777 * @param[out] queue_context The thread queue context.
778 */
779#if defined(RTEMS_SMP)
780void _Thread_queue_Release(
781  Thread_queue_Control *the_thread_queue,
782  Thread_queue_Context *queue_context
783);
784#else
785RTEMS_INLINE_ROUTINE void _Thread_queue_Release(
786  Thread_queue_Control *the_thread_queue,
787  Thread_queue_Context *queue_context
788)
789{
790  (void) the_thread_queue;
791  _Assert( _Thread_queue_Is_lock_owner( the_thread_queue ) );
792  _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context );
793}
794#endif
795
796/**
797 * @brief Dequeues the first thread waiting on the thread queue and returns it.
798 *
799 * @param the_thread_queue The thread queue for the operation.
800 * @param operations The thread queue operations.
801 *
802 * @return The first locked thread.
803 */
804Thread_Control *_Thread_queue_Do_dequeue(
805  Thread_queue_Control          *the_thread_queue,
806  const Thread_queue_Operations *operations
807#if defined(RTEMS_MULTIPROCESSING)
808  ,
809  Thread_queue_MP_callout        mp_callout
810#endif
811);
812
813/**
814 *  @brief Gets a pointer to a thread waiting on the_thread_queue.
815 *
816 *  This function returns a pointer to a thread waiting on
817 *  the_thread_queue.  The selection of this thread is based on
818 *  the discipline of the_thread_queue.  If no threads are waiting
819 *  on the_thread_queue, then NULL is returned.
820 *
821 *  - INTERRUPT LATENCY:
822 *    + single case
823 */
824#if defined(RTEMS_MULTIPROCESSING)
825  #define _Thread_queue_Dequeue( \
826    the_thread_queue, \
827    operations, \
828    mp_callout \
829  ) \
830    _Thread_queue_Do_dequeue( \
831      the_thread_queue, \
832      operations, \
833      mp_callout \
834    )
835#else
836  #define _Thread_queue_Dequeue( \
837    the_thread_queue, \
838    operations, \
839    mp_callout \
840  ) \
841    _Thread_queue_Do_dequeue( \
842      the_thread_queue, \
843      operations \
844    )
845#endif
846
847/**
848 * @brief Blocks the thread and places it on the thread queue.
849 *
850 * This enqueues the thread on the thread queue, blocks the thread, and
851 * optionally starts the thread timer in case the timeout discipline is not
852 * WATCHDOG_NO_TIMEOUT. Timeout discipline and value are in the queue_context.
853 *
854 * The caller must be the owner of the thread queue lock.  This function will
855 * release the thread queue lock and register it as the new thread lock.
856 * Thread dispatching is disabled before the thread queue lock is released.
857 * Thread dispatching is enabled once the sequence to block the thread is
858 * complete.  The operation to enqueue the thread on the queue is protected by
859 * the thread queue lock.  This makes it possible to use the thread queue lock
860 * to protect the state of objects embedding the thread queue and directly
861 * enter _Thread_queue_Enqueue() in case the thread must block.
862 *
863 * The thread queue context must be set up with the following functions,
864 * otherwise the behaviour is unpredictable
865 *
866 * - _Thread_queue_Context_set_thread_state(),
867 *
868 * - _Thread_queue_Context_set_enqueue_callout() or
869 *   _Thread_queue_Context_set_enqueue_do_nothing_extra() or
870 *   _Thread_queue_Context_set_enqueue_timeout_ticks() or
871 *   _Thread_queue_Context_set_enqueue_timeout_monotonic_timespec() or
872 *   _Thread_queue_Context_set_enqueue_timeout_realtime_timespec(),
873 *
874 * - _Thread_queue_Context_set_deadlock_callout().
875 *
876 * @code
877 * #include <rtems/score/threadqimpl.h>
878 * #include <rtems/score/statesimpl.h>
879 *
880 * #define MUTEX_TQ_OPERATIONS &_Thread_queue_Operations_priority
881 *
882 * typedef struct {
883 *   Thread_queue_Control Queue;
884 * } Mutex;
885 *
886 * void _Mutex_Obtain( Mutex *mutex )
887 * {
888 *   Thread_queue_Context  queue_context;
889 *   Thread_Control       *executing;
890 *
891 *   _Thread_queue_Context_initialize( &queue_context );
892 *   _Thread_queue_Acquire( &mutex->Queue, queue_context );
893 *
894 *   executing = _Thread_Executing;
895 *
896 *   if ( mutex->Queue.owner == NULL ) {
897 *     mutex->Queue.owner = executing;
898 *     _Thread_queue_Release( &mutex->Queue, queue_context );
899 *   } else {
900 *     _Thread_queue_Context_set_thread_state(
901 *       &queue_context,
902 *       STATES_WAITING_FOR_MUTEX
903 *     );
904 *     _Thread_queue_Context_set_enqueue_do_nothing_extra( &queue_context );
905 *     _Thread_queue_Context_set_deadlock_callout(
906 *       queue_context,
907 *       _Thread_queue_Deadlock_fatal
908 *     );
909 *     _Thread_queue_Enqueue(
910 *       &mutex->Queue.Queue,
911 *       MUTEX_TQ_OPERATIONS,
912 *       executing,
913 *       &queue_context
914 *     );
915 *   }
916 * }
917 * @endcode
918 *
919 * @param queue The actual thread queue.
920 * @param operations The thread queue operations.
921 * @param[in, out] the_thread The thread to enqueue.
922 * @param[in, out] queue_context The thread queue context of the lock acquire.
923 */
924void _Thread_queue_Enqueue(
925  Thread_queue_Queue            *queue,
926  const Thread_queue_Operations *operations,
927  Thread_Control                *the_thread,
928  Thread_queue_Context          *queue_context
929);
930
931#if defined(RTEMS_SMP)
932/**
933 * @brief Enqueues the thread on the thread queue and busy waits for dequeue.
934 *
935 * Optionally starts the thread timer in case the timeout discipline is not
936 * WATCHDOG_NO_TIMEOUT. Timeout discipline and value are in the queue_context.
937 *
938 * The caller must be the owner of the thread queue lock.  This function will
939 * release the thread queue lock and register it as the new thread lock.
940 *
941 * The thread priorities of the owner and the are updated with respect to the
942 * scheduler.  The sticky level of the thread is incremented.  A thread
943 * dispatch is performed if necessary.
944 *
945 * Afterwards, the thread busy waits on the thread wait flags until a timeout
946 * occurs or the thread queue is surrendered to this thread.  So, it sticks to
947 * the processor instead of blocking with respect to the scheduler.
948 *
949 * @param queue The actual thread queue.
950 * @param operations The thread queue operations.
951 * @param[in, out] the_thread The thread to enqueue.
952 * @param[in, out] queue_context The thread queue context of the lock acquire.
953 */
954Status_Control _Thread_queue_Enqueue_sticky(
955  Thread_queue_Queue            *queue,
956  const Thread_queue_Operations *operations,
957  Thread_Control                *the_thread,
958  Thread_queue_Context          *queue_context
959);
960#endif
961
962/**
963 * @brief Extracts the thread from the thread queue, restores the default wait
964 * operations and restores the default thread lock.
965 *
966 * The caller must be the owner of the thread queue lock.  The thread queue
967 * lock is not released.
968 *
969 * @param queue The actual thread queue.
970 * @param operations The thread queue operations.
971 * @param[in, out] the_thread The thread to extract.
972 * @param[in, out] queue_context The thread queue context.
973 *
974 * @return Returns the unblock indicator for _Thread_queue_Unblock_critical().
975 * True indicates, that this thread must be unblocked by the scheduler later in
976 * _Thread_queue_Unblock_critical(), and false otherwise.  In case false is
977 * returned, then the thread queue enqueue procedure was interrupted.  Thus it
978 * will unblock itself and the thread wait information is no longer accessible,
979 * since this thread may already block on another resource in an SMP
980 * configuration.
981 */
982bool _Thread_queue_Extract_locked(
983  Thread_queue_Queue            *queue,
984  const Thread_queue_Operations *operations,
985  Thread_Control                *the_thread,
986  Thread_queue_Context          *queue_context
987);
988
989/**
990 * @brief Unblocks the thread which was on the thread queue before.
991 *
992 * The caller must be the owner of the thread queue lock.  This function will
993 * release the thread queue lock.  Thread dispatching is disabled before the
994 * thread queue lock is released and an unblock is necessary.  Thread
995 * dispatching is enabled once the sequence to unblock the thread is complete.
996 *
997 * @param unblock The unblock indicator returned by
998 * _Thread_queue_Extract_locked().
999 * @param queue The actual thread queue.
1000 * @param[in, out] the_thread The thread to extract.
1001 * @param[in, out] lock_context The lock context of the lock acquire.
1002 */
1003void _Thread_queue_Unblock_critical(
1004  bool                unblock,
1005  Thread_queue_Queue *queue,
1006  Thread_Control     *the_thread,
1007  ISR_lock_Context   *lock_context
1008);
1009
1010/**
1011 * @brief Extracts the thread from the thread queue and unblocks it.
1012 *
1013 * The caller must be the owner of the thread queue lock.  This function will
1014 * release the thread queue lock and restore the default thread lock.  Thread
1015 * dispatching is disabled before the thread queue lock is released and an
1016 * unblock is necessary.  Thread dispatching is enabled once the sequence to
1017 * unblock the thread is complete.  This makes it possible to use the thread
1018 * queue lock to protect the state of objects embedding the thread queue and
1019 * directly enter _Thread_queue_Extract_critical() to finalize an operation in
1020 * case a waiting thread exists.
1021 *
1022 * @code
1023 * #include <rtems/score/threadqimpl.h>
1024 *
1025 * typedef struct {
1026 *   Thread_queue_Control  Queue;
1027 *   Thread_Control       *owner;
1028 * } Mutex;
1029 *
1030 * void _Mutex_Release( Mutex *mutex )
1031 * {
1032 *   Thread_queue_Context  queue_context;
1033 *   Thread_Control       *first;
1034 *
1035 *   _Thread_queue_Context_initialize( &queue_context, NULL );
1036 *   _Thread_queue_Acquire( &mutex->Queue, queue_context );
1037 *
1038 *   first = _Thread_queue_First_locked( &mutex->Queue );
1039 *   mutex->owner = first;
1040 *
1041 *   if ( first != NULL ) {
1042 *     _Thread_queue_Extract_critical(
1043 *       &mutex->Queue.Queue,
1044 *       mutex->Queue.operations,
1045 *       first,
1046 *       &queue_context
1047 *   );
1048 * }
1049 * @endcode
1050 *
1051 * @param queue The actual thread queue.
1052 * @param operations The thread queue operations.
1053 * @param[in, out] the_thread The thread to extract.
1054 * @param[in, out] queue_context The thread queue context of the lock acquire.
1055 */
1056void _Thread_queue_Extract_critical(
1057  Thread_queue_Queue            *queue,
1058  const Thread_queue_Operations *operations,
1059  Thread_Control                *the_thread,
1060  Thread_queue_Context          *queue_context
1061);
1062
1063/**
1064 * @brief Extracts thread from thread queue.
1065 *
1066 * This routine removes @a the_thread its thread queue
1067 * and cancels any timeouts associated with this blocking.
1068 *
1069 * @param[in, out] the_thread The pointer to a thread control block that
1070 *     is to be removed
1071 */
1072void _Thread_queue_Extract( Thread_Control *the_thread );
1073
1074/**
1075 * @brief Extracts the_thread from the_thread_queue.
1076 *
1077 * This routine extracts the_thread from the_thread_queue
1078 * and ensures that if there is a proxy for this task on
1079 * another node, it is also dealt with. A proxy is a data
1080 * data that is on the thread queue on the remote node and
1081 * acts as a proxy for the local thread. If the local thread
1082 * was waiting on a remote operation, then the remote side
1083 * of the operation must be cleaned up.
1084 *
1085 * @param[in, out] the_thread The pointer to a thread control block that
1086 *     is to be removed
1087 */
1088void _Thread_queue_Extract_with_proxy(
1089  Thread_Control       *the_thread
1090);
1091
1092/**
1093 * @brief Surrenders the thread queue previously owned by the thread to the
1094 * first enqueued thread.
1095 *
1096 * The owner of the thread queue must be set to NULL by the caller.
1097 *
1098 * This function releases the thread queue lock.  In addition it performs a
1099 * thread dispatch if necessary.
1100 *
1101 * @param[in, out] queue The actual thread queue.
1102 * @param heads The thread queue heads.  It must not be NULL.
1103 * @param previous_owner The previous owner thread surrendering the thread
1104 *   queue.
1105 * @param queue_context The thread queue context of the lock acquire.
1106 * @param operations The thread queue operations.
1107 */
1108void _Thread_queue_Surrender(
1109  Thread_queue_Queue            *queue,
1110  Thread_queue_Heads            *heads,
1111  Thread_Control                *previous_owner,
1112  Thread_queue_Context          *queue_context,
1113  const Thread_queue_Operations *operations
1114);
1115
1116#if defined(RTEMS_SMP)
1117/**
1118 * @brief Surrenders the thread queue previously owned by the thread to the
1119 * first enqueued thread.
1120 *
1121 * The owner of the thread queue must be set to NULL by the caller.
1122 *
1123 * The caller must be the owner of the thread queue lock.  This function will
1124 * release the thread queue.
1125 *
1126 * The thread priorities of the previous owner and the new owner are updated.  The
1127 * sticky level of the previous owner is decremented.  A thread dispatch is
1128 * performed if necessary.
1129 *
1130 * @param[in, out] queue The actual thread queue.
1131 * @param heads The thread queue heads.  It must not be NULL.
1132 * @param[in, out] previous_owner The previous owner thread surrendering the thread
1133 *   queue.
1134 * @param queue_context The thread queue context of the lock acquire.
1135 * @param operations The thread queue operations.
1136 */
1137void _Thread_queue_Surrender_sticky(
1138  Thread_queue_Queue            *queue,
1139  Thread_queue_Heads            *heads,
1140  Thread_Control                *previous_owner,
1141  Thread_queue_Context          *queue_context,
1142  const Thread_queue_Operations *operations
1143);
1144#endif
1145
1146/**
1147 * @brief Checks if the thread queue queue is empty.
1148 *
1149 * @param queue The thread queue for the verification.
1150 *
1151 * @retval true @a queue is empty.
1152 * @retval false @a queue is not empty.
1153 */
1154RTEMS_INLINE_ROUTINE bool _Thread_queue_Is_empty(
1155  const Thread_queue_Queue *queue
1156)
1157{
1158  return queue->heads == NULL;
1159}
1160
1161/**
1162 * @brief Returns the first thread on the thread queue if it exists, otherwise
1163 * @c NULL.
1164 *
1165 * The caller must be the owner of the thread queue lock.  The thread queue
1166 * lock is not released.
1167 *
1168 * @param the_thread_queue The thread queue.
1169 * @param operations The thread queue operations.
1170 *
1171* @retval first The first thread on the thread queue according to the enqueue
1172 * order.
1173 * @retval NULL No thread is present on the thread queue.
1174 */
1175RTEMS_INLINE_ROUTINE Thread_Control *_Thread_queue_First_locked(
1176  Thread_queue_Control          *the_thread_queue,
1177  const Thread_queue_Operations *operations
1178)
1179{
1180  Thread_queue_Heads *heads = the_thread_queue->Queue.heads;
1181
1182  if ( heads != NULL ) {
1183    return ( *operations->first )( heads );
1184  } else {
1185    return NULL;
1186  }
1187}
1188
1189/**
1190 * @brief Returns the first thread on the thread queue if it exists, otherwise
1191 * @c NULL.
1192 *
1193 * @param the_thread_queue The thread queue.
1194 *
1195 * @retval first The first thread on the thread queue according to the enqueue
1196 * order.
1197 * @retval NULL No thread is present on the thread queue.
1198 */
1199Thread_Control *_Thread_queue_First(
1200  Thread_queue_Control          *the_thread_queue,
1201  const Thread_queue_Operations *operations
1202);
1203
1204/**
1205 * @brief Thread queue flush filter function.
1206 *
1207 * Called under protection of the thread queue lock by
1208 * _Thread_queue_Flush_critical() to optionally alter the thread wait
1209 * information and control the iteration.
1210 *
1211 * @param the_thread The thread to extract.  This is the first parameter to
1212 *   optimize for architectures that use the same register for the first
1213 *   parameter and the return value.
1214 * @param queue The actual thread queue.
1215 * @param queue_context The thread queue context of the lock acquire.  May be
1216 *   used to pass additional data to the filter function via an overlay
1217 *   structure.  The filter function should not release or acquire the thread
1218 *   queue lock.
1219 *
1220 * @retval the_thread Extract this thread.
1221 * @retval NULL Do not extract this thread and stop the thread queue flush
1222 *   operation.  Threads that are already extracted will complete the flush
1223 *   operation.
1224 */
1225typedef Thread_Control *( *Thread_queue_Flush_filter )(
1226  Thread_Control       *the_thread,
1227  Thread_queue_Queue   *queue,
1228  Thread_queue_Context *queue_context
1229);
1230
1231/**
1232 * @brief Default thread queue flush filter function.
1233 *
1234 * @param the_thread The thread to extract.
1235 * @param queue This parameter is unused.
1236 * @param queue_context This parameter is unused.
1237 *
1238 * @retval the_thread Extract this thread.
1239 */
1240Thread_Control *_Thread_queue_Flush_default_filter(
1241  Thread_Control       *the_thread,
1242  Thread_queue_Queue   *queue,
1243  Thread_queue_Context *queue_context
1244);
1245
1246/**
1247 * @brief Status unavailable thread queue flush filter function.
1248 *
1249 * Sets the thread wait return code of the thread to STATUS_UNAVAILABLE.
1250 *
1251 * @param[out] the_thread The thread to extract.
1252 * @param queue This parameter is unused.
1253 * @param queue_context This parameter is unused.
1254 *
1255 * @retval the_thread Extract this thread.
1256 */
1257Thread_Control *_Thread_queue_Flush_status_unavailable(
1258  Thread_Control       *the_thread,
1259  Thread_queue_Queue   *queue,
1260  Thread_queue_Context *queue_context
1261);
1262
1263/**
1264 * @brief Status object was deleted thread queue flush filter function.
1265 *
1266 * Sets the thread wait return code of the thread to STATUS_OBJECT_WAS_DELETED
1267 *
1268 * @param[out] the_thread The thread to extract.
1269 * @param queue This parameter is unused.
1270 * @param queue_context This parameter is unused.
1271 *
1272 * @retval the_thread Extract this thread.
1273 */
1274Thread_Control *_Thread_queue_Flush_status_object_was_deleted(
1275  Thread_Control       *the_thread,
1276  Thread_queue_Queue   *queue,
1277  Thread_queue_Context *queue_context
1278);
1279
1280/**
1281 * @brief Unblocks all threads enqueued on the thread queue.
1282 *
1283 * This function iteratively extracts the first enqueued thread of the thread
1284 * queue until the thread queue is empty or the filter function indicates a
1285 * stop.  The thread timers of the extracted threads are cancelled.  The
1286 * extracted threads are unblocked.
1287 *
1288 * @param queue The actual thread queue.
1289 * @param operations The thread queue operations.
1290 * @param filter The filter functions is called for each thread to extract from
1291 *   the thread queue.  It may be used to alter the thread under protection of
1292 *   the thread queue lock, for example to set the thread wait return code.
1293 *   The return value of the filter function controls if the thread queue flush
1294 *   operation should stop or continue.
1295 * @param queue_context The thread queue context of the lock acquire.  May be
1296 *   used to pass additional data to the filter function via an overlay
1297 *   structure.  The filter function should not release or acquire the thread
1298 *   queue lock.
1299 *
1300 * @return The count of extracted threads.
1301 */
1302size_t _Thread_queue_Flush_critical(
1303  Thread_queue_Queue            *queue,
1304  const Thread_queue_Operations *operations,
1305  Thread_queue_Flush_filter      filter,
1306  Thread_queue_Context          *queue_context
1307);
1308
1309/**
1310 * @brief Initializes the thread queue control to the given name.
1311 *
1312 * @param[out] the_thread_queue The thread queue control to initialize.
1313 * @param name The name for @a the_thread_queue.
1314 */
1315void _Thread_queue_Initialize(
1316  Thread_queue_Control *the_thread_queue,
1317  const char           *name
1318);
1319
1320#if defined(RTEMS_SMP) && defined(RTEMS_DEBUG) && defined(RTEMS_PROFILING)
1321  #define THREAD_QUEUE_INITIALIZER( _name ) \
1322    { \
1323      .Lock_stats = SMP_LOCK_STATS_INITIALIZER( _name ), \
1324      .owner = SMP_LOCK_NO_OWNER, \
1325      .Queue = { \
1326        .Lock = SMP_TICKET_LOCK_INITIALIZER, \
1327        .heads = NULL, \
1328        .owner = NULL, \
1329        .name = _name \
1330      } \
1331    }
1332#elif defined(RTEMS_SMP) && defined(RTEMS_DEBUG)
1333  #define THREAD_QUEUE_INITIALIZER( _name ) \
1334    { \
1335      .owner = SMP_LOCK_NO_OWNER, \
1336      .Queue = { \
1337        .Lock = SMP_TICKET_LOCK_INITIALIZER, \
1338        .heads = NULL, \
1339        .owner = NULL, \
1340        .name = _name \
1341      } \
1342    }
1343#elif defined(RTEMS_SMP) && defined(RTEMS_PROFILING)
1344  #define THREAD_QUEUE_INITIALIZER( _name ) \
1345    { \
1346      .Lock_stats = SMP_LOCK_STATS_INITIALIZER( _name ), \
1347      .Queue = { \
1348        .Lock = SMP_TICKET_LOCK_INITIALIZER, \
1349        .heads = NULL, \
1350        .owner = NULL, \
1351        .name = _name \
1352      } \
1353    }
1354#elif defined(RTEMS_SMP)
1355  #define THREAD_QUEUE_INITIALIZER( _name ) \
1356    { \
1357      .Queue = { \
1358        .Lock = SMP_TICKET_LOCK_INITIALIZER, \
1359        .heads = NULL, \
1360        .owner = NULL, \
1361        .name = _name \
1362      } \
1363    }
1364#else
1365  #define THREAD_QUEUE_INITIALIZER( _name ) \
1366    { \
1367      .Queue = { \
1368        .heads = NULL, \
1369        .owner = NULL, \
1370        .name = _name \
1371      } \
1372    }
1373#endif
1374
1375/**
1376 * @brief Destroys the thread queue.
1377 *
1378 * @param[out] the_thread_queue The thread queue to destroy.
1379 */
1380RTEMS_INLINE_ROUTINE void _Thread_queue_Destroy(
1381  Thread_queue_Control *the_thread_queue
1382)
1383{
1384#if defined(RTEMS_SMP)
1385  _SMP_ticket_lock_Destroy( &the_thread_queue->Queue.Lock );
1386  _SMP_lock_Stats_destroy( &the_thread_queue->Lock_stats );
1387#endif
1388}
1389
1390/**
1391 * @brief Does nothing.
1392 *
1393 * @param the_proxy This parameter is unused.
1394 * @param mp_id This parameter is unused.
1395 */
1396#if defined(RTEMS_MULTIPROCESSING)
1397void _Thread_queue_MP_callout_do_nothing(
1398  Thread_Control *the_proxy,
1399  Objects_Id      mp_id
1400);
1401
1402/**
1403 * @brief Unblocks the proxy of the thread.
1404 *
1405 * @param queue The thread queue queue.
1406 * @param the_threat The thread to unblock proxy (after casting it to Thread_Proxy_control *).
1407 */
1408void _Thread_queue_Unblock_proxy(
1409  Thread_queue_Queue *queue,
1410  Thread_Control     *the_thread
1411);
1412#endif
1413
1414/**
1415 * @brief Acquires the thread queue path in a critical section.
1416 *
1417 * @param queue The thread queue queue.
1418 * @param the_thread The thread for the operation.
1419 * @param queue_context The thread queue context.
1420 *
1421 * @retval true The operation was successful.
1422 * @retval false The operation failed.
1423 */
1424#if defined(RTEMS_SMP)
1425bool _Thread_queue_Path_acquire_critical(
1426  Thread_queue_Queue   *queue,
1427  Thread_Control       *the_thread,
1428  Thread_queue_Context *queue_context
1429);
1430
1431/**
1432 * @brief Releases the thread queue path in a critical section.
1433 *
1434 * @param queue_context The thread queue context.
1435 */
1436void _Thread_queue_Path_release_critical(
1437  Thread_queue_Context *queue_context
1438);
1439#endif
1440
1441/**
1442 * @brief Helper structure to ensure that all objects containing a thread queue
1443 * have the right layout.
1444 *
1445 * @see _Thread_Wait_get_id() and THREAD_QUEUE_OBJECT_ASSERT().
1446 */
1447typedef struct {
1448  Objects_Control      Object;
1449  Thread_queue_Control Wait_queue;
1450} Thread_queue_Object;
1451
1452#define THREAD_QUEUE_OBJECT_ASSERT( object_type, wait_queue_member, msg ) \
1453  RTEMS_STATIC_ASSERT( \
1454    offsetof( object_type, wait_queue_member ) \
1455      == offsetof( Thread_queue_Object, Wait_queue ) \
1456    && RTEMS_HAVE_MEMBER_SAME_TYPE( \
1457      object_type, \
1458      wait_queue_member, \
1459      Thread_queue_Object, \
1460      Wait_queue \
1461    ), \
1462    msg \
1463  )
1464
1465#define THREAD_QUEUE_QUEUE_TO_OBJECT( queue ) \
1466  RTEMS_CONTAINER_OF( \
1467    queue, \
1468    Thread_queue_Object, \
1469    Wait_queue.Queue \
1470  )
1471
1472extern const Thread_queue_Operations _Thread_queue_Operations_default;
1473
1474extern const Thread_queue_Operations _Thread_queue_Operations_FIFO;
1475
1476extern const Thread_queue_Operations _Thread_queue_Operations_priority;
1477
1478extern const Thread_queue_Operations _Thread_queue_Operations_priority_inherit;
1479
1480/**
1481 * @brief The special thread queue name to indicated that the thread queue is
1482 * embedded in an object with identifier.
1483 *
1484 * @see _Thread_queue_Object_initialize().
1485 */
1486extern const char _Thread_queue_Object_name[];
1487
1488/**
1489 * @brief Initializes a thread queue embedded in an object with identifier.
1490 *
1491 * The object must have the layout specified by Thread_queue_Object.  It should
1492 * be ensured with the THREAD_QUEUE_OBJECT_ASSERT() static assertion.
1493 *
1494 * @param[out] the_thread_queue The thread queue.
1495 */
1496void _Thread_queue_Object_initialize(
1497  Thread_queue_Control *the_thread_queue
1498);
1499
1500/** @} */
1501
1502#ifdef __cplusplus
1503}
1504#endif
1505
1506#endif
1507/* end of include file */
Note: See TracBrowser for help on using the repository browser.