source: rtems/cpukit/score/include/rtems/score/threadq.h @ b5f1b24

5
Last change on this file since b5f1b24 was f6142c19, checked in by Sebastian Huber <sebastian.huber@…>, on 09/09/16 at 09:00:06

score: Scheduler node awareness for thread queues

Maintain the priority of a thread for each scheduler instance via the
thread queue enqueue, extract, priority actions and surrender
operations. This replaces the primitive priority boosting.

Update #2556.

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