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

5
Last change on this file since fce900b5 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: 10.8 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ScoreSchedulerStrongAPA
5 *
6 * @brief Strong APA Scheduler Implementation
7 */
8
9/*
10 * Copyright (c) 2013, 2016 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/schedulerstrongapa.h>
28#include <rtems/score/schedulerpriorityimpl.h>
29#include <rtems/score/schedulersmpimpl.h>
30
31static Scheduler_strong_APA_Context *_Scheduler_strong_APA_Get_self(
32  Scheduler_Context *context
33)
34{
35  return (Scheduler_strong_APA_Context *) context;
36}
37
38static Scheduler_strong_APA_Node *
39_Scheduler_strong_APA_Node_downcast( Scheduler_Node *node )
40{
41  return (Scheduler_strong_APA_Node *) node;
42}
43
44static void _Scheduler_strong_APA_Move_from_scheduled_to_ready(
45  Scheduler_Context *context,
46  Scheduler_Node    *scheduled_to_ready
47)
48{
49  Scheduler_strong_APA_Context *self =
50    _Scheduler_strong_APA_Get_self( context );
51  Scheduler_strong_APA_Node *node =
52    _Scheduler_strong_APA_Node_downcast( scheduled_to_ready );
53
54  _Chain_Extract_unprotected( &node->Base.Base.Node.Chain );
55  _Scheduler_priority_Ready_queue_enqueue_first(
56    &node->Base.Base.Node.Chain,
57    &node->Ready_queue,
58    &self->Bit_map
59  );
60}
61
62static void _Scheduler_strong_APA_Move_from_ready_to_scheduled(
63  Scheduler_Context *context,
64  Scheduler_Node    *ready_to_scheduled
65)
66{
67  Scheduler_strong_APA_Context *self;
68  Scheduler_strong_APA_Node    *node;
69  Priority_Control              insert_priority;
70
71  self = _Scheduler_strong_APA_Get_self( context );
72  node = _Scheduler_strong_APA_Node_downcast( ready_to_scheduled );
73
74  _Scheduler_priority_Ready_queue_extract(
75    &node->Base.Base.Node.Chain,
76    &node->Ready_queue,
77    &self->Bit_map
78  );
79  insert_priority = _Scheduler_SMP_Node_priority( &node->Base.Base );
80  insert_priority = SCHEDULER_PRIORITY_APPEND( insert_priority );
81  _Chain_Insert_ordered_unprotected(
82    &self->Base.Scheduled,
83    &node->Base.Base.Node.Chain,
84    &insert_priority,
85    _Scheduler_SMP_Priority_less_equal
86  );
87}
88
89static void _Scheduler_strong_APA_Insert_ready(
90  Scheduler_Context *context,
91  Scheduler_Node    *node_base,
92  Priority_Control   insert_priority
93)
94{
95  Scheduler_strong_APA_Context *self;
96  Scheduler_strong_APA_Node    *node;
97
98  self = _Scheduler_strong_APA_Get_self( context );
99  node = _Scheduler_strong_APA_Node_downcast( node_base );
100
101  if ( SCHEDULER_PRIORITY_IS_APPEND( insert_priority ) ) {
102    _Scheduler_priority_Ready_queue_enqueue(
103      &node->Base.Base.Node.Chain,
104      &node->Ready_queue,
105      &self->Bit_map
106    );
107  } else {
108    _Scheduler_priority_Ready_queue_enqueue_first(
109      &node->Base.Base.Node.Chain,
110      &node->Ready_queue,
111      &self->Bit_map
112    );
113  }
114}
115
116static void _Scheduler_strong_APA_Extract_from_ready(
117  Scheduler_Context *context,
118  Scheduler_Node    *the_thread
119)
120{
121  Scheduler_strong_APA_Context *self =
122    _Scheduler_strong_APA_Get_self( context );
123  Scheduler_strong_APA_Node *node =
124    _Scheduler_strong_APA_Node_downcast( the_thread );
125
126  _Scheduler_priority_Ready_queue_extract(
127    &node->Base.Base.Node.Chain,
128    &node->Ready_queue,
129    &self->Bit_map
130  );
131}
132
133static void _Scheduler_strong_APA_Do_update(
134  Scheduler_Context *context,
135  Scheduler_Node *node_to_update,
136  Priority_Control new_priority
137)
138{
139  Scheduler_strong_APA_Context *self =
140    _Scheduler_strong_APA_Get_self( context );
141  Scheduler_strong_APA_Node *node =
142    _Scheduler_strong_APA_Node_downcast( node_to_update );
143
144  _Scheduler_SMP_Node_update_priority( &node->Base, new_priority );
145  _Scheduler_priority_Ready_queue_update(
146    &node->Ready_queue,
147    SCHEDULER_PRIORITY_UNMAP( new_priority ),
148    &self->Bit_map,
149    &self->Ready[ 0 ]
150  );
151}
152
153static Scheduler_strong_APA_Context *
154_Scheduler_strong_APA_Get_context( const Scheduler_Control *scheduler )
155{
156  return (Scheduler_strong_APA_Context *) _Scheduler_Get_context( scheduler );
157}
158
159void _Scheduler_strong_APA_Initialize( const Scheduler_Control *scheduler )
160{
161  Scheduler_strong_APA_Context *self =
162    _Scheduler_strong_APA_Get_context( scheduler );
163
164  _Scheduler_SMP_Initialize( &self->Base );
165  _Priority_bit_map_Initialize( &self->Bit_map );
166  _Scheduler_priority_Ready_queue_initialize(
167    &self->Ready[ 0 ],
168    scheduler->maximum_priority
169  );
170}
171
172void _Scheduler_strong_APA_Node_initialize(
173  const Scheduler_Control *scheduler,
174  Scheduler_Node          *node,
175  Thread_Control          *the_thread,
176  Priority_Control         priority
177)
178{
179  Scheduler_Context            *context;
180  Scheduler_strong_APA_Context *self;
181  Scheduler_strong_APA_Node    *the_node;
182
183  the_node = _Scheduler_strong_APA_Node_downcast( node );
184  _Scheduler_SMP_Node_initialize(
185    scheduler,
186    &the_node->Base,
187    the_thread,
188    priority
189  );
190
191  context = _Scheduler_Get_context( scheduler );
192  self = _Scheduler_strong_APA_Get_self( context );
193  _Scheduler_priority_Ready_queue_update(
194    &the_node->Ready_queue,
195    SCHEDULER_PRIORITY_UNMAP( priority ),
196    &self->Bit_map,
197    &self->Ready[ 0 ]
198  );
199}
200
201static bool _Scheduler_strong_APA_Has_ready( Scheduler_Context *context )
202{
203  Scheduler_strong_APA_Context *self =
204    _Scheduler_strong_APA_Get_self( context );
205
206  return !_Priority_bit_map_Is_empty( &self->Bit_map );
207}
208
209static Scheduler_Node *_Scheduler_strong_APA_Get_highest_ready(
210  Scheduler_Context *context,
211  Scheduler_Node    *node
212)
213{
214  Scheduler_strong_APA_Context *self =
215    _Scheduler_strong_APA_Get_self( context );
216
217  (void) node;
218
219  return (Scheduler_Node *) _Scheduler_priority_Ready_queue_first(
220    &self->Bit_map,
221    &self->Ready[ 0 ]
222  );
223}
224
225void _Scheduler_strong_APA_Block(
226  const Scheduler_Control *scheduler,
227  Thread_Control          *the_thread,
228  Scheduler_Node          *node
229)
230{
231  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
232
233  _Scheduler_SMP_Block(
234    context,
235    the_thread,
236    node,
237    _Scheduler_strong_APA_Extract_from_ready,
238    _Scheduler_strong_APA_Get_highest_ready,
239    _Scheduler_strong_APA_Move_from_ready_to_scheduled,
240    _Scheduler_SMP_Allocate_processor_exact
241  );
242}
243
244static bool _Scheduler_strong_APA_Enqueue(
245  Scheduler_Context *context,
246  Scheduler_Node    *node,
247  Priority_Control   insert_priority
248)
249{
250  return _Scheduler_SMP_Enqueue(
251    context,
252    node,
253    insert_priority,
254    _Scheduler_SMP_Priority_less_equal,
255    _Scheduler_strong_APA_Insert_ready,
256    _Scheduler_SMP_Insert_scheduled,
257    _Scheduler_strong_APA_Move_from_scheduled_to_ready,
258    _Scheduler_SMP_Get_lowest_scheduled,
259    _Scheduler_SMP_Allocate_processor_exact
260  );
261}
262
263static bool _Scheduler_strong_APA_Enqueue_scheduled(
264  Scheduler_Context *context,
265  Scheduler_Node    *node,
266  Priority_Control  insert_priority
267)
268{
269  return _Scheduler_SMP_Enqueue_scheduled(
270    context,
271    node,
272    insert_priority,
273    _Scheduler_SMP_Priority_less_equal,
274    _Scheduler_strong_APA_Extract_from_ready,
275    _Scheduler_strong_APA_Get_highest_ready,
276    _Scheduler_strong_APA_Insert_ready,
277    _Scheduler_SMP_Insert_scheduled,
278    _Scheduler_strong_APA_Move_from_ready_to_scheduled,
279    _Scheduler_SMP_Allocate_processor_exact
280  );
281}
282
283void _Scheduler_strong_APA_Unblock(
284  const Scheduler_Control *scheduler,
285  Thread_Control          *the_thread,
286  Scheduler_Node          *node
287)
288{
289  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
290
291  _Scheduler_SMP_Unblock(
292    context,
293    the_thread,
294    node,
295    _Scheduler_strong_APA_Do_update,
296    _Scheduler_strong_APA_Enqueue
297  );
298}
299
300static bool _Scheduler_strong_APA_Do_ask_for_help(
301  Scheduler_Context *context,
302  Thread_Control    *the_thread,
303  Scheduler_Node    *node
304)
305{
306  return _Scheduler_SMP_Ask_for_help(
307    context,
308    the_thread,
309    node,
310    _Scheduler_SMP_Priority_less_equal,
311    _Scheduler_strong_APA_Insert_ready,
312    _Scheduler_SMP_Insert_scheduled,
313    _Scheduler_strong_APA_Move_from_scheduled_to_ready,
314    _Scheduler_SMP_Get_lowest_scheduled,
315    _Scheduler_SMP_Allocate_processor_lazy
316  );
317}
318
319void _Scheduler_strong_APA_Update_priority(
320  const Scheduler_Control *scheduler,
321  Thread_Control          *the_thread,
322  Scheduler_Node          *node
323)
324{
325  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
326
327  _Scheduler_SMP_Update_priority(
328    context,
329    the_thread,
330    node,
331    _Scheduler_strong_APA_Extract_from_ready,
332    _Scheduler_strong_APA_Do_update,
333    _Scheduler_strong_APA_Enqueue,
334    _Scheduler_strong_APA_Enqueue_scheduled,
335    _Scheduler_strong_APA_Do_ask_for_help
336  );
337}
338
339bool _Scheduler_strong_APA_Ask_for_help(
340  const Scheduler_Control *scheduler,
341  Thread_Control          *the_thread,
342  Scheduler_Node          *node
343)
344{
345  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
346
347  return _Scheduler_strong_APA_Do_ask_for_help( context, the_thread, node );
348}
349
350void _Scheduler_strong_APA_Reconsider_help_request(
351  const Scheduler_Control *scheduler,
352  Thread_Control          *the_thread,
353  Scheduler_Node          *node
354)
355{
356  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
357
358  _Scheduler_SMP_Reconsider_help_request(
359    context,
360    the_thread,
361    node,
362    _Scheduler_strong_APA_Extract_from_ready
363  );
364}
365
366void _Scheduler_strong_APA_Withdraw_node(
367  const Scheduler_Control *scheduler,
368  Thread_Control          *the_thread,
369  Scheduler_Node          *node,
370  Thread_Scheduler_state   next_state
371)
372{
373  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
374
375  _Scheduler_SMP_Withdraw_node(
376    context,
377    the_thread,
378    node,
379    next_state,
380    _Scheduler_strong_APA_Extract_from_ready,
381    _Scheduler_strong_APA_Get_highest_ready,
382    _Scheduler_strong_APA_Move_from_ready_to_scheduled,
383    _Scheduler_SMP_Allocate_processor_lazy
384  );
385}
386
387void _Scheduler_strong_APA_Add_processor(
388  const Scheduler_Control *scheduler,
389  Thread_Control          *idle
390)
391{
392  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
393
394  _Scheduler_SMP_Add_processor(
395    context,
396    idle,
397    _Scheduler_strong_APA_Has_ready,
398    _Scheduler_strong_APA_Enqueue_scheduled,
399    _Scheduler_SMP_Do_nothing_register_idle
400  );
401}
402
403Thread_Control *_Scheduler_strong_APA_Remove_processor(
404  const Scheduler_Control *scheduler,
405  Per_CPU_Control         *cpu
406)
407{
408  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
409
410  return _Scheduler_SMP_Remove_processor(
411    context,
412    cpu,
413    _Scheduler_strong_APA_Extract_from_ready,
414    _Scheduler_strong_APA_Enqueue
415  );
416}
417
418void _Scheduler_strong_APA_Yield(
419  const Scheduler_Control *scheduler,
420  Thread_Control          *the_thread,
421  Scheduler_Node          *node
422)
423{
424  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
425
426  _Scheduler_SMP_Yield(
427    context,
428    the_thread,
429    node,
430    _Scheduler_strong_APA_Extract_from_ready,
431    _Scheduler_strong_APA_Enqueue,
432    _Scheduler_strong_APA_Enqueue_scheduled
433  );
434}
Note: See TracBrowser for help on using the repository browser.