source: rtems/cpukit/score/src/schedulerprioritysmp.c @ f39f667a

4.115
Last change on this file since f39f667a was f39f667a, checked in by Sebastian Huber <sebastian.huber@…>, on May 14, 2014 at 11:50:48 AM

score: Simplify _Thread_Change_priority()

The function to change a thread priority was too complex. Simplify it
with a new scheduler operation. This increases the average case
performance due to the simplified logic. The interrupt disabled
critical section is a bit prolonged since now the extract, update and
enqueue steps are executed atomically. This should however not impact
the worst-case interrupt latency since at least for the Deterministic
Priority Scheduler this sequence can be carried out with a wee bit of
instructions and no loops.

Add _Scheduler_Change_priority() to replace the sequence of

  • _Thread_Set_transient(),
  • _Scheduler_Extract(),
  • _Scheduler_Enqueue(), and
  • _Scheduler_Enqueue_first().

Delete STATES_TRANSIENT, _States_Is_transient() and
_Thread_Set_transient() since this state is now superfluous.

With this change it is possible to get rid of the
SCHEDULER_SMP_NODE_IN_THE_AIR state. This considerably simplifies the
implementation of the new SMP locking protocols.

  • Property mode set to 100644
File size: 8.3 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreSchedulerPrioritySMP
5 *
6 * @brief Deterministic Priority SMP Scheduler Implementation
7 */
8
9/*
10 * Copyright (c) 2013-2014 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Dornierstr. 4
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.org/license/LICENSE.
21 */
22
23#if HAVE_CONFIG_H
24  #include "config.h"
25#endif
26
27#include <rtems/score/schedulerprioritysmp.h>
28#include <rtems/score/schedulerpriorityimpl.h>
29#include <rtems/score/schedulersmpimpl.h>
30
31static Scheduler_priority_SMP_Context *
32_Scheduler_priority_SMP_Get_context( const Scheduler_Control *scheduler )
33{
34  return (Scheduler_priority_SMP_Context *) _Scheduler_Get_context( scheduler );
35}
36
37static Scheduler_priority_SMP_Context *
38_Scheduler_priority_SMP_Get_self( Scheduler_Context *context )
39{
40  return (Scheduler_priority_SMP_Context *) context;
41}
42
43static Scheduler_priority_SMP_Node *_Scheduler_priority_SMP_Node_get(
44  Thread_Control *thread
45)
46{
47  return (Scheduler_priority_SMP_Node *) _Scheduler_Node_get( thread );
48}
49
50static Scheduler_priority_SMP_Node *_Scheduler_priority_SMP_Node_downcast(
51  Scheduler_Node *node
52)
53{
54  return (Scheduler_priority_SMP_Node *) node;
55}
56
57void _Scheduler_priority_SMP_Initialize( const Scheduler_Control *scheduler )
58{
59  Scheduler_priority_SMP_Context *self =
60    _Scheduler_priority_SMP_Get_context( scheduler );
61
62  _Scheduler_SMP_Initialize( &self->Base );
63  _Priority_bit_map_Initialize( &self->Bit_map );
64  _Scheduler_priority_Ready_queue_initialize( &self->Ready[ 0 ] );
65}
66
67bool _Scheduler_priority_SMP_Allocate(
68  const Scheduler_Control *scheduler,
69  Thread_Control *thread
70)
71{
72  Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread );
73
74  _Scheduler_SMP_Node_initialize( node );
75
76  return true;
77}
78
79static void _Scheduler_priority_SMP_Do_update(
80  Scheduler_Context *context,
81  Scheduler_Node *base_node,
82  Priority_Control new_priority
83)
84{
85  Scheduler_priority_SMP_Context *self =
86    _Scheduler_priority_SMP_Get_self( context );
87  Scheduler_priority_SMP_Node *node =
88    _Scheduler_priority_SMP_Node_downcast( base_node );
89
90  _Scheduler_priority_Ready_queue_update(
91    &node->Ready_queue,
92    new_priority,
93    &self->Bit_map,
94    &self->Ready[ 0 ]
95  );
96}
97
98void _Scheduler_priority_SMP_Update(
99  const Scheduler_Control *scheduler,
100  Thread_Control *thread
101)
102{
103  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
104  Scheduler_Node *node = _Scheduler_Node_get( thread );
105
106  _Scheduler_priority_SMP_Do_update( context, node, thread->current_priority );
107}
108
109static Thread_Control *_Scheduler_priority_SMP_Get_highest_ready(
110  Scheduler_Context *context
111)
112{
113  Scheduler_priority_SMP_Context *self =
114    _Scheduler_priority_SMP_Get_self( context );
115
116  return _Scheduler_priority_Ready_queue_first(
117    &self->Bit_map,
118    &self->Ready[ 0 ]
119  );
120}
121
122static void _Scheduler_priority_SMP_Move_from_scheduled_to_ready(
123  Scheduler_Context *context,
124  Thread_Control *scheduled_to_ready
125)
126{
127  Scheduler_priority_SMP_Context *self =
128    _Scheduler_priority_SMP_Get_self( context );
129  Scheduler_priority_SMP_Node *node =
130    _Scheduler_priority_SMP_Node_get( scheduled_to_ready );
131
132  _Chain_Extract_unprotected( &scheduled_to_ready->Object.Node );
133  _Scheduler_priority_Ready_queue_enqueue_first(
134    scheduled_to_ready,
135    &node->Ready_queue,
136    &self->Bit_map
137  );
138}
139
140static void _Scheduler_priority_SMP_Move_from_ready_to_scheduled(
141  Scheduler_Context *context,
142  Thread_Control *ready_to_scheduled
143)
144{
145  Scheduler_priority_SMP_Context *self =
146    _Scheduler_priority_SMP_Get_self( context );
147  Scheduler_priority_SMP_Node *node =
148    _Scheduler_priority_SMP_Node_get( ready_to_scheduled );
149
150  _Scheduler_priority_Ready_queue_extract(
151    ready_to_scheduled,
152    &node->Ready_queue,
153    &self->Bit_map
154  );
155  _Scheduler_simple_Insert_priority_fifo(
156    &self->Base.Scheduled,
157    ready_to_scheduled
158  );
159}
160
161static void _Scheduler_priority_SMP_Insert_ready_lifo(
162  Scheduler_Context *context,
163  Thread_Control *thread
164)
165{
166  Scheduler_priority_SMP_Context *self =
167    _Scheduler_priority_SMP_Get_self( context );
168  Scheduler_priority_SMP_Node *node =
169    _Scheduler_priority_SMP_Node_get( thread );
170
171  _Scheduler_priority_Ready_queue_enqueue(
172    thread,
173    &node->Ready_queue,
174    &self->Bit_map
175  );
176}
177
178static void _Scheduler_priority_SMP_Insert_ready_fifo(
179  Scheduler_Context *context,
180  Thread_Control *thread
181)
182{
183  Scheduler_priority_SMP_Context *self =
184    _Scheduler_priority_SMP_Get_self( context );
185  Scheduler_priority_SMP_Node *node =
186    _Scheduler_priority_SMP_Node_get( thread );
187
188  _Scheduler_priority_Ready_queue_enqueue_first(
189    thread,
190    &node->Ready_queue,
191    &self->Bit_map
192  );
193}
194
195static void _Scheduler_priority_SMP_Extract_from_ready(
196  Scheduler_Context *context,
197  Thread_Control *thread
198)
199{
200  Scheduler_priority_SMP_Context *self =
201    _Scheduler_priority_SMP_Get_self( context );
202  Scheduler_priority_SMP_Node *node =
203    _Scheduler_priority_SMP_Node_get( thread );
204
205  _Scheduler_priority_Ready_queue_extract(
206    thread,
207    &node->Ready_queue,
208    &self->Bit_map
209  );
210}
211
212void _Scheduler_priority_SMP_Block(
213  const Scheduler_Control *scheduler,
214  Thread_Control *thread
215)
216{
217  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
218
219  _Scheduler_SMP_Block(
220    context,
221    thread,
222    _Scheduler_priority_SMP_Extract_from_ready,
223    _Scheduler_priority_SMP_Get_highest_ready,
224    _Scheduler_priority_SMP_Move_from_ready_to_scheduled
225  );
226}
227
228static void _Scheduler_priority_SMP_Enqueue_ordered(
229  Scheduler_Context *context,
230  Thread_Control *thread,
231  bool has_processor_allocated,
232  Chain_Node_order order,
233  Scheduler_SMP_Insert insert_ready,
234  Scheduler_SMP_Insert insert_scheduled
235)
236{
237  _Scheduler_SMP_Enqueue_ordered(
238    context,
239    thread,
240    has_processor_allocated,
241    order,
242    _Scheduler_priority_SMP_Get_highest_ready,
243    insert_ready,
244    insert_scheduled,
245    _Scheduler_priority_SMP_Move_from_ready_to_scheduled,
246    _Scheduler_priority_SMP_Move_from_scheduled_to_ready
247  );
248}
249
250static void _Scheduler_priority_SMP_Enqueue_lifo(
251  Scheduler_Context *context,
252  Thread_Control *thread,
253  bool has_processor_allocated
254)
255{
256  _Scheduler_priority_SMP_Enqueue_ordered(
257    context,
258    thread,
259    has_processor_allocated,
260    _Scheduler_simple_Insert_priority_lifo_order,
261    _Scheduler_priority_SMP_Insert_ready_lifo,
262    _Scheduler_SMP_Insert_scheduled_lifo
263  );
264}
265
266static void _Scheduler_priority_SMP_Enqueue_fifo(
267  Scheduler_Context *context,
268  Thread_Control *thread,
269  bool has_processor_allocated
270)
271{
272  _Scheduler_priority_SMP_Enqueue_ordered(
273    context,
274    thread,
275    has_processor_allocated,
276    _Scheduler_simple_Insert_priority_fifo_order,
277    _Scheduler_priority_SMP_Insert_ready_fifo,
278    _Scheduler_SMP_Insert_scheduled_fifo
279  );
280}
281
282void _Scheduler_priority_SMP_Unblock(
283  const Scheduler_Control *scheduler,
284  Thread_Control *thread
285)
286{
287  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
288
289  _Scheduler_priority_SMP_Enqueue_fifo( context, thread, false );
290}
291
292void _Scheduler_priority_SMP_Change_priority(
293  const Scheduler_Control *scheduler,
294  Thread_Control          *thread,
295  Priority_Control         new_priority,
296  bool                     prepend_it
297)
298{
299  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
300
301  _Scheduler_SMP_Change_priority(
302    context,
303    thread,
304    new_priority,
305    prepend_it,
306    _Scheduler_priority_SMP_Extract_from_ready,
307    _Scheduler_priority_SMP_Do_update,
308    _Scheduler_priority_SMP_Enqueue_fifo,
309    _Scheduler_priority_SMP_Enqueue_lifo
310  );
311}
312
313void _Scheduler_priority_SMP_Yield(
314  const Scheduler_Control *scheduler,
315  Thread_Control *thread
316)
317{
318  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
319  ISR_Level level;
320
321  _ISR_Disable( level );
322
323  _Scheduler_SMP_Extract_from_scheduled( thread );
324  _Scheduler_priority_SMP_Enqueue_fifo( context, thread, true );
325
326  _ISR_Enable( level );
327}
328
329void _Scheduler_priority_SMP_Schedule(
330  const Scheduler_Control *scheduler,
331  Thread_Control *thread
332)
333{
334  (void) scheduler;
335  (void) thread;
336}
337
338void _Scheduler_priority_SMP_Start_idle(
339  const Scheduler_Control *scheduler,
340  Thread_Control *thread,
341  Per_CPU_Control *cpu
342)
343{
344  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
345
346  _Scheduler_SMP_Start_idle( context, thread, cpu );
347}
Note: See TracBrowser for help on using the repository browser.