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

Last change on this file since dce48791 was dce48791, checked in by Sebastian Huber <sebastian.huber@…>, on May 23, 2016 at 11:37:59 AM

score: Add Status_Control for all APIs

Unify the status codes of the Classic and POSIX API to use the new enum
Status_Control. This eliminates the Thread_Control::Wait::timeout_code
field and the timeout parameter of _Thread_queue_Enqueue_critical() and
_MPCI_Send_request_packet(). It gets rid of the status code translation
tables and instead uses simple bit operations to get the status for a
particular API. This enables translation of status code constants at
compile time. Add _Thread_Wait_get_status() to avoid direct access of
thread internal data structures.

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