source: rtems/cpukit/score/include/rtems/score/threadqimpl.h @ 6359b68

4.115
Last change on this file since 6359b68 was 91e7b0c, checked in by Sebastian Huber <sebastian.huber@…>, on 03/27/14 at 08:04:47

score: PR2172: _Thread_queue_Extract()

Add _Thread_queue_Extract_with_return_code(). On SMP this sequence in
_Thread_queue_Process_timeout() was broken:

[...]

/*

  • After we enable interrupts here, a lot may happen in the
  • meantime, e.g. nested interrupts may release the resource that
  • times out here. So we enter _Thread_queue_Extract()
  • speculatively. Inside this function we check the actual status
  • under ISR disable protection. This ensures that exactly one
  • executing context performs the extract operation (other parties
  • may call _Thread_queue_Dequeue()). If this context won, then
  • we have a timeout. *
  • We can use the_thread_queue pointer here even if
  • the_thread->Wait.queue is already set to NULL since the extract
  • operation will only use the thread queue discipline to select
  • the right extract operation. The timeout status is set during
  • thread queue initialization. */

we_did_it = _Thread_queue_Extract( the_thread_queue, the_thread );
if ( we_did_it ) {

the_thread->Wait.return_code = the_thread_queue->timeout_status;

}

[...]

In case _Thread_queue_Extract() successfully extracted a thread, then
this thread may start execution on a remote processor immediately and
read the the_thread->Wait.return_code before we update it here with the
timeout status. Thus it observes a successful operation even if it
timed out.

  • Property mode set to 100644
