source: rtems/cpukit/score/src/schedulerprioritysmp.c @ 238629f

4.115
Last change on this file since 238629f was 238629f, checked in by Joel Sherrill <joel.sherrill@…>, on May 19, 2014 at 8:26:55 PM

Add SMP Priority Scheduler with Affinity

This scheduler attempts to account for needed thread migrations caused
as a side-effect of a thread state, affinity, or priority change operation.

This scheduler has its own allocate_processor handler named
_Scheduler_SMP_Allocate_processor_exact() because
_Scheduler_SMP_Allocate_processor() attempts to prevent an executing
thread from moving off its current CPU without considering affinity.
Without this, the scheduler makes all the right decisions and then
they are discarded at the end.

==Side Effects of Adding This Scheduler==

Added Thread_Control * parameter to Scheduler_SMP_Get_highest_ready type
so methods looking for the highest ready thread can filter by the processor
on which the thread blocking resides. This allows affinity to be considered.
Simple Priority SMP and Priority SMP ignore this parameter.

+ Added get_lowest_scheduled argument to _Scheduler_SMP_Enqueue_ordered().

+ Added allocate_processor argument to the following methods:

  • _Scheduler_SMP_Block()
  • _Scheduler_SMP_Enqueue_scheduled_ordered()
  • _Scheduler_SMP_Enqueue_scheduled_ordered()

+ schedulerprioritysmpimpl.h is a new file with prototypes for methods

which were formerly static in schedulerprioritysmp.c but now need to
be public to be shared with this scheduler.

NOTE:

_Scheduler_SMP_Get_lowest_ready() appears to have a path which would
allow it to return a NULL. Previously, _Scheduler_SMP_Enqueue_ordered()
would have asserted on it. If it cannot return a NULL,
_Scheduler_SMP_Get_lowest_ready() should have an assertions.

  • Property mode set to 100644
