source: rtems/cpukit/include/rtems/score/threadq.h @ 0f5b2c09

5
Last change on this file since 0f5b2c09 was ccc6695, checked in by Sebastian Huber <sebastian.huber@…>, on 11/08/18 at 10:50:24

score: Introduce <rtems/score/watchdogticks.h>

Separate the definitions related to watchdog ticks from the watchdog
structures.

Update #3598.

  • Property mode set to 100644
File size: 15.6 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief Constants and Structures Needed to Declare a Thread Queue
5 *
6 *  This include file contains all the constants and structures
7 *  needed to declare a thread queue.
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_THREADQ_H
20#define _RTEMS_SCORE_THREADQ_H
21
22#include <rtems/score/chain.h>
23#include <rtems/score/isrlock.h>
24#include <rtems/score/object.h>
25#include <rtems/score/priority.h>
26#include <rtems/score/rbtree.h>
27#include <rtems/score/states.h>
28#include <rtems/score/watchdogticks.h>
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
34struct Per_CPU_Control;
35
36struct Scheduler_Node;
37
38/**
39 *  @defgroup ScoreThreadQueue Thread Queue Handler
40 *
41 *  @ingroup Score
42 *
43 *  This handler provides the capability to have threads block in
44 *  ordered sets. The sets may be ordered using the FIFO or priority
45 *  discipline.
46 */
47/**@{*/
48
49typedef struct _Thread_Control Thread_Control;
50
51typedef struct Thread_queue_Context Thread_queue_Context;
52
53typedef struct Thread_queue_Queue Thread_queue_Queue;
54
55typedef struct Thread_queue_Operations Thread_queue_Operations;
56
57/**
58 * @brief Thread queue enqueue callout.
59 *
60 * @param[in] queue The actual thread queue.
61 * @param[in] the_thread The thread to enqueue.
62 * @param[in] cpu_self The current processor.
63 * @param[in] queue_context The thread queue context of the lock acquire.
64 *
65 * @see _Thread_queue_Context_set_enqueue_callout().
66 */
67typedef void ( *Thread_queue_Enqueue_callout )(
68  Thread_queue_Queue     *queue,
69  Thread_Control         *the_thread,
70  struct Per_CPU_Control *cpu_self,
71  Thread_queue_Context   *queue_context
72);
73
74/**
75 * @brief Thread queue deadlock callout.
76 *
77 * @param the_thread The thread that detected the deadlock.
78 *
79 * @see _Thread_queue_Context_set_deadlock_callout().
80 */
81typedef void ( *Thread_queue_Deadlock_callout )(
82  Thread_Control *the_thread
83);
84
85#if defined(RTEMS_MULTIPROCESSING)
86/**
87 * @brief Multiprocessing (MP) support callout for thread queue operations.
88 *
89 * @param the_proxy The thread proxy of the thread queue operation.  A thread
90 *   control is actually a thread proxy if and only if
91 *   _Objects_Is_local_id( the_proxy->Object.id ) is false.
92 * @param mp_id Object identifier of the object containing the thread queue.
93 *
94 * @see _Thread_queue_Context_set_MP_callout().
95 */
96typedef void ( *Thread_queue_MP_callout )(
97  Thread_Control *the_proxy,
98  Objects_Id      mp_id
99);
100#endif
101
102#if defined(RTEMS_SMP)
103/**
104 * @brief The thread queue gate is an SMP synchronization means.
105 *
106 * The gates are added to a list of requests.  A busy wait is performed to make
107 * sure that preceding requests are carried out.  Each predecessor notifies its
108 * successor about on request completion.
109 *
110 * @see _Thread_queue_Gate_add(), _Thread_queue_Gate_wait(), and
111 *   _Thread_queue_Gate_open().
112 */
113typedef struct {
114  Chain_Node Node;
115
116  Atomic_Uint go_ahead;
117} Thread_queue_Gate;
118#endif
119
120typedef struct {
121  /**
122   * @brief The lock context for the thread queue acquire and release
123   * operations.
124   */
125  ISR_lock_Context Lock_context;
126
127#if defined(RTEMS_SMP)
128  /**
129   * @brief Data to support thread queue enqueue operations.
130   */
131  struct {
132    /**
133     * @brief Gate to synchronize thread wait lock requests.
134     *
135     * @see _Thread_Wait_acquire_critical() and _Thread_Wait_tranquilize().
136     */
137    Thread_queue_Gate Gate;
138
139    /**
140     * @brief The thread queue in case the thread is blocked on a thread queue.
141     */
142    Thread_queue_Queue *queue;
143  } Wait;
144#endif
145} Thread_queue_Lock_context;
146
147#if defined(RTEMS_SMP)
148/**
149 * @brief A thread queue link from one thread to another specified by the
150 * thread queue owner and thread wait queue relationships.
151 */
152typedef struct {
153  /**
154   * @brief Node to register this link in the global thread queue links lookup
155   * tree.
156   */
157  RBTree_Node Registry_node;
158
159  /**
160   * @brief The source thread queue determined by the thread queue owner.
161   */
162  Thread_queue_Queue *source;
163
164  /**
165   * @brief The target thread queue determined by the thread wait queue of the
166   * source owner.
167   */
168  Thread_queue_Queue *target;
169
170  /**
171   * @brief Node to add this link to a thread queue path.
172   */
173  Chain_Node Path_node;
174
175  /**
176   * @brief The owner of this thread queue link.
177   */
178  Thread_Control *owner;
179
180  /**
181   * @brief The queue lock context used to acquire the thread wait lock of the
182   * owner.
183   */
184  Thread_queue_Lock_context Lock_context;
185} Thread_queue_Link;
186#endif
187
188/**
189 * @brief Thread queue context for the thread queue methods.
190 *
191 * @see _Thread_queue_Context_initialize().
192 */
193struct Thread_queue_Context {
194  /**
195   * @brief The lock context for the thread queue acquire and release
196   * operations.
197   */
198  Thread_queue_Lock_context Lock_context;
199
200  /**
201   * @brief The thread state for _Thread_queue_Enqueue().
202   */
203  States_Control thread_state;
204
205  /**
206   * @brief The enqueue callout for _Thread_queue_Enqueue().
207   *
208   * The callout is invoked after the release of the thread queue lock with
209   * thread dispatching disabled.  Afterwards the thread is blocked.  This
210   * callout must be used to install the thread watchdog for timeout handling.
211   *
212   * @see _Thread_queue_Enqueue_do_nothing_extra().
213   *   _Thread_queue_Add_timeout_ticks(), and
214   *   _Thread_queue_Add_timeout_realtime_timespec().
215   */
216  Thread_queue_Enqueue_callout enqueue_callout;
217
218  /**
219   * @brief Interval to wait.
220   *
221   * May be used by the enqueue callout to register a timeout handler.
222   */
223  union {
224    /**
225     * @brief The timeout in ticks.
226     */
227    Watchdog_Interval ticks;
228
229    /**
230     * @brief The timeout argument, e.g. pointer to struct timespec.
231     */
232    const void *arg;
233  } Timeout;
234
235#if defined(RTEMS_SMP)
236  /**
237   * @brief Representation of a thread queue path from a start thread queue to
238   * the terminal thread queue.
239   *
240   * The start thread queue is determined by the object on which a thread intends
241   * to block.  The terminal thread queue is the thread queue reachable via
242   * thread queue links whose owner is not blocked on a thread queue.  The thread
243   * queue links are determined by the thread queue owner and thread wait queue
244   * relationships.
245   */
246  struct {
247    /**
248     * @brief The chain of thread queue links defining the thread queue path.
249     */
250    Chain_Control Links;
251
252    /**
253     * @brief The start of a thread queue path.
254     */
255    Thread_queue_Link Start;
256
257    /**
258     * @brief In case of a deadlock, a link for the first thread on the path
259     * that tries to enqueue on a thread queue.
260     */
261    Thread_queue_Link Deadlock;
262  } Path;
263#endif
264
265  /**
266   * @brief Block to manage thread priority changes due to a thread queue
267   * operation.
268   */
269  struct {
270    /**
271     * @brief A priority action list.
272     */
273    Priority_Actions Actions;
274
275    /**
276     * @brief Count of threads to update the priority via
277     * _Thread_Priority_update().
278     */
279    size_t update_count;
280
281    /**
282     * @brief Threads to update the priority via _Thread_Priority_update().
283     *
284     * Currently, a maximum of two threads need an update in one rush, for
285     * example the thread of the thread queue operation and the owner of the
286     * thread queue.
287     */
288    Thread_Control *update[ 2 ];
289  } Priority;
290
291  /**
292   * @brief Invoked in case of a detected deadlock.
293   *
294   * Must be initialized for _Thread_queue_Enqueue() in case the
295   * thread queue may have an owner, e.g. for mutex objects.
296   *
297   * @see _Thread_queue_Context_set_deadlock_callout().
298   */
299  Thread_queue_Deadlock_callout deadlock_callout;
300
301#if defined(RTEMS_MULTIPROCESSING)
302  /**
303   * @brief Callout to unblock the thread in case it is actually a thread
304   * proxy.
305   *
306   * This field is only used on multiprocessing configurations.  Used by
307   * thread queue extract and unblock methods for objects with multiprocessing
308   * (MP) support.
309   *
310   * @see _Thread_queue_Context_set_MP_callout().
311   */
312  Thread_queue_MP_callout mp_callout;
313#endif
314};
315
316/**
317 * @brief Thread priority queue.
318 */
319typedef struct {
320#if defined(RTEMS_SMP)
321  /**
322   * @brief Node to enqueue this queue in the FIFO chain of the corresponding
323   * heads structure.
324   *
325   * @see Thread_queue_Heads::Heads::Fifo.
326   */
327  Chain_Node Node;
328#endif
329
330  /**
331   * @brief The actual thread priority queue.
332   */
333  Priority_Aggregation Queue;
334
335  /**
336   * @brief This priority queue is added to a scheduler node of the owner in
337   * case of priority inheritance.
338   */
339  struct Scheduler_Node *scheduler_node;
340} Thread_queue_Priority_queue;
341
342/**
343 * @brief Thread queue heads.
344 *
345 * Each thread is equipped with spare thread queue heads in case it is not
346 * enqueued on a thread queue.  The first thread enqueued on a thread queue
347 * will give its spare thread queue heads to that thread queue.  The threads
348 * arriving at the queue will add their thread queue heads to the free chain of
349 * the queue heads provided by the first thread enqueued.  Once a thread is
350 * dequeued it use the free chain to get new spare thread queue heads.
351 *
352 * Uses a leading underscore in the structure name to allow forward
353 * declarations in standard header files provided by Newlib and GCC.
354 */
355typedef struct _Thread_queue_Heads {
356  /** This union contains the data structures used to manage the blocked
357   *  set of tasks which varies based upon the discipline.
358   */
359  union {
360    /**
361     * @brief This is the FIFO discipline list.
362     *
363     * On SMP configurations this FIFO is used to enqueue the per scheduler
364     * instance priority queues of this structure.  This ensures FIFO fairness
365     * among the highest priority thread of each scheduler instance.
366     */
367    Chain_Control Fifo;
368
369#if !defined(RTEMS_SMP)
370    /**
371     * @brief This is the set of threads for priority discipline waiting.
372     */
373    Thread_queue_Priority_queue Priority;
374#endif
375  } Heads;
376
377  /**
378   * @brief A chain with free thread queue heads providing the spare thread
379   * queue heads for a thread once it is dequeued.
380   */
381  Chain_Control Free_chain;
382
383  /**
384   * @brief A chain node to add these thread queue heads to the free chain of
385   * the thread queue heads dedicated to the thread queue of an object.
386   */
387  Chain_Node Free_node;
388
389#if defined(RTEMS_SMP)
390  /**
391   * @brief One priority queue per scheduler instance.
392   */
393  Thread_queue_Priority_queue Priority[ RTEMS_ZERO_LENGTH_ARRAY ];
394#endif
395} Thread_queue_Heads;
396
397#if defined(RTEMS_SMP)
398  #define THREAD_QUEUE_HEADS_SIZE( scheduler_count ) \
399    ( sizeof( Thread_queue_Heads ) \
400      + ( scheduler_count ) * sizeof( Thread_queue_Priority_queue ) )
401#else
402  #define THREAD_QUEUE_HEADS_SIZE( scheduler_count ) \
403    sizeof( Thread_queue_Heads )
404#endif
405
406struct Thread_queue_Queue {
407  /**
408   * @brief Lock to protect this thread queue.
409   *
410   * It may be used to protect additional state of the object embedding this
411   * thread queue.
412   *
413   * Must be the first component of this structure to be able to re-use
414   * implementation parts for structures defined by Newlib <sys/lock.h>.
415   *
416   * @see _Thread_queue_Acquire(), _Thread_queue_Acquire_critical() and
417   * _Thread_queue_Release().
418   */
419#if defined(RTEMS_SMP)
420  SMP_ticket_lock_Control Lock;
421#endif
422
423  /**
424   * @brief The thread queue heads.
425   *
426   * This pointer is NULL, if and only if no threads are enqueued.  The first
427   * thread to enqueue will give its spare thread queue heads to this thread
428   * queue.
429   */
430  Thread_queue_Heads *heads;
431
432  /**
433   * @brief The thread queue owner.
434   */
435  Thread_Control *owner;
436
437  /**
438   * @brief The thread queue name.
439   */
440  const char *name;
441};
442
443/**
444 * @brief Thread queue action operation.
445 *
446 * @param[in] queue The actual thread queue.
447 * @param[in] the_thread The thread.
448 * @param[in] queue_context The thread queue context providing the thread queue
449 *   action set to perform.  Returns the thread queue action set to perform on
450 *   the thread queue owner or the empty set in case there is nothing to do.
451 */
452typedef void ( *Thread_queue_Priority_actions_operation )(
453  Thread_queue_Queue   *queue,
454  Priority_Actions     *priority_actions
455);
456
457/**
458 * @brief Thread queue enqueue operation.
459 *
460 * A potential thread to update the priority due to priority inheritance is
461 * returned via the thread queue context.  This thread is handed over to
462 * _Thread_Priority_update().
463 *
464 * @param[in] queue The actual thread queue.
465 * @param[in] the_thread The thread to enqueue on the queue.
466 */
467typedef void ( *Thread_queue_Enqueue_operation )(
468  Thread_queue_Queue   *queue,
469  Thread_Control       *the_thread,
470  Thread_queue_Context *queue_context
471);
472
473/**
474 * @brief Thread queue extract operation.
475 *
476 * @param[in] queue The actual thread queue.
477 * @param[in] the_thread The thread to extract from the thread queue.
478 */
479typedef void ( *Thread_queue_Extract_operation )(
480  Thread_queue_Queue   *queue,
481  Thread_Control       *the_thread,
482  Thread_queue_Context *queue_context
483);
484
485/**
486 * @brief Thread queue surrender operation.
487 *
488 * This operation must dequeue and return the first thread on the queue.
489 *
490 * @param[in] queue The actual thread queue.
491 * @param[in] heads The thread queue heads.  It must not be NULL.
492 * @param[in] previous_owner The previous owner of the thread queue.
493 *
494 * @return The previous first thread on the queue.
495 */
496typedef Thread_Control *( *Thread_queue_Surrender_operation )(
497  Thread_queue_Queue   *queue,
498  Thread_queue_Heads   *heads,
499  Thread_Control       *previous_owner,
500  Thread_queue_Context *queue_context
501);
502
503/**
504 * @brief Thread queue first operation.
505 *
506 * @param[in] heads The thread queue heads.
507 *
508 * @retval NULL No thread is present on the thread queue.
509 * @retval first The first thread of the thread queue according to the insert
510 * order.  This thread remains on the thread queue.
511 */
512typedef Thread_Control *( *Thread_queue_First_operation )(
513  Thread_queue_Heads *heads
514);
515
516/**
517 * @brief Thread queue operations.
518 *
519 * @see _Thread_wait_Set_operations().
520 */
521struct Thread_queue_Operations {
522  /**
523   * @brief Thread queue priority actions operation.
524   */
525  Thread_queue_Priority_actions_operation priority_actions;
526
527  /**
528   * @brief Thread queue enqueue operation.
529   *
530   * Called by object routines to enqueue the thread.
531   */
532  Thread_queue_Enqueue_operation enqueue;
533
534  /**
535   * @brief Thread queue extract operation.
536   *
537   * Called by object routines to extract a thread from a thread queue.
538   */
539  Thread_queue_Extract_operation extract;
540
541  /**
542   * @brief Thread queue surrender operation.
543   */
544  Thread_queue_Surrender_operation surrender;
545
546  /**
547   * @brief Thread queue first operation.
548   */
549  Thread_queue_First_operation first;
550};
551
552/**
553 *  This is the structure used to manage sets of tasks which are blocked
554 *  waiting to acquire a resource.
555 */
556typedef struct {
557#if defined(RTEMS_SMP)
558#if defined(RTEMS_DEBUG)
559  /**
560   * @brief The index of the owning processor of the thread queue lock.
561   *
562   * The thread queue lock may be acquired via the thread lock also.  This path
563   * is not covered by this field.  In case the lock is not owned directly via
564   * _Thread_queue_Acquire(), then the value of this field is
565   * SMP_LOCK_NO_OWNER.
566   *
567   * Must be before the queue component of this structure to be able to re-use
568   * implementation parts for structures defined by Newlib <sys/lock.h>.
569   */
570  uint32_t owner;
571#endif
572
573#if defined(RTEMS_PROFILING)
574  /**
575   * @brief SMP lock statistics in case SMP and profiling are enabled.
576   *
577   * Must be before the queue component of this structure to be able to re-use
578   * implementation parts for structures defined by Newlib <sys/lock.h>.
579   */
580  SMP_lock_Stats Lock_stats;
581#endif
582#endif
583
584  /**
585   * @brief The actual thread queue.
586   */
587  Thread_queue_Queue Queue;
588} Thread_queue_Control;
589
590/**@}*/
591
592#ifdef __cplusplus
593}
594#endif
595
596#endif
597/* end of include file */
Note: See TracBrowser for help on using the repository browser.