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

Last change on this file since e709aa85 was e709aa85, checked in by Sebastian Huber <sebastian.huber@…>, on Jul 13, 2015 at 11:49:35 AM

score: Move wait flag update to tq extract

This makes it possible to use _Thread_queue_Extract_locked() for barrier
operations which extract all threads on the queue in one critical
section.

  • Property mode set to 100644
File size: 13.6 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/thread.h>
26
27#ifdef __cplusplus
28extern "C" {
29#endif
30
31/**
32 *  @addtogroup ScoreThreadQueue
33 */
34/**@{*/
35
36RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_initialize(
37  Thread_queue_Queue *queue
38)
39{
40  queue->heads = NULL;
41  _ISR_lock_Initialize( &queue->Lock, "Thread Queue" );
42}
43
44RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_acquire_critical(
45  Thread_queue_Queue *queue,
46  ISR_lock_Context   *lock_context
47)
48{
49  _ISR_lock_Acquire( &queue->Lock, lock_context );
50}
51
52RTEMS_INLINE_ROUTINE void _Thread_queue_Queue_release(
53  Thread_queue_Queue *queue,
54  ISR_lock_Context   *lock_context
55)
56{
57  _ISR_lock_Release_and_ISR_enable( &queue->Lock, lock_context );
58}
59
60RTEMS_INLINE_ROUTINE void _Thread_queue_Acquire_critical(
61  Thread_queue_Control *the_thread_queue,
62  ISR_lock_Context     *lock_context
63)
64{
65  _Thread_queue_Queue_acquire_critical(
66    &the_thread_queue->Queue,
67    lock_context
68  );
69}
70
71RTEMS_INLINE_ROUTINE void _Thread_queue_Acquire(
72  Thread_queue_Control *the_thread_queue,
73  ISR_lock_Context     *lock_context
74)
75{
76  _ISR_lock_ISR_disable( lock_context );
77  _Thread_queue_Acquire_critical( the_thread_queue, lock_context );
78}
79
80RTEMS_INLINE_ROUTINE void _Thread_queue_Release(
81  Thread_queue_Control *the_thread_queue,
82  ISR_lock_Context     *lock_context
83)
84{
85  _Thread_queue_Queue_release( &the_thread_queue->Queue, lock_context );
86}
87
88/**
89 *  The following type defines the callout used when a remote task
90 *  is extracted from a local thread queue.
91 */
92typedef void ( *Thread_queue_Flush_callout )(
93                  Thread_Control *
94             );
95
96/**
97 *  @brief Gets a pointer to a thread waiting on the_thread_queue.
98 *
99 *  This function returns a pointer to a thread waiting on
100 *  the_thread_queue.  The selection of this thread is based on
101 *  the discipline of the_thread_queue.  If no threads are waiting
102 *  on the_thread_queue, then NULL is returned.
103 *
104 *  - INTERRUPT LATENCY:
105 *    + single case
106 */
107Thread_Control *_Thread_queue_Dequeue(
108  Thread_queue_Control *the_thread_queue
109);
110
111/**
112 * @brief Blocks the thread and places it on the thread queue.
113 *
114 * This enqueues the thread on the thread queue, blocks the thread, and
115 * optionally starts the thread timer in case the timeout interval is not
116 * WATCHDOG_NO_TIMEOUT.
117 *
118 * The caller must be the owner of the thread queue lock.  This function will
119 * release the thread queue lock and register it as the new thread lock.
120 * Thread dispatching is disabled before the thread queue lock is released.
121 * Thread dispatching is enabled once the sequence to block the thread is
122 * complete.  The operation to enqueue the thread on the queue is protected by
123 * the thread queue lock.  This makes it possible to use the thread queue lock
124 * to protect the state of objects embedding the thread queue and directly
125 * enter _Thread_queue_Enqueue_critical() in case the thread must block.
126 *
127 * @code
128 * #include <rtems/score/threadqimpl.h>
129 * #include <rtems/score/statesimpl.h>
130 *
131 * typedef struct {
132 *   Thread_queue_Control  Queue;
133 *   Thread_Control       *owner;
134 * } Mutex;
135 *
136 * void _Mutex_Obtain( Mutex *mutex )
137 * {
138 *   ISR_lock_Context  lock_context;
139 *   Thread_Control   *executing;
140 *
141 *   _Thread_queue_Acquire( &mutex->Queue, &lock_context );
142 *
143 *   executing = _Thread_Executing;
144 *
145 *   if ( mutex->owner == NULL ) {
146 *     mutex->owner = executing;
147 *     _Thread_queue_Release( &mutex->Queue, &lock_context );
148 *   } else {
149 *     _Thread_queue_Enqueue_critical(
150 *       &mutex->Queue.Queue,
151 *       mutex->Queue.operations,
152 *       executing,
153 *       STATES_WAITING_FOR_MUTEX,
154 *       WATCHDOG_NO_TIMEOUT,
155 *       0,
156 *       &lock_context
157 *     );
158 *   }
159 * }
160 * @endcode
161 *
162 * @param[in] queue The actual thread queue.
163 * @param[in] operations The thread queue operations.
164 * @param[in] the_thread The thread to enqueue.
165 * @param[in] state The new state of the thread.
166 * @param[in] timeout Interval to wait.  Use WATCHDOG_NO_TIMEOUT to block
167 * potentially forever.
168 * @param[in] timeout_code The return code in case a timeout occurs.
169 * @param[in] lock_context The lock context of the lock acquire.
170 */
171void _Thread_queue_Enqueue_critical(
172  Thread_queue_Queue            *queue,
173  const Thread_queue_Operations *operations,
174  Thread_Control                *the_thread,
175  States_Control                 state,
176  Watchdog_Interval              timeout,
177  uint32_t                       timeout_code,
178  ISR_lock_Context              *lock_context
179);
180
181/**
182 * @brief Acquires the thread queue lock and calls
183 * _Thread_queue_Enqueue_critical().
184 */
185RTEMS_INLINE_ROUTINE void _Thread_queue_Enqueue(
186  Thread_queue_Control *the_thread_queue,
187  Thread_Control       *the_thread,
188  States_Control        state,
189  Watchdog_Interval     timeout,
190  uint32_t              timeout_code
191)
192{
193  ISR_lock_Context lock_context;
194
195  _Thread_queue_Acquire( the_thread_queue, &lock_context );
196  _Thread_queue_Enqueue_critical(
197    &the_thread_queue->Queue,
198    the_thread_queue->operations,
199    the_thread,
200    state,
201    timeout,
202    timeout_code,
203    &lock_context
204  );
205}
206
207/**
208 * @brief Extracts the thread from the thread queue, restores the default wait
209 * operations and restores the default thread lock.
210 *
211 * The caller must be the owner of the thread queue lock.  The thread queue
212 * lock is not released.
213 *
214 * @param[in] queue The actual thread queue.
215 * @param[in] operations The thread queue operations.
216 * @param[in] the_thread The thread to extract.
217 *
218 * @return Returns the unblock indicator for _Thread_queue_Unblock_critical().
219 * True indicates, that this thread must be unblocked by the scheduler later in
220 * _Thread_queue_Unblock_critical(), and false otherwise.  In case false is
221 * returned, then the thread queue enqueue procedure was interrupted.  Thus it
222 * will unblock itself and the thread wait information is no longer accessible,
223 * since this thread may already block on another resource in an SMP
224 * configuration.
225 */
226bool _Thread_queue_Extract_locked(
227  Thread_queue_Queue            *queue,
228  const Thread_queue_Operations *operations,
229  Thread_Control                *the_thread
230);
231
232/**
233 * @brief Unblocks the thread which was on the thread queue before.
234 *
235 * The caller must be the owner of the thread queue lock.  This function will
236 * release the thread queue lock.  Thread dispatching is disabled before the
237 * thread queue lock is released and an unblock is necessary.  Thread
238 * dispatching is enabled once the sequence to unblock the thread is complete.
239 *
240 * @param[in] unblock The unblock indicator returned by
241 * _Thread_queue_Extract_locked().
242 * @param[in] queue The actual thread queue.
243 * @param[in] the_thread The thread to extract.
244 * @param[in] lock_context The lock context of the lock acquire.
245 */
246void _Thread_queue_Unblock_critical(
247  bool                unblock,
248  Thread_queue_Queue *queue,
249  Thread_Control     *the_thread,
250  ISR_lock_Context   *lock_context
251);
252
253/**
254 * @brief Extracts the thread from the thread queue and unblocks it.
255 *
256 * The caller must be the owner of the thread queue lock.  This function will
257 * release the thread queue lock and restore the default thread lock.  Thread
258 * dispatching is disabled before the thread queue lock is released and an
259 * unblock is necessary.  Thread dispatching is enabled once the sequence to
260 * unblock the thread is complete.  This makes it possible to use the thread
261 * queue lock to protect the state of objects embedding the thread queue and
262 * directly enter _Thread_queue_Extract_critical() to finalize an operation in
263 * case a waiting thread exists.
264 *
265 * @code
266 * #include <rtems/score/threadqimpl.h>
267 *
268 * typedef struct {
269 *   Thread_queue_Control  Queue;
270 *   Thread_Control       *owner;
271 * } Mutex;
272 *
273 * void _Mutex_Release( Mutex *mutex )
274 * {
275 *   ISR_lock_Context  lock_context;
276 *   Thread_Control   *first;
277 *
278 *   _Thread_queue_Acquire( &mutex->Queue, &lock_context );
279 *
280 *   first = _Thread_queue_First_locked( &mutex->Queue );
281 *   mutex->owner = first;
282 *
283 *   if ( first != NULL ) {
284 *     _Thread_queue_Extract_critical(
285 *       &mutex->Queue.Queue,
286 *       mutex->Queue.operations,
287 *       first,
288 *       &lock_context
289 *   );
290 * }
291 * @endcode
292 *
293 * @param[in] queue The actual thread queue.
294 * @param[in] operations The thread queue operations.
295 * @param[in] the_thread The thread to extract.
296 * @param[in] lock_context The lock context of the lock acquire.
297 */
298void _Thread_queue_Extract_critical(
299  Thread_queue_Queue            *queue,
300  const Thread_queue_Operations *operations,
301  Thread_Control                *the_thread,
302  ISR_lock_Context              *lock_context
303);
304
305/**
306 *  @brief Extracts thread from thread queue.
307 *
308 *  This routine removes @a the_thread its thread queue
309 *  and cancels any timeouts associated with this blocking.
310 *
311 *  @param[in] the_thread is the pointer to a thread control block that
312 *      is to be removed
313 */
314void _Thread_queue_Extract( Thread_Control *the_thread );
315
316/**
317 *  @brief Extracts the_thread from the_thread_queue.
318 *
319 *  This routine extracts the_thread from the_thread_queue
320 *  and ensures that if there is a proxy for this task on
321 *  another node, it is also dealt with.
322 */
323void _Thread_queue_Extract_with_proxy(
324  Thread_Control       *the_thread
325);
326
327/**
328 * @brief Returns the first thread on the thread queue if it exists, otherwise
329 * @c NULL.
330 *
331 * The caller must be the owner of the thread queue lock.  The thread queue
332 * lock is not released.
333 *
334 * @param[in] the_thread_queue The thread queue.
335 *
336 * @retval NULL No thread is present on the thread queue.
337 * @retval first The first thread on the thread queue according to the enqueue
338 * order.
339 */
340RTEMS_INLINE_ROUTINE Thread_Control *_Thread_queue_First_locked(
341  Thread_queue_Control *the_thread_queue
342)
343{
344  Thread_queue_Heads *heads = the_thread_queue->Queue.heads;
345
346  if ( heads != NULL ) {
347    return ( *the_thread_queue->operations->first )( heads );
348  } else {
349    return NULL;
350  }
351}
352
353/**
354 * @brief Returns the first thread on the thread queue if it exists, otherwise
355 * @c NULL.
356 *
357 * @param[in] the_thread_queue The thread queue.
358 *
359 * @retval NULL No thread is present on the thread queue.
360 * @retval first The first thread on the thread queue according to the enqueue
361 * order.
362 */
363Thread_Control *_Thread_queue_First(
364  Thread_queue_Control *the_thread_queue
365);
366
367/**
368 *  @brief Unblocks all threads blocked on the_thread_queue.
369 *
370 *  This routine unblocks all threads blocked on the_thread_queue
371 *  and cancels any associated timeouts.
372 *
373 *  @param[in] the_thread_queue is the pointer to a threadq header
374 *  @param[in] remote_extract_callout points to a method to invoke to
375 *             invoke when a remote thread is unblocked
376 *  @param[in] status is the status which will be returned to
377 *             all unblocked threads
378 */
379void _Thread_queue_Flush(
380  Thread_queue_Control       *the_thread_queue,
381  Thread_queue_Flush_callout  remote_extract_callout,
382  uint32_t                    status
383);
384
385/**
386 *  @brief Initialize the_thread_queue.
387 *
388 *  This routine initializes the_thread_queue based on the
389 *  discipline indicated in attribute_set.  The state set on
390 *  threads which block on the_thread_queue is state.
391 *
392 *  @param[in] the_thread_queue is the pointer to a threadq header
393 *  @param[in] the_discipline is the queueing discipline
394 */
395void _Thread_queue_Initialize(
396  Thread_queue_Control     *the_thread_queue,
397  Thread_queue_Disciplines  the_discipline
398);
399
400#if defined(RTEMS_SMP)
401  #define THREAD_QUEUE_FIFO_INITIALIZER( designator, name ) { \
402      .Queue = { \
403        .heads = NULL, \
404        .Lock = ISR_LOCK_INITIALIZER( name ), \
405      }, \
406      .operations = &_Thread_queue_Operations_FIFO \
407    }
408
409  #define THREAD_QUEUE_PRIORITY_INITIALIZER( designator, name ) { \
410      .Queue = { \
411        .heads = NULL, \
412        .Lock = ISR_LOCK_INITIALIZER( name ), \
413      }, \
414      .operations = &_Thread_queue_Operations_priority \
415    }
416#else
417  #define THREAD_QUEUE_FIFO_INITIALIZER( designator, name ) { \
418      .Queue = { .heads = NULL }, \
419      .operations = &_Thread_queue_Operations_FIFO \
420    }
421
422  #define THREAD_QUEUE_PRIORITY_INITIALIZER( designator, name ) { \
423      .Queue = { .heads = NULL }, \
424      .operations = &_Thread_queue_Operations_priority \
425    }
426#endif
427
428RTEMS_INLINE_ROUTINE void _Thread_queue_Destroy(
429  Thread_queue_Control *the_thread_queue
430)
431{
432  _ISR_lock_Destroy( &the_thread_queue->Queue.Lock );
433}
434
435/**
436 * @brief Compare two thread's priority for RBTree Insertion.
437 *
438 * @param[in] left points to the left thread's RBnode
439 * @param[in] right points to the right thread's RBnode
440 *
441 * @retval 1 The @a left node is more important than @a right node.
442 * @retval 0 The @a left node is of equal importance with @a right node.
443 * @retval 1 The @a left node is less important than @a right node.
444 */
445RBTree_Compare_result _Thread_queue_Compare_priority(
446  const RBTree_Node *left,
447  const RBTree_Node *right
448);
449
450extern const Thread_queue_Operations _Thread_queue_Operations_default;
451
452extern const Thread_queue_Operations _Thread_queue_Operations_FIFO;
453
454extern const Thread_queue_Operations _Thread_queue_Operations_priority;
455
456/**@}*/
457
458#ifdef __cplusplus
459}
460#endif
461
462#endif
463/* end of include file */
Note: See TracBrowser for help on using the repository browser.