source: rtems/cpukit/score/src/schedulersimplesmp.c @ c597fb1

5
Last change on this file since c597fb1 was c597fb1, checked in by Sebastian Huber <sebastian.huber@…>, on 11/09/17 at 15:21:37

score: Optimize scheduler priority updates

Thread priority changes may append or prepend the thread to its priority
group on the scheduler ready queue. Previously, a separate priority
value and a prepend-it flag in the scheduler node were used to propagate
a priority change to the scheduler.

Now, use an append-it bit in the priority control and reduce the plain
priority value to 63 bits.

This change leads to a significant code size reduction (about 25%) of
the SMP schedulers. The negligible increase of the standard priority
scheduler is due to some additional shift operations
(SCHEDULER_PRIORITY_MAP() and SCHEDULER_PRIORITY_UNMAP()).

Before:

text filename

136 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulersimpleblock.o
464 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulersimplechangepriority.o

24 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulersimple.o

108 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulersimpleschedule.o
292 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulersimpleunblock.o
264 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulersimpleyield.o

text filename

280 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulerpriorityblock.o
488 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulerprioritychangepriority.o
200 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulerpriority.o
164 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulerpriorityschedule.o
328 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulerpriorityunblock.o
200 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulerpriorityyield.o

text filename

24112 arm-rtems5/c/imx7/cpukit/score/src/libscore_a-scheduleredfsmp.o

text filename

37204 sparc-rtems5/c/gr740/cpukit/score/src/libscore_a-scheduleredfsmp.o

text filename

42236 powerpc-rtems5/c/qoriq_e6500_32/cpukit/score/src/libscore_a-scheduleredfsmp.o

After:

text filename

136 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulersimpleblock.o
272 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulersimplechangepriority.o

24 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulersimple.o

108 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulersimpleschedule.o
292 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulersimpleunblock.o
264 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulersimpleyield.o

text filename

280 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulerpriorityblock.o
488 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulerprioritychangepriority.o
208 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulerpriority.o
164 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulerpriorityschedule.o
332 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulerpriorityunblock.o
200 sparc-rtems5/c/erc32/cpukit/score/src/libscore_a-schedulerpriorityyield.o

text filename

18860 arm-rtems5/c/imx7/cpukit/score/src/libscore_a-scheduleredfsmp.o

text filename

28520 sparc-rtems5/c/gr740/cpukit/score/src/libscore_a-scheduleredfsmp.o

text filename

32664 powerpc-rtems5/c/qoriq_e6500_32/cpukit/score/src/libscore_a-scheduleredfsmp.o

  • Property mode set to 100644
