source: rtems/cpukit/score/include/rtems/score/threadqimpl.h @ dfcc8bb

Last change on this file since dfcc8bb was dfcc8bb, checked in by Sebastian Huber <sebastian.huber@…>, on May 3, 2016 at 5:43:54 AM

score: Adjust thread queue layout

Adjust thread queue layout according to Newlib. This makes it possible
to use the same implementation for <sys/lock.h> and CORE mutexes in the
future.

  • Property mode set to 100644
File size: 22.7 KB
Line 
1/**
2 *  @file  rtems/score/threadq.h
3 *
4 *  Constants and Structures Associated with the Manipulation of Objects
5 *
6 *  This include file contains all the constants and structures associated
7 *  with the manipulation of objects.
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/rbtreeimpl.h>
25#include <rtems/score/scheduler.h>
26#include <rtems/score/smp.h>
27#include <rtems/score/thread.h>
28
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33/**
34 *  @addtogroup ScoreThreadQueue
35 */
36/**@{*/
37
38/**
39 * @brief Thread queue with a layout compatible to struct _Thread_queue_Queue
40 * defined in Newlib <sys/lock.h>.
41 */
42typedef struct {
43#if !defined(RTEMS_SMP)
44  /*
45   * The struct _Thread_queue_Queue definition is independent of the RTEMS
46   * build configuration.  Thus, the storage space for the SMP lock is always
47   * present.  In SMP configurations, the SMP lock is contained in the
48   * Thread_queue_Queue.
49   */
50  unsigned int reserved[2];
51#endif
52
53  Thread_queue_Queue Queue;
54} Thread_queue_Syslock_queue;
55
56RTEMS_INLINE_ROUTINE void _Thread_queue_Do_context_initialize(
57  Thread_queue_Context    *queue_context
58#if defined(RTEMS_MULTIPROCESSING)
59  ,
60  Thread_queue_MP_callout  mp_callout
61#endif
62)
63{
64#if defined(RTEMS_MULTIPROCESSING)
65  queue_context->mp_callout = mp_callout;
66#else
67  (void) queue_context;
68#endif
69}
70
71/**
72 * @brief Initializes a thread queue context.
73 *
74 * @param queue_context The thread queue context to initialize.
75 * @param mp_callout Callout to unblock the thread in case it is actually a
76 *   thread proxy.  This parameter is only used on multiprocessing
77 *   configurations.  Used by thread queue extract and unblock methods for
78 *   objects with multiprocessing (MP) support.
79 */
80#if defined(RTEMS_MULTIPROCESSING)
81  #define _Thread_queue_Context_initialize( \
82    queue_context, \
83    mp_callout \
84  ) \
85    _Thread_queue_Do_context_initialize( \
86      queue_context, \
87      mp_callout \
88    )
89#else
90  #define _Thread_queue_Context_initialize( \
91    queue_context, \
92    mp_callout \
93  ) \
94    _Thread_queue_Do_context_initialize( \
95      queue_context \
96    )
97#endif
98
99RTEMS_INLINE_ROUTINE void _Thread_queue_Heads_initialize(
100  Thread_queue_Heads *heads
101)
102{
103#if defined(RTEMS_SMP)
104  size_t i;
105
106  for ( i = 0; i < _Scheduler_Count; ++i ) {
107    _RBTree_Initialize_empty( &heads->Priority[ i ].Queue );
108  }
109#endif
110
111  _Chain_Initialize_empty( &heads->Free_chain );
112}
113
114RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_initialize(
115  Thread_queue_Queue *queue
116)
117{
118#if defined(RTEMS_SMP)
119  _SMP_ticket_lock_Initialize( &queue->Lock );
120#endif
121  queue->heads = NULL;
122  queue->owner = NULL;
123}
124
125RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_do_acquire_critical(
126  Thread_queue_Queue *queue,
127#if defined(RTEMS_SMP) && defined(RTEMS_PROFILING)
128  SMP_lock_Stats     *lock_stats,
129#endif
130  ISR_lock_Context   *lock_context
131)
132{
133#if defined(RTEMS_SMP)
134  _SMP_ticket_lock_Acquire(
135    &queue->Lock,
136    lock_stats,
137    &lock_context->Lock_context.Stats_context
138  );
139#else
140  (void) queue;
141  (void) lock_context;
142#endif
143}
144
145#if defined(RTEMS_SMP) && defined( RTEMS_PROFILING )
146  #define \
147    _Thread_queue_Queue_acquire_critical( queue, lock_stats, lock_context ) \
148    _Thread_queue_Queue_do_acquire_critical( queue, lock_stats, lock_context )
149#else
150  #define \
151    _Thread_queue_Queue_acquire_critical( queue, lock_stats, lock_context ) \
152    _Thread_queue_Queue_do_acquire_critical( queue, lock_context )
153#endif
154
155RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_release_critical(
156  Thread_queue_Queue *queue,
157  ISR_lock_Context   *lock_context
158)
159{
160#if defined(RTEMS_SMP)
161  _SMP_ticket_lock_Release(
162    &queue->Lock,
163    &lock_context->Lock_context.Stats_context
164  );
165#else
166  (void) queue;
167  (void) lock_context;
168#endif
169}
170
171RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_release(
172  Thread_queue_Queue *queue,
173  ISR_lock_Context   *lock_context
174)
175{
176  _Thread_queue_Queue_release_critical( queue, lock_context );
177  _ISR_lock_ISR_enable( lock_context );
178}
179
180RTEMS_INLINE_ROUTINE void _Thread_queue_Acquire_critical(
181  Thread_queue_Control *the_thread_queue,
182  ISR_lock_Context     *lock_context
183)
184{
185  _Thread_queue_Queue_acquire_critical(
186    &the_thread_queue->Queue,
187    &the_thread_queue->Lock_stats,
188    lock_context
189  );
190#if defined(RTEMS_DEBUG) && defined(RTEMS_SMP)
191  the_thread_queue->owner = _SMP_Get_current_processor();
192#endif
193}
194
195RTEMS_INLINE_ROUTINE void _Thread_queue_Acquire(
196  Thread_queue_Control *the_thread_queue,
197  ISR_lock_Context     *lock_context
198)
199{
200  _ISR_lock_ISR_disable( lock_context );
201  _Thread_queue_Acquire_critical( the_thread_queue, lock_context );
202}
203
204#if defined(RTEMS_DEBUG)
205RTEMS_INLINE_ROUTINE bool _Thread_queue_Is_lock_owner(
206  const Thread_queue_Control *the_thread_queue
207)
208{
209#if defined(RTEMS_SMP)
210  return the_thread_queue->owner == _SMP_Get_current_processor();
211#else
212  return _ISR_Get_level() != 0;
213#endif
214}
215#endif
216
217RTEMS_INLINE_ROUTINE void _Thread_queue_Release_critical(
218  Thread_queue_Control *the_thread_queue,
219  ISR_lock_Context     *lock_context
220)
221{
222#if defined(RTEMS_DEBUG)
223  _Assert( _Thread_queue_Is_lock_owner( the_thread_queue ) );
224#if defined(RTEMS_SMP)
225  the_thread_queue->owner = SMP_LOCK_NO_OWNER;
226#endif
227#endif
228  _Thread_queue_Queue_release_critical(
229    &the_thread_queue->Queue,
230    lock_context
231  );
232}
233
234RTEMS_INLINE_ROUTINE void _Thread_queue_Release(
235  Thread_queue_Control *the_thread_queue,
236  ISR_lock_Context     *lock_context
237)
238{
239  _Thread_queue_Release_critical( the_thread_queue, lock_context );
240  _ISR_lock_ISR_enable( lock_context );
241}
242
243Thread_Control *_Thread_queue_Do_dequeue(
244  Thread_queue_Control          *the_thread_queue,
245  const Thread_queue_Operations *operations
246#if defined(RTEMS_MULTIPROCESSING)
247  ,
248  Thread_queue_MP_callout        mp_callout
249#endif
250);
251
252/**
253 *  @brief Gets a pointer to a thread waiting on the_thread_queue.
254 *
255 *  This function returns a pointer to a thread waiting on
256 *  the_thread_queue.  The selection of this thread is based on
257 *  the discipline of the_thread_queue.  If no threads are waiting
258 *  on the_thread_queue, then NULL is returned.
259 *
260 *  - INTERRUPT LATENCY:
261 *    + single case
262 */
263#if defined(RTEMS_MULTIPROCESSING)
264  #define _Thread_queue_Dequeue( \
265    the_thread_queue, \
266    operations, \
267    mp_callout \
268  ) \
269    _Thread_queue_Do_dequeue( \
270      the_thread_queue, \
271      operations, \
272      mp_callout \
273    )
274#else
275  #define _Thread_queue_Dequeue( \
276    the_thread_queue, \
277    operations, \
278    mp_callout \
279  ) \
280    _Thread_queue_Do_dequeue( \
281      the_thread_queue, \
282      operations \
283    )
284#endif
285
286/**
287 * @brief Blocks the thread and places it on the thread queue.
288 *
289 * This enqueues the thread on the thread queue, blocks the thread, and
290 * optionally starts the thread timer in case the timeout interval is not
291 * WATCHDOG_NO_TIMEOUT.
292 *
293 * The caller must be the owner of the thread queue lock.  This function will
294 * release the thread queue lock and register it as the new thread lock.
295 * Thread dispatching is disabled before the thread queue lock is released.
296 * Thread dispatching is enabled once the sequence to block the thread is
297 * complete.  The operation to enqueue the thread on the queue is protected by
298 * the thread queue lock.  This makes it possible to use the thread queue lock
299 * to protect the state of objects embedding the thread queue and directly
300 * enter _Thread_queue_Enqueue_critical() in case the thread must block.
301 *
302 * @code
303 * #include <rtems/score/threadqimpl.h>
304 * #include <rtems/score/statesimpl.h>
305 *
306 * #define MUTEX_TQ_OPERATIONS &_Thread_queue_Operations_priority
307 *
308 * typedef struct {
309 *   Thread_queue_Control  Queue;
310 *   Thread_Control       *owner;
311 * } Mutex;
312 *
313 * void _Mutex_Obtain( Mutex *mutex )
314 * {
315 *   ISR_lock_Context  lock_context;
316 *   Thread_Control   *executing;
317 *
318 *   _Thread_queue_Acquire( &mutex->Queue, &lock_context );
319 *
320 *   executing = _Thread_Executing;
321 *
322 *   if ( mutex->owner == NULL ) {
323 *     mutex->owner = executing;
324 *     _Thread_queue_Release( &mutex->Queue, &lock_context );
325 *   } else {
326 *     _Thread_queue_Enqueue_critical(
327 *       &mutex->Queue.Queue,
328 *       MUTEX_TQ_OPERATIONS,
329 *       executing,
330 *       STATES_WAITING_FOR_MUTEX,
331 *       WATCHDOG_NO_TIMEOUT,
332 *       0,
333 *       &lock_context
334 *     );
335 *   }
336 * }
337 * @endcode
338 *
339 * @param[in] queue The actual thread queue.
340 * @param[in] operations The thread queue operations.
341 * @param[in] the_thread The thread to enqueue.
342 * @param[in] state The new state of the thread.
343 * @param[in] timeout Interval to wait.  Use WATCHDOG_NO_TIMEOUT to block
344 * potentially forever.
345 * @param[in] lock_context The lock context of the lock acquire.
346 */
347void _Thread_queue_Enqueue_critical(
348  Thread_queue_Queue            *queue,
349  const Thread_queue_Operations *operations,
350  Thread_Control                *the_thread,
351  States_Control                 state,
352  Watchdog_Interval              timeout,
353  ISR_lock_Context              *lock_context
354);
355
356/**
357 * @brief Acquires the thread queue lock and calls
358 * _Thread_queue_Enqueue_critical().
359 */
360RTEMS_INLINE_ROUTINE void _Thread_queue_Enqueue(
361  Thread_queue_Control          *the_thread_queue,
362  const Thread_queue_Operations *operations,
363  Thread_Control                *the_thread,
364  States_Control                 state,
365  Watchdog_Interval              timeout
366)
367{
368  ISR_lock_Context lock_context;
369
370  _Thread_queue_Acquire( the_thread_queue, &lock_context );
371  _Thread_queue_Enqueue_critical(
372    &the_thread_queue->Queue,
373    operations,
374    the_thread,
375    state,
376    timeout,
377    &lock_context
378  );
379}
380
381bool _Thread_queue_Do_extract_locked(
382  Thread_queue_Queue            *queue,
383  const Thread_queue_Operations *operations,
384  Thread_Control                *the_thread
385#if defined(RTEMS_MULTIPROCESSING)
386  ,
387  const Thread_queue_Context    *queue_context
388#endif
389);
390
391/**
392 * @brief Extracts the thread from the thread queue, restores the default wait
393 * operations and restores the default thread lock.
394 *
395 * The caller must be the owner of the thread queue lock.  The thread queue
396 * lock is not released.
397 *
398 * @param[in] queue The actual thread queue.
399 * @param[in] operations The thread queue operations.
400 * @param[in] the_thread The thread to extract.
401 * @param[in] queue_context The thread queue context.  This parameter is only
402 *   used on multiprocessing configurations.
403 *
404 * @return Returns the unblock indicator for _Thread_queue_Unblock_critical().
405 * True indicates, that this thread must be unblocked by the scheduler later in
406 * _Thread_queue_Unblock_critical(), and false otherwise.  In case false is
407 * returned, then the thread queue enqueue procedure was interrupted.  Thus it
408 * will unblock itself and the thread wait information is no longer accessible,
409 * since this thread may already block on another resource in an SMP
410 * configuration.
411 */
412#if defined(RTEMS_MULTIPROCESSING)
413  #define _Thread_queue_Extract_locked( \
414    unblock, \
415    queue, \
416    the_thread, \
417    queue_context \
418  ) \
419    _Thread_queue_Do_extract_locked( \
420      unblock, \
421      queue, \
422      the_thread, \
423      queue_context \
424    )
425#else
426  #define _Thread_queue_Extract_locked( \
427    unblock, \
428    queue, \
429    the_thread, \
430    queue_context \
431  ) \
432    _Thread_queue_Do_extract_locked( \
433      unblock, \
434      queue, \
435      the_thread \
436    )
437#endif
438
439/**
440 * @brief Unblocks the thread which was on the thread queue before.
441 *
442 * The caller must be the owner of the thread queue lock.  This function will
443 * release the thread queue lock.  Thread dispatching is disabled before the
444 * thread queue lock is released and an unblock is necessary.  Thread
445 * dispatching is enabled once the sequence to unblock the thread is complete.
446 *
447 * @param[in] unblock The unblock indicator returned by
448 * _Thread_queue_Extract_locked().
449 * @param[in] queue The actual thread queue.
450 * @param[in] the_thread The thread to extract.
451 * @param[in] lock_context The lock context of the lock acquire.
452 */
453void _Thread_queue_Unblock_critical(
454  bool                unblock,
455  Thread_queue_Queue *queue,
456  Thread_Control     *the_thread,
457  ISR_lock_Context   *lock_context
458);
459
460/**
461 * @brief Extracts the thread from the thread queue and unblocks it.
462 *
463 * The caller must be the owner of the thread queue lock.  This function will
464 * release the thread queue lock and restore the default thread lock.  Thread
465 * dispatching is disabled before the thread queue lock is released and an
466 * unblock is necessary.  Thread dispatching is enabled once the sequence to
467 * unblock the thread is complete.  This makes it possible to use the thread
468 * queue lock to protect the state of objects embedding the thread queue and
469 * directly enter _Thread_queue_Extract_critical() to finalize an operation in
470 * case a waiting thread exists.
471 *
472 * @code
473 * #include <rtems/score/threadqimpl.h>
474 *
475 * typedef struct {
476 *   Thread_queue_Control  Queue;
477 *   Thread_Control       *owner;
478 * } Mutex;
479 *
480 * void _Mutex_Release( Mutex *mutex )
481 * {
482 *   Thread_queue_Context  queue_context;
483 *   Thread_Control       *first;
484 *
485 *   _Thread_queue_Context_initialize( &queue_context, NULL );
486 *   _Thread_queue_Acquire( &mutex->Queue, &queue_context.Lock_context );
487 *
488 *   first = _Thread_queue_First_locked( &mutex->Queue );
489 *   mutex->owner = first;
490 *
491 *   if ( first != NULL ) {
492 *     _Thread_queue_Extract_critical(
493 *       &mutex->Queue.Queue,
494 *       mutex->Queue.operations,
495 *       first,
496 *       &queue_context
497 *   );
498 * }
499 * @endcode
500 *
501 * @param[in] queue The actual thread queue.
502 * @param[in] operations The thread queue operations.
503 * @param[in] the_thread The thread to extract.
504 * @param[in] queue_context The thread queue context of the lock acquire.
505 */
506void _Thread_queue_Extract_critical(
507  Thread_queue_Queue            *queue,
508  const Thread_queue_Operations *operations,
509  Thread_Control                *the_thread,
510  Thread_queue_Context          *queue_context
511);
512
513/**
514 *  @brief Extracts thread from thread queue.
515 *
516 *  This routine removes @a the_thread its thread queue
517 *  and cancels any timeouts associated with this blocking.
518 *
519 *  @param[in] the_thread is the pointer to a thread control block that
520 *      is to be removed
521 */
522void _Thread_queue_Extract( Thread_Control *the_thread );
523
524/**
525 *  @brief Extracts the_thread from the_thread_queue.
526 *
527 *  This routine extracts the_thread from the_thread_queue
528 *  and ensures that if there is a proxy for this task on
529 *  another node, it is also dealt with.
530 */
531void _Thread_queue_Extract_with_proxy(
532  Thread_Control       *the_thread
533);
534
535RTEMS_INLINE_ROUTINE bool _Thread_queue_Is_empty(
536  const Thread_queue_Queue *queue
537)
538{
539  return queue->heads == NULL;
540}
541
542/**
543 * @brief Returns the first thread on the thread queue if it exists, otherwise
544 * @c NULL.
545 *
546 * The caller must be the owner of the thread queue lock.  The thread queue
547 * lock is not released.
548 *
549 * @param[in] the_thread_queue The thread queue.
550 * @param[in] operations The thread queue operations.
551 *
552 * @retval NULL No thread is present on the thread queue.
553 * @retval first The first thread on the thread queue according to the enqueue
554 * order.
555 */
556RTEMS_INLINE_ROUTINE Thread_Control *_Thread_queue_First_locked(
557  Thread_queue_Control          *the_thread_queue,
558  const Thread_queue_Operations *operations
559)
560{
561  Thread_queue_Heads *heads = the_thread_queue->Queue.heads;
562
563  if ( heads != NULL ) {
564    return ( *operations->first )( heads );
565  } else {
566    return NULL;
567  }
568}
569
570/**
571 * @brief Returns the first thread on the thread queue if it exists, otherwise
572 * @c NULL.
573 *
574 * @param[in] the_thread_queue The thread queue.
575 *
576 * @retval NULL No thread is present on the thread queue.
577 * @retval first The first thread on the thread queue according to the enqueue
578 * order.
579 */
580Thread_Control *_Thread_queue_First(
581  Thread_queue_Control          *the_thread_queue,
582  const Thread_queue_Operations *operations
583);
584
585/**
586 * @brief Thread queue flush filter function.
587 *
588 * Called under protection of the thread queue lock by
589 * _Thread_queue_Flush_critical() to optionally alter the thread wait
590 * information and control the iteration.
591 *
592 * @param the_thread The thread to extract.  This is the first parameter to
593 *   optimize for architectures that use the same register for the first
594 *   parameter and the return value.
595 * @param queue The actual thread queue.
596 * @param queue_context The thread queue context of the lock acquire.  May be
597 *   used to pass additional data to the filter function via an overlay
598 *   structure.  The filter function should not release or acquire the thread
599 *   queue lock.
600 *
601 * @retval the_thread Extract this thread.
602 * @retval NULL Do not extract this thread and stop the thread queue flush
603 *   operation.  Threads that are already extracted will complete the flush
604 *   operation.
605 */
606typedef Thread_Control *( *Thread_queue_Flush_filter )(
607  Thread_Control       *the_thread,
608  Thread_queue_Queue   *queue,
609  Thread_queue_Context *queue_context
610);
611
612/**
613 * @brief Default thread queue flush filter function.
614 *
615 * @param the_thread The thread to extract.
616 * @param queue Unused.
617 * @param queue_context Unused.
618 *
619 * @retval the_thread Extract this thread.
620 */
621Thread_Control *_Thread_queue_Flush_default_filter(
622  Thread_Control       *the_thread,
623  Thread_queue_Queue   *queue,
624  Thread_queue_Context *queue_context
625);
626
627/**
628 * @brief Status unavailable thread queue flush filter function.
629 *
630 * Sets the thread wait return code of the thread to STATUS_UNAVAILABLE.
631 *
632 * @param the_thread The thread to extract.
633 * @param queue Unused.
634 * @param queue_context Unused.
635 *
636 * @retval the_thread Extract this thread.
637 */
638Thread_Control *_Thread_queue_Flush_status_unavailable(
639  Thread_Control       *the_thread,
640  Thread_queue_Queue   *queue,
641  Thread_queue_Context *queue_context
642);
643
644/**
645 * @brief Status object was deleted thread queue flush filter function.
646 *
647 * Sets the thread wait return code of the thread to STATUS_OBJECT_WAS_DELETED
648 *
649 * @param the_thread The thread to extract.
650 * @param queue Unused.
651 * @param queue_context Unused.
652 *
653 * @retval the_thread Extract this thread.
654 */
655Thread_Control *_Thread_queue_Flush_status_object_was_deleted(
656  Thread_Control       *the_thread,
657  Thread_queue_Queue   *queue,
658  Thread_queue_Context *queue_context
659);
660
661/**
662 * @brief Unblocks all threads enqueued on the thread queue.
663 *
664 * This function iteratively extracts the first enqueued thread of the thread
665 * queue until the thread queue is empty or the filter function indicates a
666 * stop.  The thread timers of the extracted threads are cancelled.  The
667 * extracted threads are unblocked.
668 *
669 * @param queue The actual thread queue.
670 * @param operations The thread queue operations.
671 * @param filter The filter functions is called for each thread to extract from
672 *   the thread queue.  It may be used to alter the thread under protection of
673 *   the thread queue lock, for example to set the thread wait return code.
674 *   The return value of the filter function controls if the thread queue flush
675 *   operation should stop or continue.
676 * @param queue_context The thread queue context of the lock acquire.  May be
677 *   used to pass additional data to the filter function via an overlay
678 *   structure.  The filter function should not release or acquire the thread
679 *   queue lock.
680 *
681 * @return The count of extracted threads.
682 */
683size_t _Thread_queue_Flush_critical(
684  Thread_queue_Queue            *queue,
685  const Thread_queue_Operations *operations,
686  Thread_queue_Flush_filter      filter,
687  Thread_queue_Context          *queue_context
688);
689
690void _Thread_queue_Initialize( Thread_queue_Control *the_thread_queue );
691
692#if defined(RTEMS_SMP) && defined(RTEMS_DEBUG) && defined(RTEMS_PROFILING)
693  #define THREAD_QUEUE_INITIALIZER( name ) \
694    { \
695      .Lock_stats = SMP_LOCK_STATS_INITIALIZER( name ), \
696      .owner = SMP_LOCK_NO_OWNER, \
697      .Queue = { \
698        .heads = NULL, \
699        .Lock = SMP_TICKET_LOCK_INITIALIZER, \
700      } \
701    }
702#elif defined(RTEMS_SMP) && defined(RTEMS_DEBUG)
703  #define THREAD_QUEUE_INITIALIZER( name ) \
704    { \
705      .owner = SMP_LOCK_NO_OWNER, \
706      .Queue = { \
707        .heads = NULL, \
708        .Lock = SMP_TICKET_LOCK_INITIALIZER, \
709      } \
710    }
711#elif defined(RTEMS_SMP) && defined(RTEMS_PROFILING)
712  #define THREAD_QUEUE_INITIALIZER( name ) \
713    { \
714      .Lock_stats = SMP_LOCK_STATS_INITIALIZER( name ), \
715      .Queue = { \
716        .heads = NULL, \
717        .Lock = SMP_TICKET_LOCK_INITIALIZER, \
718      } \
719    }
720#elif defined(RTEMS_SMP)
721  #define THREAD_QUEUE_INITIALIZER( name ) \
722    { \
723      .Queue = { \
724        .heads = NULL, \
725        .Lock = SMP_TICKET_LOCK_INITIALIZER, \
726      } \
727    }
728#else
729  #define THREAD_QUEUE_INITIALIZER( name ) \
730    { .Queue = { .heads = NULL } }
731#endif
732
733RTEMS_INLINE_ROUTINE void _Thread_queue_Destroy(
734  Thread_queue_Control *the_thread_queue
735)
736{
737#if defined(RTEMS_SMP)
738  _SMP_ticket_lock_Destroy( &the_thread_queue->Queue.Lock );
739  _SMP_lock_Stats_destroy( &the_thread_queue->Lock_stats );
740#endif
741}
742
743/**
744 * @brief Boosts the priority of the thread if threads of another scheduler
745 * instance are enqueued on the thread queue.
746 *
747 * The thread queue must use the priority waiting discipline.
748 *
749 * @param[in] queue The actual thread queue.
750 * @param[in] the_thread The thread to boost the priority if necessary.
751 */
752#if defined(RTEMS_SMP)
753void _Thread_queue_Boost_priority(
754  Thread_queue_Queue *queue,
755  Thread_Control     *the_thread
756);
757#else
758RTEMS_INLINE_ROUTINE void _Thread_queue_Boost_priority(
759  Thread_queue_Queue *queue,
760  Thread_Control     *the_thread
761)
762{
763  (void) queue;
764  (void) the_thread;
765}
766#endif
767
768#if defined(RTEMS_MULTIPROCESSING)
769void _Thread_queue_MP_callout_do_nothing(
770  Thread_Control *the_proxy,
771  Objects_Id      mp_id
772);
773
774void _Thread_queue_Unblock_proxy(
775  Thread_queue_Queue *queue,
776  Thread_Control     *the_thread
777);
778#endif
779
780/**
781 * @brief Helper structure to ensure that all objects containing a thread queue
782 * have the right layout.
783 *
784 * @see _Thread_Wait_get_id() and THREAD_QUEUE_OBJECT_ASSERT().
785 */
786typedef struct {
787  Objects_Control      Object;
788  Thread_queue_Control Wait_queue;
789} Thread_queue_Object;
790
791#define THREAD_QUEUE_OBJECT_ASSERT( object_type, wait_queue_member ) \
792  RTEMS_STATIC_ASSERT( \
793    offsetof( object_type, wait_queue_member ) \
794      == offsetof( Thread_queue_Object, Wait_queue ) \
795    && ( &( ( (object_type *) 0 )->wait_queue_member ) \
796      == ( &( (Thread_queue_Object *) 0 )->Wait_queue ) ), \
797    object_type \
798  )
799
800#define THREAD_QUEUE_QUEUE_TO_OBJECT( queue ) \
801  RTEMS_CONTAINER_OF( \
802    queue, \
803    Thread_queue_Object, \
804    Wait_queue.Queue \
805  )
806
807extern const Thread_queue_Operations _Thread_queue_Operations_default;
808
809extern const Thread_queue_Operations _Thread_queue_Operations_FIFO;
810
811extern const Thread_queue_Operations _Thread_queue_Operations_priority;
812
813/**@}*/
814
815#ifdef __cplusplus
816}
817#endif
818
819#endif
820/* end of include file */
Note: See TracBrowser for help on using the repository browser.