File size: 12.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-2009.
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/thread.h>
24
25#ifdef __cplusplus
26extern "C" {
27#endif
28
29/**
30 *  @addtogroup ScoreThreadQueue
31 */
32/**@{*/
33
34/**
35 *  Constant for indefinite wait.
36 */
37#define THREAD_QUEUE_WAIT_FOREVER  WATCHDOG_NO_TIMEOUT
38
39/**
40 *  This is one of the constants used to manage the priority queues.
41 *  @ref TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS for more details.
42 */
43#define TASK_QUEUE_DATA_PRIORITIES_PER_HEADER      64
44
45/**
46 *  This is one of the constants used to manage the priority queues.
47 *  @ref TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS for more details.
48 */
49#define TASK_QUEUE_DATA_REVERSE_SEARCH_MASK        0x20
50
51/**
52 *  The following type defines the callout used when a remote task
53 *  is extracted from a local thread queue.
54 */
55typedef void ( *Thread_queue_Flush_callout )(
56                  Thread_Control *
57             );
58
59/**
60 *  The following type defines the callout used for timeout processing
61 *  methods.
62 */
63typedef void ( *Thread_queue_Timeout_callout )(
64                 Objects_Id,
65                 void *
66             );
67
68/**
69 *  @brief Gets a pointer to a thread waiting on the_thread_queue.
70 *
71 *  This function returns a pointer to a thread waiting on
72 *  the_thread_queue.  The selection of this thread is based on
73 *  the discipline of the_thread_queue.  If no threads are waiting
74 *  on the_thread_queue, then NULL is returned.
75 */
76Thread_Control *_Thread_queue_Dequeue(
77  Thread_queue_Control *the_thread_queue
78);
79
80/**
81 *  @brief Enqueues the currently executing thread on the_thread_queue.
82 *
83 *  This routine enqueues the currently executing thread on
84 *  the_thread_queue with an optional timeout.
85 */
86#define _Thread_queue_Enqueue( _the_thread_queue, _the_thread, _timeout ) \
87  _Thread_queue_Enqueue_with_handler( \
88    _the_thread_queue, \
89    _the_thread, \
90    _timeout, \
91    _Thread_queue_Timeout )
92
93/**
94 *  @brief Blocks a thread and places it on a thread.
95 *
96 *  This routine blocks a thread, places it on a thread, and optionally
97 *  starts a timeout timer.
98 *
99 *  @param[in] the_thread_queue pointer to threadq
100 *  @param[in] the_thread the thread to enqueue
101 *  @param[in] timeout interval to wait
102 *
103 *  - INTERRUPT LATENCY:
104 *    + single case
105 */
106void _Thread_queue_Enqueue_with_handler(
107  Thread_queue_Control         *the_thread_queue,
108  Thread_Control               *the_thread,
109  Watchdog_Interval             timeout,
110  Thread_queue_Timeout_callout  handler
111);
112
113/**
114 *  @brief Invoked when a thread changes priority and is blocked.
115 *
116 *  This routine is invoked when a thread changes priority and is
117 *  blocked on a thread queue.  If the queue is priority ordered,
118 *  the_thread is removed from the_thread_queue and reinserted using
119 *  its new priority.  This method has no impact on the state of the_thread
120 *  or of any timeouts associated with this blocking.
121 *
122 *  @param[in] the_thread_queue pointer to a threadq header
123 *  @param[in] the_thread pointer to a thread control block
124 */
125void _Thread_queue_Requeue(
126  Thread_queue_Control *the_thread_queue,
127  Thread_Control       *the_thread
128);
129
130/**
131 *  @brief Extracts thread from thread queue.
132 *
133 *  This routine removes @a the_thread from @a the_thread_queue
134 *  and cancels any timeouts associated with this blocking.
135 *
136 *  @param[in] the_thread_queue is the pointer to the ThreadQ header
137 *  @param[in] the_thread is the pointer to a thread control block that is to be removed
138 */
139void _Thread_queue_Extract(
140  Thread_queue_Control *the_thread_queue,
141  Thread_Control       *the_thread
142);
143
144void _Thread_queue_Extract_with_return_code(
145  Thread_queue_Control *the_thread_queue,
146  Thread_Control       *the_thread,
147  uint32_t              return_code
148);
149
150/**
151 *  @brief Extracts the_thread from the_thread_queue.
152 *
153 *  This routine extracts the_thread from the_thread_queue
154 *  and ensures that if there is a proxy for this task on
155 *  another node, it is also dealt with.
156 */
157void _Thread_queue_Extract_with_proxy(
158  Thread_Control       *the_thread
159);
160
161/**
162 *  @brief Gets a pointer to the "first" thread on the_thread_queue.
163 *
164 *  This function returns a pointer to the "first" thread
165 *  on the_thread_queue.  The "first" thread is selected
166 *  based on the discipline of the_thread_queue.
167 *
168 *  @param[in] the_thread_queue pointer to thread queue
169 *
170 *  @retval first thread or NULL
171 */
172Thread_Control *_Thread_queue_First(
173  Thread_queue_Control *the_thread_queue
174);
175
176/**
177 *  @brief Unblocks all threads blocked on the_thread_queue.
178 *
179 *  This routine unblocks all threads blocked on the_thread_queue
180 *  and cancels any associated timeouts.
181 *
182 *  @param[in] the_thread_queue is the pointer to a threadq header
183 *  @param[in] remote_extract_callout points to a method to invoke to
184 *             invoke when a remote thread is unblocked
185 *  @param[in] status is the status which will be returned to
186 *             all unblocked threads
187 */
188void _Thread_queue_Flush(
189  Thread_queue_Control       *the_thread_queue,
190  Thread_queue_Flush_callout  remote_extract_callout,
191  uint32_t                    status
192);
193
194/**
195 *  @brief Initialize the_thread_queue.
196 *
197 *  This routine initializes the_thread_queue based on the
198 *  discipline indicated in attribute_set.  The state set on
199 *  threads which block on the_thread_queue is state.
200 *
201 *  @param[in] the_thread_queue is the pointer to a threadq header
202 *  @param[in] the_discipline is the queueing discipline
203 *  @param[in] state is the state of waiting threads
204 *  @param[in] timeout_status is the return on a timeout
205 */
206void _Thread_queue_Initialize(
207  Thread_queue_Control         *the_thread_queue,
208  Thread_queue_Disciplines      the_discipline,
209  States_Control                state,
210  uint32_t                      timeout_status
211);
212
213/**
214 *  @brief Removes a thread from the specified PRIORITY based
215 *  threadq, unblocks it, and cancels its timeout timer.
216 *
217 *  This routine removes a thread from the specified PRIORITY based
218 *  threadq, unblocks it, and cancels its timeout timer.
219 *
220 *  - INTERRUPT LATENCY:
221 *    + single case
222 *
223 * @param[in] the_thread_queue is a pointer to a thread queue
224 *
225 * @retval thread dequeued
226 * @retval NULL if no thread are waiting on the_thread_queue
227 */
228Thread_Control *_Thread_queue_Dequeue_priority(
229  Thread_queue_Control *the_thread_queue
230);
231
232/**
233 *  @brief Enqueues the currently executing thread on the_thread_queue.
234 *
235 *  This routine enqueues the currently executing thread on
236 *  the_thread_queue with an optional timeout using the
237 *  priority discipline.
238 *
239 *  @param[in] the_thread_queue is the pointer to threadq
240 *  @param[in] the_thread is the thread to insert
241 *  @param[in] level_p is a pointer to an interrupt level to be returned
242 *
243 *  @retval This methods returns an indication of the blocking state as
244 *          well as filling in *@ level_p with the previous interrupt level.
245 *
246 *  - INTERRUPT LATENCY:
247 *    + forward less than
248 *    + forward equal
249 */
250Thread_blocking_operation_States _Thread_queue_Enqueue_priority (
251  Thread_queue_Control *the_thread_queue,
252  Thread_Control       *the_thread,
253  ISR_Level            *level_p
254);
255
256/**
257 *  @brief Removes the_thread and cancels related timeouts.
258 *
259 *  This routine removes the_thread from the_thread_queue
260 *  and cancels any timeouts associated with this blocking.
261 *  @param[in] the_thread_queue pointer to a threadq header
262 *  @param[in] the_thread pointer to a thread control block
263 *  @param[in] requeuing true if requeuing and should not alter
264 *         timeout or state
265 *  - INTERRUPT LATENCY:
266 *    + EXTRACT_PRIORITY
267 *
268 *  @retval true The extract operation was performed by the executing context.
269 *  @retval false Otherwise.
270 */
271void _Thread_queue_Extract_priority_helper(
272  Thread_Control       *the_thread,
273  uint32_t              return_code,
274  bool                  requeuing
275);
276
277/**
278 *  @brief Wraps the underlying call and hides the requeuing argument.
279 *
280 * This macro wraps the underlying call and hides the requeuing argument.
281 */
282
283#define _Thread_queue_Extract_priority( _the_thread, _return_code ) \
284  _Thread_queue_Extract_priority_helper( _the_thread, _return_code, false )
285/**
286 *  @brief Get highest priority thread on the_thread_queue.
287 *
288 *  This function returns a pointer to the "first" thread
289 *  on @a the_thread_queue.  The "first" thread is the highest
290 *  priority thread waiting on @a the_thread_queue.
291 *
292 *  @param[in] the_thread_queue is the pointer to the thread queue
293 *  @retval first thread or NULL
294 */
295Thread_Control *_Thread_queue_First_priority(
296  Thread_queue_Control *the_thread_queue
297);
298
299/**
300 *  @brief Gets a pointer to the thread which has been waiting the longest.
301 *
302 *  This function returns a pointer to the thread which has
303 *  been waiting the longest on  the_thread_queue.  If no
304 *  threads are waiting on the_thread_queue, then NULL is returned.
305 *
306 *  @param[in] the_thread_queue is the pointer to threadq
307 *
308 *  @retval thread dequeued or NULL
309 *
310 *  - INTERRUPT LATENCY:
311 *    + check sync
312 *    + FIFO
313 */
314Thread_Control *_Thread_queue_Dequeue_fifo(
315  Thread_queue_Control *the_thread_queue
316);
317
318/**
319 *  @brief Enqueues the currently executing thread on the_thread_queue.
320 *
321 *  This routine enqueues the currently executing thread on
322 *  the_thread_queue with an optional timeout using the
323 *  FIFO discipline.
324 *
325 *    @param[in] the_thread_queue pointer to threadq
326 *    @param[in] the_thread pointer to the thread to block
327 *    @param[in] level_p interrupt level in case the operation blocks actually
328 *
329 *  - INTERRUPT LATENCY:
330 *    + single case
331 */
332Thread_blocking_operation_States _Thread_queue_Enqueue_fifo (
333  Thread_queue_Control *the_thread_queue,
334  Thread_Control       *the_thread,
335  ISR_Level            *level_p
336);
337
338/**
339 *  @brief Removes the_thread from the_thread_queue and cancels any timeouts.
340 *
341 *  This routine removes the_thread from the_thread_queue
342 *  and cancels any timeouts associated with this blocking.
343 */
344void _Thread_queue_Extract_fifo(
345  Thread_Control       *the_thread,
346  uint32_t              return_code
347);
348
349/**
350 *  @brief Gets a pointer to the "first" thread on the_thread_queue.
351 *
352 *  This function returns a pointer to the "first" thread
353 *  on the_thread_queue.  The first thread is the thread
354 *  which has been waiting longest on the_thread_queue.
355 *
356 *  @param[in] the_thread_queue is the pointer to threadq
357 *
358 *  @retval first thread or NULL
359 */
360Thread_Control *_Thread_queue_First_fifo(
361  Thread_queue_Control *the_thread_queue
362);
363
364/**
365 *  @brief Thread queue timeout.
366 *
367 *  This routine is invoked when a task's request has not
368 *  been satisfied after the timeout interval specified to
369 *  enqueue.  The task represented by ID will be unblocked and
370 *  its status code will be set in it's control block to indicate
371 *  that a timeout has occurred.
372 *
373 *  @param[in] id thread id
374 */
375void _Thread_queue_Timeout (
376  Objects_Id  id,
377  void       *ignored
378);
379
380/**
381 *  @brief Process thread queue timeout.
382 *
383 * This is a shared helper routine which makes it easier to have multiple
384 * object class specific timeout routines.
385 *
386 * @param[in] the_thread is the thread to extract
387 *
388 * @note This method assumes thread dispatching is disabled
389 *       and is expected to be called via the processing of
390 *       a clock tick.
391 */
392void _Thread_queue_Process_timeout(
393  Thread_Control *the_thread
394);
395
396/**
397 * This function returns the index of the priority chain on which
398 * a thread of the_priority should be placed.
399 */
400
401RTEMS_INLINE_ROUTINE uint32_t   _Thread_queue_Header_number (
402  Priority_Control the_priority
403)
404{
405  return (the_priority / TASK_QUEUE_DATA_PRIORITIES_PER_HEADER);
406}
407
408/**
409 * This function returns true if the_priority indicates that the
410 * enqueue search should start at the front of this priority
411 * group chain, and false if the search should start at the rear.
412 */
413
414RTEMS_INLINE_ROUTINE bool _Thread_queue_Is_reverse_search (
415  Priority_Control the_priority
416)
417{
418  return ( the_priority & TASK_QUEUE_DATA_REVERSE_SEARCH_MASK );
419}
420
421/**
422 * This routine is invoked to indicate that the specified thread queue is
423 * entering a critical section.
424 */
425
426RTEMS_INLINE_ROUTINE void _Thread_queue_Enter_critical_section (
427  Thread_queue_Control *the_thread_queue
428)
429{
430  the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
431}
432
433/**@}*/
434
435#ifdef __cplusplus
436}
437#endif
438
439#endif
440/* end of include file */
Note: See TracBrowser for help on using the repository browser.