File size: 9.2 KB
Line 
1/**
2 * @file
3 *
4 * @brief Simple SMP Scheduler Implementation
5 *
6 * @ingroup ScoreSchedulerSMPSimple
7 */
8
9/*
10 * Copyright (c) 2013, 2016 embedded brains GmbH.
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/schedulersimplesmp.h>
22#include <rtems/score/schedulersmpimpl.h>
23
24static Scheduler_simple_SMP_Context *
25_Scheduler_simple_SMP_Get_context( const Scheduler_Control *scheduler )
26{
27  return (Scheduler_simple_SMP_Context *) _Scheduler_Get_context( scheduler );
28}
29
30static Scheduler_simple_SMP_Context *
31_Scheduler_simple_SMP_Get_self( Scheduler_Context *context )
32{
33  return (Scheduler_simple_SMP_Context *) context;
34}
35
36void _Scheduler_simple_SMP_Initialize( const Scheduler_Control *scheduler )
37{
38  Scheduler_simple_SMP_Context *self =
39    _Scheduler_simple_SMP_Get_context( scheduler );
40
41  _Scheduler_SMP_Initialize( &self->Base );
42  _Chain_Initialize_empty( &self->Ready );
43}
44
45void _Scheduler_simple_SMP_Node_initialize(
46  const Scheduler_Control *scheduler,
47  Scheduler_Node          *node,
48  Thread_Control          *the_thread,
49  Priority_Control         priority
50)
51{
52  Scheduler_SMP_Node *smp_node;
53
54  smp_node = _Scheduler_SMP_Node_downcast( node );
55  _Scheduler_SMP_Node_initialize( scheduler, smp_node, the_thread, priority );
56}
57
58static void _Scheduler_simple_SMP_Do_update(
59  Scheduler_Context *context,
60  Scheduler_Node    *node,
61  Priority_Control   new_priority
62)
63{
64  Scheduler_SMP_Node *smp_node;
65
66  (void) context;
67
68  smp_node = _Scheduler_SMP_Node_downcast( node );
69  _Scheduler_SMP_Node_update_priority( smp_node, new_priority );
70}
71
72static bool _Scheduler_simple_SMP_Has_ready( Scheduler_Context *context )
73{
74  Scheduler_simple_SMP_Context *self =
75    _Scheduler_simple_SMP_Get_self( context );
76
77  return !_Chain_Is_empty( &self->Ready );
78}
79
80static Scheduler_Node *_Scheduler_simple_SMP_Get_highest_ready(
81  Scheduler_Context *context,
82  Scheduler_Node    *node
83)
84{
85  Scheduler_simple_SMP_Context *self =
86    _Scheduler_simple_SMP_Get_self( context );
87  Scheduler_Node *first = (Scheduler_Node *) _Chain_First( &self->Ready );
88
89  (void) node;
90
91  _Assert( &first->Node.Chain != _Chain_Tail( &self->Ready ) );
92
93  return first;
94}
95
96static void _Scheduler_simple_SMP_Move_from_scheduled_to_ready(
97  Scheduler_Context *context,
98  Scheduler_Node    *scheduled_to_ready
99)
100{
101  Scheduler_simple_SMP_Context *self;
102  Priority_Control              insert_priority;
103
104  self = _Scheduler_simple_SMP_Get_self( context );
105
106  _Chain_Extract_unprotected( &scheduled_to_ready->Node.Chain );
107  insert_priority = _Scheduler_SMP_Node_priority( scheduled_to_ready );
108  _Chain_Insert_ordered_unprotected(
109    &self->Ready,
110    &scheduled_to_ready->Node.Chain,
111    &insert_priority,
112    _Scheduler_SMP_Priority_less_equal
113  );
114}
115
116static void _Scheduler_simple_SMP_Move_from_ready_to_scheduled(
117  Scheduler_Context *context,
118  Scheduler_Node    *ready_to_scheduled
119)
120{
121  Scheduler_simple_SMP_Context *self;
122  Priority_Control              insert_priority;
123
124  self = _Scheduler_simple_SMP_Get_self( context );
125
126  _Chain_Extract_unprotected( &ready_to_scheduled->Node.Chain );
127  insert_priority = _Scheduler_SMP_Node_priority( ready_to_scheduled );
128  insert_priority = SCHEDULER_PRIORITY_APPEND( insert_priority );
129  _Chain_Insert_ordered_unprotected(
130    &self->Base.Scheduled,
131    &ready_to_scheduled->Node.Chain,
132    &insert_priority,
133    _Scheduler_SMP_Priority_less_equal
134  );
135}
136
137static void _Scheduler_simple_SMP_Insert_ready(
138  Scheduler_Context *context,
139  Scheduler_Node    *node_to_insert,
140  Priority_Control   insert_priority
141)
142{
143  Scheduler_simple_SMP_Context *self;
144
145  self = _Scheduler_simple_SMP_Get_self( context );
146
147  _Chain_Insert_ordered_unprotected(
148    &self->Ready,
149    &node_to_insert->Node.Chain,
150    &insert_priority,
151    _Scheduler_SMP_Priority_less_equal
152  );
153}
154
155static void _Scheduler_simple_SMP_Extract_from_ready(
156  Scheduler_Context *context,
157  Scheduler_Node    *node_to_extract
158)
159{
160  (void) context;
161
162  _Chain_Extract_unprotected( &node_to_extract->Node.Chain );
163}
164
165void _Scheduler_simple_SMP_Block(
166  const Scheduler_Control *scheduler,
167  Thread_Control          *thread,
168  Scheduler_Node          *node
169)
170{
171  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
172
173  _Scheduler_SMP_Block(
174    context,
175    thread,
176    node,
177    _Scheduler_simple_SMP_Extract_from_ready,
178    _Scheduler_simple_SMP_Get_highest_ready,
179    _Scheduler_simple_SMP_Move_from_ready_to_scheduled,
180    _Scheduler_SMP_Allocate_processor_lazy
181  );
182}
183
184static bool _Scheduler_simple_SMP_Enqueue(
185  Scheduler_Context *context,
186  Scheduler_Node    *node,
187  Priority_Control   insert_priority
188)
189{
190  return _Scheduler_SMP_Enqueue(
191    context,
192    node,
193    insert_priority,
194    _Scheduler_SMP_Priority_less_equal,
195    _Scheduler_simple_SMP_Insert_ready,
196    _Scheduler_SMP_Insert_scheduled,
197    _Scheduler_simple_SMP_Move_from_scheduled_to_ready,
198    _Scheduler_SMP_Get_lowest_scheduled,
199    _Scheduler_SMP_Allocate_processor_lazy
200  );
201}
202
203static bool _Scheduler_simple_SMP_Enqueue_scheduled(
204  Scheduler_Context *context,
205  Scheduler_Node    *node,
206  Priority_Control   insert_priority
207)
208{
209  return _Scheduler_SMP_Enqueue_scheduled(
210    context,
211    node,
212    insert_priority,
213    _Scheduler_SMP_Priority_less_equal,
214    _Scheduler_simple_SMP_Extract_from_ready,
215    _Scheduler_simple_SMP_Get_highest_ready,
216    _Scheduler_simple_SMP_Insert_ready,
217    _Scheduler_SMP_Insert_scheduled,
218    _Scheduler_simple_SMP_Move_from_ready_to_scheduled,
219    _Scheduler_SMP_Allocate_processor_lazy
220  );
221}
222
223void _Scheduler_simple_SMP_Unblock(
224  const Scheduler_Control *scheduler,
225  Thread_Control          *thread,
226  Scheduler_Node          *node
227)
228{
229  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
230
231  _Scheduler_SMP_Unblock(
232    context,
233    thread,
234    node,
235    _Scheduler_simple_SMP_Do_update,
236    _Scheduler_simple_SMP_Enqueue
237  );
238}
239
240static bool _Scheduler_simple_SMP_Do_ask_for_help(
241  Scheduler_Context *context,
242  Thread_Control    *the_thread,
243  Scheduler_Node    *node
244)
245{
246  return _Scheduler_SMP_Ask_for_help(
247    context,
248    the_thread,
249    node,
250    _Scheduler_SMP_Priority_less_equal,
251    _Scheduler_simple_SMP_Insert_ready,
252    _Scheduler_SMP_Insert_scheduled,
253    _Scheduler_simple_SMP_Move_from_scheduled_to_ready,
254    _Scheduler_SMP_Get_lowest_scheduled,
255    _Scheduler_SMP_Allocate_processor_lazy
256  );
257}
258
259void _Scheduler_simple_SMP_Update_priority(
260  const Scheduler_Control *scheduler,
261  Thread_Control          *thread,
262  Scheduler_Node          *node
263)
264{
265  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
266
267  _Scheduler_SMP_Update_priority(
268    context,
269    thread,
270    node,
271    _Scheduler_simple_SMP_Extract_from_ready,
272    _Scheduler_simple_SMP_Do_update,
273    _Scheduler_simple_SMP_Enqueue,
274    _Scheduler_simple_SMP_Enqueue_scheduled,
275    _Scheduler_simple_SMP_Do_ask_for_help
276  );
277}
278
279bool _Scheduler_simple_SMP_Ask_for_help(
280  const Scheduler_Control *scheduler,
281  Thread_Control          *the_thread,
282  Scheduler_Node          *node
283)
284{
285  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
286
287  return _Scheduler_simple_SMP_Do_ask_for_help( context, the_thread, node );
288}
289
290void _Scheduler_simple_SMP_Reconsider_help_request(
291  const Scheduler_Control *scheduler,
292  Thread_Control          *the_thread,
293  Scheduler_Node          *node
294)
295{
296  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
297
298  _Scheduler_SMP_Reconsider_help_request(
299    context,
300    the_thread,
301    node,
302    _Scheduler_simple_SMP_Extract_from_ready
303  );
304}
305
306void _Scheduler_simple_SMP_Withdraw_node(
307  const Scheduler_Control *scheduler,
308  Thread_Control          *the_thread,
309  Scheduler_Node          *node,
310  Thread_Scheduler_state   next_state
311)
312{
313  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
314
315  _Scheduler_SMP_Withdraw_node(
316    context,
317    the_thread,
318    node,
319    next_state,
320    _Scheduler_simple_SMP_Extract_from_ready,
321    _Scheduler_simple_SMP_Get_highest_ready,
322    _Scheduler_simple_SMP_Move_from_ready_to_scheduled,
323    _Scheduler_SMP_Allocate_processor_lazy
324  );
325}
326
327void _Scheduler_simple_SMP_Add_processor(
328  const Scheduler_Control *scheduler,
329  Thread_Control          *idle
330)
331{
332  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
333
334  _Scheduler_SMP_Add_processor(
335    context,
336    idle,
337    _Scheduler_simple_SMP_Has_ready,
338    _Scheduler_simple_SMP_Enqueue_scheduled,
339    _Scheduler_SMP_Do_nothing_register_idle
340  );
341}
342
343Thread_Control *_Scheduler_simple_SMP_Remove_processor(
344  const Scheduler_Control *scheduler,
345  Per_CPU_Control         *cpu
346)
347{
348  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
349
350  return _Scheduler_SMP_Remove_processor(
351    context,
352    cpu,
353    _Scheduler_simple_SMP_Extract_from_ready,
354    _Scheduler_simple_SMP_Enqueue
355  );
356}
357
358void _Scheduler_simple_SMP_Yield(
359  const Scheduler_Control *scheduler,
360  Thread_Control          *thread,
361  Scheduler_Node          *node
362)
363{
364  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
365
366  _Scheduler_SMP_Yield(
367    context,
368    thread,
369    node,
370    _Scheduler_simple_SMP_Extract_from_ready,
371    _Scheduler_simple_SMP_Enqueue,
372    _Scheduler_simple_SMP_Enqueue_scheduled
373  );
374}
Note: See TracBrowser for help on using the repository browser.