source: rtems/cpukit/score/src/threadqflush.c @ fce900b5

5
Last change on this file since fce900b5 was ec771f2, checked in by Sebastian Huber <sebastian.huber@…>, on 11/16/17 at 14:04:21

score: Fix priority ceiling updates

We must not clear the priority updates in _Thread_queue_Extract_locked()
since this function is used by the priority ceiling surrender operations
after the ceiling priority handover from the previous owner to the new
owner. This is especially important in SMP configurations.

Move the _Thread_queue_Context_clear_priority_updates() invocation to
the callers.

Close #3237.

  • Property mode set to 100644
File size: 3.7 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    /*
96     * We do not have enough space in the queue context to collect all priority
97     * updates, so clear it each time.  We unconditionally do the priority
98     * update for the owner later if it exists.
99     */
100    _Thread_queue_Context_clear_priority_updates( queue_context );
101
102    do_unblock = _Thread_queue_Extract_locked(
103      queue,
104      operations,
105      first,
106      queue_context
107    );
108    if ( do_unblock ) {
109      Scheduler_Node *scheduler_node;
110
111      scheduler_node = _Thread_Scheduler_get_home_node( first );
112      _Chain_Append_unprotected(
113        &unblock,
114        &scheduler_node->Wait.Priority.Node.Node.Chain
115      );
116    }
117
118    ++flushed;
119  }
120
121  node = _Chain_First( &unblock );
122  tail = _Chain_Tail( &unblock );
123
124  if ( node != tail ) {
125    Per_CPU_Control *cpu_self;
126
127    cpu_self = _Thread_queue_Dispatch_disable( queue_context );
128    _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );
129
130    do {
131      Scheduler_Node *scheduler_node;
132      Thread_Control *the_thread;
133      Chain_Node     *next;
134
135      next = _Chain_Next( node );
136      scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( node );
137      the_thread = _Scheduler_Node_get_owner( scheduler_node );
138      _Thread_Remove_timer_and_unblock( the_thread, queue );
139
140      node = next;
141    } while ( node != tail );
142
143    if ( owner != NULL ) {
144      ISR_lock_Context lock_context;
145
146      _Thread_State_acquire( owner, &lock_context );
147      _Scheduler_Update_priority( owner );
148      _Thread_State_release( owner, &lock_context );
149    }
150
151    _Thread_Dispatch_enable( cpu_self );
152  } else {
153    _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );
154  }
155
156  return flushed;
157}
Note: See TracBrowser for help on using the repository browser.