File size: 9.1 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/schedulerprioritysmpimpl.h>
30#include <rtems/score/schedulersmpimpl.h>
31
32static Scheduler_priority_SMP_Context *
33_Scheduler_priority_SMP_Get_context( const Scheduler_Control *scheduler )
34{
35  return (Scheduler_priority_SMP_Context *) _Scheduler_Get_context( scheduler );
36}
37
38Scheduler_priority_SMP_Context *_Scheduler_priority_SMP_Get_self(
39  Scheduler_Context *context
40)
41{
42  return (Scheduler_priority_SMP_Context *) context;
43}
44
45Scheduler_priority_SMP_Node *_Scheduler_priority_SMP_Node_get(
46  Thread_Control *thread
47)
48{
49  return (Scheduler_priority_SMP_Node *) _Scheduler_Node_get( thread );
50}
51
52static Scheduler_priority_SMP_Node *_Scheduler_priority_SMP_Node_downcast(
53  Scheduler_Node *node
54)
55{
56  return (Scheduler_priority_SMP_Node *) node;
57}
58
59void _Scheduler_priority_SMP_Initialize( const Scheduler_Control *scheduler )
60{
61  Scheduler_priority_SMP_Context *self =
62    _Scheduler_priority_SMP_Get_context( scheduler );
63
64  _Scheduler_SMP_Initialize( &self->Base );
65  _Priority_bit_map_Initialize( &self->Bit_map );
66  _Scheduler_priority_Ready_queue_initialize( &self->Ready[ 0 ] );
67}
68
69void _Scheduler_priority_SMP_Node_initialize(
70  const Scheduler_Control *scheduler,
71  Thread_Control *thread
72)
73{
74  Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread );
75
76  _Scheduler_SMP_Node_initialize( node );
77}
78
79void _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_priority(
99  const Scheduler_Control *scheduler,
100  Thread_Control *thread,
101  Priority_Control new_priority
102)
103{
104  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
105  Scheduler_Node *node = _Scheduler_Node_get( thread );
106
107  _Scheduler_priority_SMP_Do_update( context, node, new_priority );
108}
109
110static Thread_Control *_Scheduler_priority_SMP_Get_highest_ready(
111  Scheduler_Context *context,
112  Thread_Control    *thread
113)
114{
115  Scheduler_priority_SMP_Context *self =
116    _Scheduler_priority_SMP_Get_self( context );
117
118  (void) thread;
119
120  return _Scheduler_priority_Ready_queue_first(
121    &self->Bit_map,
122    &self->Ready[ 0 ]
123  );
124}
125
126void _Scheduler_priority_SMP_Move_from_scheduled_to_ready(
127  Scheduler_Context *context,
128  Thread_Control *scheduled_to_ready
129)
130{
131  Scheduler_priority_SMP_Context *self =
132    _Scheduler_priority_SMP_Get_self( context );
133  Scheduler_priority_SMP_Node *node =
134    _Scheduler_priority_SMP_Node_get( scheduled_to_ready );
135
136  _Chain_Extract_unprotected( &scheduled_to_ready->Object.Node );
137  _Scheduler_priority_Ready_queue_enqueue_first(
138    scheduled_to_ready,
139    &node->Ready_queue,
140    &self->Bit_map
141  );
142}
143
144void _Scheduler_priority_SMP_Move_from_ready_to_scheduled(
145  Scheduler_Context *context,
146  Thread_Control *ready_to_scheduled
147)
148{
149  Scheduler_priority_SMP_Context *self =
150    _Scheduler_priority_SMP_Get_self( context );
151  Scheduler_priority_SMP_Node *node =
152    _Scheduler_priority_SMP_Node_get( ready_to_scheduled );
153
154  _Scheduler_priority_Ready_queue_extract(
155    ready_to_scheduled,
156    &node->Ready_queue,
157    &self->Bit_map
158  );
159  _Scheduler_simple_Insert_priority_fifo(
160    &self->Base.Scheduled,
161    ready_to_scheduled
162  );
163}
164
165void _Scheduler_priority_SMP_Insert_ready_lifo(
166  Scheduler_Context *context,
167  Thread_Control *thread
168)
169{
170  Scheduler_priority_SMP_Context *self =
171    _Scheduler_priority_SMP_Get_self( context );
172  Scheduler_priority_SMP_Node *node =
173    _Scheduler_priority_SMP_Node_get( thread );
174
175  _Scheduler_priority_Ready_queue_enqueue(
176    thread,
177    &node->Ready_queue,
178    &self->Bit_map
179  );
180}
181
182void _Scheduler_priority_SMP_Insert_ready_fifo(
183  Scheduler_Context *context,
184  Thread_Control *thread
185)
186{
187  Scheduler_priority_SMP_Context *self =
188    _Scheduler_priority_SMP_Get_self( context );
189  Scheduler_priority_SMP_Node *node =
190    _Scheduler_priority_SMP_Node_get( thread );
191
192  _Scheduler_priority_Ready_queue_enqueue_first(
193    thread,
194    &node->Ready_queue,
195    &self->Bit_map
196  );
197}
198
199void _Scheduler_priority_SMP_Extract_from_ready(
200  Scheduler_Context *context,
201  Thread_Control *thread
202)
203{
204  Scheduler_priority_SMP_Context *self =
205    _Scheduler_priority_SMP_Get_self( context );
206  Scheduler_priority_SMP_Node *node =
207    _Scheduler_priority_SMP_Node_get( thread );
208
209  _Scheduler_priority_Ready_queue_extract(
210    thread,
211    &node->Ready_queue,
212    &self->Bit_map
213  );
214}
215
216void _Scheduler_priority_SMP_Block(
217  const Scheduler_Control *scheduler,
218  Thread_Control *thread
219)
220{
221  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
222
223  _Scheduler_SMP_Block(
224    context,
225    thread,
226    _Scheduler_priority_SMP_Extract_from_ready,
227    _Scheduler_priority_SMP_Get_highest_ready,
228    _Scheduler_priority_SMP_Move_from_ready_to_scheduled,
229    _Scheduler_SMP_Allocate_processor
230  );
231}
232
233static void _Scheduler_priority_SMP_Enqueue_ordered(
234  Scheduler_Context *context,
235  Thread_Control *thread,
236  Chain_Node_order order,
237  Scheduler_SMP_Insert insert_ready,
238  Scheduler_SMP_Insert insert_scheduled
239)
240{
241  _Scheduler_SMP_Enqueue_ordered(
242    context,
243    thread,
244    order,
245    insert_ready,
246    insert_scheduled,
247    _Scheduler_priority_SMP_Move_from_scheduled_to_ready,
248    _Scheduler_SMP_Get_lowest_scheduled,
249    _Scheduler_SMP_Allocate_processor
250  );
251}
252
253static void _Scheduler_priority_SMP_Enqueue_lifo(
254  Scheduler_Context *context,
255  Thread_Control *thread
256)
257{
258  _Scheduler_priority_SMP_Enqueue_ordered(
259    context,
260    thread,
261    _Scheduler_simple_Insert_priority_lifo_order,
262    _Scheduler_priority_SMP_Insert_ready_lifo,
263    _Scheduler_SMP_Insert_scheduled_lifo
264  );
265}
266
267static void _Scheduler_priority_SMP_Enqueue_fifo(
268  Scheduler_Context *context,
269  Thread_Control *thread
270)
271{
272  _Scheduler_priority_SMP_Enqueue_ordered(
273    context,
274    thread,
275    _Scheduler_simple_Insert_priority_fifo_order,
276    _Scheduler_priority_SMP_Insert_ready_fifo,
277    _Scheduler_SMP_Insert_scheduled_fifo
278  );
279}
280
281static void _Scheduler_priority_SMP_Enqueue_scheduled_ordered(
282  Scheduler_Context *context,
283  Thread_Control *thread,
284  Chain_Node_order order,
285  Scheduler_SMP_Insert insert_ready,
286  Scheduler_SMP_Insert insert_scheduled
287)
288{
289  _Scheduler_SMP_Enqueue_scheduled_ordered(
290    context,
291    thread,
292    order,
293    _Scheduler_priority_SMP_Get_highest_ready,
294    insert_ready,
295    insert_scheduled,
296    _Scheduler_priority_SMP_Move_from_ready_to_scheduled,
297    _Scheduler_SMP_Allocate_processor
298  );
299}
300
301static void _Scheduler_priority_SMP_Enqueue_scheduled_lifo(
302  Scheduler_Context *context,
303  Thread_Control *thread
304)
305{
306  _Scheduler_priority_SMP_Enqueue_scheduled_ordered(
307    context,
308    thread,
309    _Scheduler_simple_Insert_priority_lifo_order,
310    _Scheduler_priority_SMP_Insert_ready_lifo,
311    _Scheduler_SMP_Insert_scheduled_lifo
312  );
313}
314
315static void _Scheduler_priority_SMP_Enqueue_scheduled_fifo(
316  Scheduler_Context *context,
317  Thread_Control *thread
318)
319{
320  _Scheduler_priority_SMP_Enqueue_scheduled_ordered(
321    context,
322    thread,
323    _Scheduler_simple_Insert_priority_fifo_order,
324    _Scheduler_priority_SMP_Insert_ready_fifo,
325    _Scheduler_SMP_Insert_scheduled_fifo
326  );
327}
328
329void _Scheduler_priority_SMP_Unblock(
330  const Scheduler_Control *scheduler,
331  Thread_Control *thread
332)
333{
334  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
335
336  _Scheduler_SMP_Unblock(
337    context,
338    thread,
339    _Scheduler_priority_SMP_Enqueue_fifo
340  );
341}
342
343void _Scheduler_priority_SMP_Change_priority(
344  const Scheduler_Control *scheduler,
345  Thread_Control          *thread,
346  Priority_Control         new_priority,
347  bool                     prepend_it
348)
349{
350  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
351
352  _Scheduler_SMP_Change_priority(
353    context,
354    thread,
355    new_priority,
356    prepend_it,
357    _Scheduler_priority_SMP_Extract_from_ready,
358    _Scheduler_priority_SMP_Do_update,
359    _Scheduler_priority_SMP_Enqueue_fifo,
360    _Scheduler_priority_SMP_Enqueue_lifo,
361    _Scheduler_priority_SMP_Enqueue_scheduled_fifo,
362    _Scheduler_priority_SMP_Enqueue_scheduled_lifo
363  );
364}
365
366void _Scheduler_priority_SMP_Yield(
367  const Scheduler_Control *scheduler,
368  Thread_Control *thread
369)
370{
371  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
372  ISR_Level level;
373
374  _ISR_Disable( level );
375
376  _Scheduler_SMP_Extract_from_scheduled( thread );
377  _Scheduler_priority_SMP_Enqueue_scheduled_fifo( context, thread );
378
379  _ISR_Enable( level );
380}
Note: See TracBrowser for help on using the repository browser.