source: rtems/cpukit/score/src/threadqflush.c @ 9c30c31e

5
Last change on this file since 9c30c31e was 9c30c31e, checked in by Sebastian Huber <sebastian.huber@…>, on 11/16/17 at 13:38:07

score: Fix _Thread_queue_Flush_critical()

The thread queue extract operations performed by the
_Thread_queue_Flush_critical() may result in a priority change of the
thread queue owner. Carry out the scheduler priority update operation.
This is especially important in SMP configurations.

Close #3236.

  • Property mode set to 100644
File size: 3.4 KB
Line 
1/**
2 * @file
3 *
4 * @brief Thread Queue Flush
5 * @ingroup ScoreThreadQ
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2008.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/score/threadimpl.h>
22#include <rtems/score/schedulerimpl.h>
23#include <rtems/score/status.h>
24
25Thread_Control *_Thread_queue_Flush_default_filter(
26  Thread_Control       *the_thread,
27  Thread_queue_Queue   *queue,
28  Thread_queue_Context *queue_context
29)
30{
31  (void) queue;
32  (void) queue_context;
33  return the_thread;
34}
35
36Thread_Control *_Thread_queue_Flush_status_object_was_deleted(
37  Thread_Control       *the_thread,
38  Thread_queue_Queue   *queue,
39  Thread_queue_Context *queue_context
40)
41{
42  the_thread->Wait.return_code = STATUS_OBJECT_WAS_DELETED;
43
44  (void) queue;
45  (void) queue_context;
46  return the_thread;
47}
48
49Thread_Control *_Thread_queue_Flush_status_unavailable(
50  Thread_Control       *the_thread,
51  Thread_queue_Queue   *queue,
52  Thread_queue_Context *queue_context
53)
54{
55  the_thread->Wait.return_code = STATUS_UNAVAILABLE;
56
57  (void) queue;
58  (void) queue_context;
59  return the_thread;
60}
61
62size_t _Thread_queue_Flush_critical(
63  Thread_queue_Queue            *queue,
64  const Thread_queue_Operations *operations,
65  Thread_queue_Flush_filter      filter,
66  Thread_queue_Context          *queue_context
67)
68{
69  size_t          flushed;
70  Chain_Control   unblock;
71  Thread_Control *owner;
72  Chain_Node     *node;
73  Chain_Node     *tail;
74
75  flushed = 0;
76  _Chain_Initialize_empty( &unblock );
77  owner = queue->owner;
78
79  while ( true ) {
80    Thread_queue_Heads *heads;
81    Thread_Control     *first;
82    bool                do_unblock;
83
84    heads = queue->heads;
85    if ( heads == NULL ) {
86      break;
87    }
88
89    first = ( *operations->first )( heads );
90    first = ( *filter )( first, queue, queue_context );
91    if ( first == NULL ) {
92      break;
93    }
94
95    do_unblock = _Thread_queue_Extract_locked(
96      queue,
97      operations,
98      first,
99      queue_context
100    );
101    if ( do_unblock ) {
102      Scheduler_Node *scheduler_node;
103
104      scheduler_node = _Thread_Scheduler_get_home_node( first );
105      _Chain_Append_unprotected(
106        &unblock,
107        &scheduler_node->Wait.Priority.Node.Node.Chain
108      );
109    }
110
111    ++flushed;
112  }
113
114  node = _Chain_First( &unblock );
115  tail = _Chain_Tail( &unblock );
116
117  if ( node != tail ) {
118    Per_CPU_Control *cpu_self;
119
120    cpu_self = _Thread_queue_Dispatch_disable( queue_context );
121    _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );
122
123    do {
124      Scheduler_Node *scheduler_node;
125      Thread_Control *the_thread;
126      Chain_Node     *next;
127
128      next = _Chain_Next( node );
129      scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( node );
130      the_thread = _Scheduler_Node_get_owner( scheduler_node );
131      _Thread_Remove_timer_and_unblock( the_thread, queue );
132
133      node = next;
134    } while ( node != tail );
135
136    if ( owner != NULL ) {
137      ISR_lock_Context lock_context;
138
139      _Thread_State_acquire( owner, &lock_context );
140      _Scheduler_Update_priority( owner );
141      _Thread_State_release( owner, &lock_context );
142    }
143
144    _Thread_Dispatch_enable( cpu_self );
145  } else {
146    _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );
147  }
148
149  return flushed;
150}
Note: See TracBrowser for help on using the repository browser.