source: rtems/cpukit/score/src/scheduleredfsmp.c @ fab446f

5
Last change on this file since fab446f was fab446f, checked in by Sebastian Huber <sebastian.huber@…>, on 07/05/17 at 06:10:11

score: Fix format

  • Property mode set to 100644
File size: 12.0 KB
Line 
1/**
2 * @file
3 *
4 * @brief EDF SMP Scheduler Implementation
5 *
6 * @ingroup ScoreSchedulerSMPEDF
7 */
8
9/*
10 * Copyright (c) 2017 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/scheduleredfsmp.h>
22#include <rtems/score/schedulersmpimpl.h>
23
24static Scheduler_EDF_SMP_Context *
25_Scheduler_EDF_SMP_Get_context( const Scheduler_Control *scheduler )
26{
27  return (Scheduler_EDF_SMP_Context *) _Scheduler_Get_context( scheduler );
28}
29
30static Scheduler_EDF_SMP_Context *
31_Scheduler_EDF_SMP_Get_self( Scheduler_Context *context )
32{
33  return (Scheduler_EDF_SMP_Context *) context;
34}
35
36static inline Scheduler_EDF_SMP_Node *
37_Scheduler_EDF_SMP_Node_downcast( Scheduler_Node *node )
38{
39  return (Scheduler_EDF_SMP_Node *) node;
40}
41
42static inline bool _Scheduler_EDF_SMP_Less(
43  const void        *left,
44  const RBTree_Node *right
45)
46{
47  const Priority_Control   *the_left;
48  const Scheduler_SMP_Node *the_right;
49  Priority_Control          prio_left;
50  Priority_Control          prio_right;
51
52  the_left = left;
53  the_right = RTEMS_CONTAINER_OF( right, Scheduler_SMP_Node, Base.Node.RBTree );
54
55  prio_left = *the_left;
56  prio_right = the_right->priority;
57
58  return prio_left < prio_right;
59}
60
61static inline bool _Scheduler_EDF_SMP_Less_or_equal(
62  const void        *left,
63  const RBTree_Node *right
64)
65{
66  const Priority_Control   *the_left;
67  const Scheduler_SMP_Node *the_right;
68  Priority_Control          prio_left;
69  Priority_Control          prio_right;
70
71  the_left = left;
72  the_right = RTEMS_CONTAINER_OF( right, Scheduler_SMP_Node, Base.Node.RBTree );
73
74  prio_left = *the_left;
75  prio_right = the_right->priority;
76
77  return prio_left <= prio_right;
78}
79
80void _Scheduler_EDF_SMP_Initialize( const Scheduler_Control *scheduler )
81{
82  Scheduler_EDF_SMP_Context *self =
83    _Scheduler_EDF_SMP_Get_context( scheduler );
84
85  _Scheduler_SMP_Initialize( &self->Base );
86  _RBTree_Initialize_empty( &self->Ready );
87}
88
89void _Scheduler_EDF_SMP_Node_initialize(
90  const Scheduler_Control *scheduler,
91  Scheduler_Node          *node,
92  Thread_Control          *the_thread,
93  Priority_Control         priority
94)
95{
96  Scheduler_SMP_Node *smp_node;
97
98  smp_node = _Scheduler_SMP_Node_downcast( node );
99  _Scheduler_SMP_Node_initialize( scheduler, smp_node, the_thread, priority );
100}
101
102static void _Scheduler_EDF_SMP_Do_update(
103  Scheduler_Context *context,
104  Scheduler_Node    *node,
105  Priority_Control   new_priority
106)
107{
108  Scheduler_SMP_Node *smp_node;
109
110  (void) context;
111
112  smp_node = _Scheduler_SMP_Node_downcast( node );
113  _Scheduler_SMP_Node_update_priority( smp_node, new_priority );
114}
115
116static bool _Scheduler_EDF_SMP_Has_ready( Scheduler_Context *context )
117{
118  Scheduler_EDF_SMP_Context *self = _Scheduler_EDF_SMP_Get_self( context );
119
120  return !_RBTree_Is_empty( &self->Ready );
121}
122
123static Scheduler_Node *_Scheduler_EDF_SMP_Get_highest_ready(
124  Scheduler_Context *context,
125  Scheduler_Node    *node
126)
127{
128  Scheduler_EDF_SMP_Context *self = _Scheduler_EDF_SMP_Get_self( context );
129  Scheduler_Node *first = (Scheduler_Node *) _RBTree_Minimum( &self->Ready );
130
131  (void) node;
132
133  _Assert( &first->Node != NULL );
134
135  return first;
136}
137
138static void _Scheduler_EDF_SMP_Move_from_scheduled_to_ready(
139  Scheduler_Context *context,
140  Scheduler_Node    *scheduled_to_ready
141)
142{
143  Scheduler_EDF_SMP_Context *self = _Scheduler_EDF_SMP_Get_self( context );
144  Scheduler_EDF_SMP_Node *node =
145    _Scheduler_EDF_SMP_Node_downcast( scheduled_to_ready );
146
147  _Chain_Extract_unprotected( &node->Base.Base.Node.Chain );
148  _RBTree_Initialize_node( &node->Base.Base.Node.RBTree );
149  _RBTree_Insert_inline(
150    &self->Ready,
151    &node->Base.Base.Node.RBTree,
152    &node->Base.priority,
153    _Scheduler_EDF_SMP_Less
154  );
155}
156
157static void _Scheduler_EDF_SMP_Move_from_ready_to_scheduled(
158  Scheduler_Context *context,
159  Scheduler_Node    *ready_to_scheduled
160)
161{
162  Scheduler_EDF_SMP_Context *self = _Scheduler_EDF_SMP_Get_self( context );
163  Scheduler_EDF_SMP_Node *node =
164    _Scheduler_EDF_SMP_Node_downcast( ready_to_scheduled );
165
166  _RBTree_Extract( &self->Ready, &node->Base.Base.Node.RBTree );
167  _Chain_Initialize_node( &node->Base.Base.Node.Chain );
168  _Chain_Insert_ordered_unprotected(
169    &self->Base.Scheduled,
170    &node->Base.Base.Node.Chain,
171    _Scheduler_SMP_Insert_priority_fifo_order
172  );
173}
174
175static void _Scheduler_EDF_SMP_Insert_ready_lifo(
176  Scheduler_Context *context,
177  Scheduler_Node    *node_to_insert
178)
179{
180  Scheduler_EDF_SMP_Context *self = _Scheduler_EDF_SMP_Get_self( context );
181  Scheduler_EDF_SMP_Node *node =
182    _Scheduler_EDF_SMP_Node_downcast( node_to_insert );
183
184  _RBTree_Initialize_node( &node->Base.Base.Node.RBTree );
185  _RBTree_Insert_inline(
186    &self->Ready,
187    &node->Base.Base.Node.RBTree,
188    &node->Base.priority,
189    _Scheduler_EDF_SMP_Less_or_equal
190  );
191}
192
193static void _Scheduler_EDF_SMP_Insert_ready_fifo(
194  Scheduler_Context *context,
195  Scheduler_Node    *node_to_insert
196)
197{
198  Scheduler_EDF_SMP_Context *self = _Scheduler_EDF_SMP_Get_self( context );
199  Scheduler_EDF_SMP_Node *node =
200    _Scheduler_EDF_SMP_Node_downcast( node_to_insert );
201
202  _RBTree_Initialize_node( &node->Base.Base.Node.RBTree );
203  _RBTree_Insert_inline(
204    &self->Ready,
205    &node->Base.Base.Node.RBTree,
206    &node->Base.priority,
207    _Scheduler_EDF_SMP_Less
208  );
209}
210
211static void _Scheduler_EDF_SMP_Extract_from_ready(
212  Scheduler_Context *context,
213  Scheduler_Node    *node_to_extract
214)
215{
216  Scheduler_EDF_SMP_Context *self = _Scheduler_EDF_SMP_Get_self( context );
217  Scheduler_EDF_SMP_Node *node =
218    _Scheduler_EDF_SMP_Node_downcast( node_to_extract );
219
220  _RBTree_Extract( &self->Ready, &node->Base.Base.Node.RBTree );
221  _Chain_Initialize_node( &node->Base.Base.Node.Chain );
222}
223
224void _Scheduler_EDF_SMP_Block(
225  const Scheduler_Control *scheduler,
226  Thread_Control          *thread,
227  Scheduler_Node          *node
228)
229{
230  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
231
232  _Scheduler_SMP_Block(
233    context,
234    thread,
235    node,
236    _Scheduler_EDF_SMP_Extract_from_ready,
237    _Scheduler_EDF_SMP_Get_highest_ready,
238    _Scheduler_EDF_SMP_Move_from_ready_to_scheduled,
239    _Scheduler_SMP_Allocate_processor_lazy
240  );
241}
242
243static bool _Scheduler_EDF_SMP_Enqueue_ordered(
244  Scheduler_Context    *context,
245  Scheduler_Node       *node,
246  Chain_Node_order      order,
247  Scheduler_SMP_Insert  insert_ready,
248  Scheduler_SMP_Insert  insert_scheduled
249)
250{
251  return _Scheduler_SMP_Enqueue_ordered(
252    context,
253    node,
254    order,
255    insert_ready,
256    insert_scheduled,
257    _Scheduler_EDF_SMP_Move_from_scheduled_to_ready,
258    _Scheduler_SMP_Get_lowest_scheduled,
259    _Scheduler_SMP_Allocate_processor_lazy
260  );
261}
262
263static bool _Scheduler_EDF_SMP_Enqueue_lifo(
264  Scheduler_Context *context,
265  Scheduler_Node    *node
266)
267{
268  return _Scheduler_EDF_SMP_Enqueue_ordered(
269    context,
270    node,
271    _Scheduler_SMP_Insert_priority_lifo_order,
272    _Scheduler_EDF_SMP_Insert_ready_lifo,
273    _Scheduler_SMP_Insert_scheduled_lifo
274  );
275}
276
277static bool _Scheduler_EDF_SMP_Enqueue_fifo(
278  Scheduler_Context *context,
279  Scheduler_Node    *node
280)
281{
282  return _Scheduler_EDF_SMP_Enqueue_ordered(
283    context,
284    node,
285    _Scheduler_SMP_Insert_priority_fifo_order,
286    _Scheduler_EDF_SMP_Insert_ready_fifo,
287    _Scheduler_SMP_Insert_scheduled_fifo
288  );
289}
290
291static bool _Scheduler_EDF_SMP_Enqueue_scheduled_ordered(
292  Scheduler_Context *context,
293  Scheduler_Node *node,
294  Chain_Node_order order,
295  Scheduler_SMP_Insert insert_ready,
296  Scheduler_SMP_Insert insert_scheduled
297)
298{
299  return _Scheduler_SMP_Enqueue_scheduled_ordered(
300    context,
301    node,
302    order,
303    _Scheduler_EDF_SMP_Extract_from_ready,
304    _Scheduler_EDF_SMP_Get_highest_ready,
305    insert_ready,
306    insert_scheduled,
307    _Scheduler_EDF_SMP_Move_from_ready_to_scheduled,
308    _Scheduler_SMP_Allocate_processor_lazy
309  );
310}
311
312static bool _Scheduler_EDF_SMP_Enqueue_scheduled_lifo(
313  Scheduler_Context *context,
314  Scheduler_Node *node
315)
316{
317  return _Scheduler_EDF_SMP_Enqueue_scheduled_ordered(
318    context,
319    node,
320    _Scheduler_SMP_Insert_priority_lifo_order,
321    _Scheduler_EDF_SMP_Insert_ready_lifo,
322    _Scheduler_SMP_Insert_scheduled_lifo
323  );
324}
325
326static bool _Scheduler_EDF_SMP_Enqueue_scheduled_fifo(
327  Scheduler_Context *context,
328  Scheduler_Node *node
329)
330{
331  return _Scheduler_EDF_SMP_Enqueue_scheduled_ordered(
332    context,
333    node,
334    _Scheduler_SMP_Insert_priority_fifo_order,
335    _Scheduler_EDF_SMP_Insert_ready_fifo,
336    _Scheduler_SMP_Insert_scheduled_fifo
337  );
338}
339
340void _Scheduler_EDF_SMP_Unblock(
341  const Scheduler_Control *scheduler,
342  Thread_Control          *thread,
343  Scheduler_Node          *node
344)
345{
346  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
347
348  _Scheduler_SMP_Unblock(
349    context,
350    thread,
351    node,
352    _Scheduler_EDF_SMP_Do_update,
353    _Scheduler_EDF_SMP_Enqueue_fifo
354  );
355}
356
357static bool _Scheduler_EDF_SMP_Do_ask_for_help(
358  Scheduler_Context *context,
359  Thread_Control    *the_thread,
360  Scheduler_Node    *node
361)
362{
363  return _Scheduler_SMP_Ask_for_help(
364    context,
365    the_thread,
366    node,
367    _Scheduler_SMP_Insert_priority_lifo_order,
368    _Scheduler_EDF_SMP_Insert_ready_lifo,
369    _Scheduler_SMP_Insert_scheduled_lifo,
370    _Scheduler_EDF_SMP_Move_from_scheduled_to_ready,
371    _Scheduler_SMP_Get_lowest_scheduled,
372    _Scheduler_SMP_Allocate_processor_lazy
373  );
374}
375
376void _Scheduler_EDF_SMP_Update_priority(
377  const Scheduler_Control *scheduler,
378  Thread_Control          *thread,
379  Scheduler_Node          *node
380)
381{
382  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
383
384  _Scheduler_SMP_Update_priority(
385    context,
386    thread,
387    node,
388    _Scheduler_EDF_SMP_Extract_from_ready,
389    _Scheduler_EDF_SMP_Do_update,
390    _Scheduler_EDF_SMP_Enqueue_fifo,
391    _Scheduler_EDF_SMP_Enqueue_lifo,
392    _Scheduler_EDF_SMP_Enqueue_scheduled_fifo,
393    _Scheduler_EDF_SMP_Enqueue_scheduled_lifo,
394    _Scheduler_EDF_SMP_Do_ask_for_help
395  );
396}
397
398bool _Scheduler_EDF_SMP_Ask_for_help(
399  const Scheduler_Control *scheduler,
400  Thread_Control          *the_thread,
401  Scheduler_Node          *node
402)
403{
404  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
405
406  return _Scheduler_EDF_SMP_Do_ask_for_help( context, the_thread, node );
407}
408
409void _Scheduler_EDF_SMP_Reconsider_help_request(
410  const Scheduler_Control *scheduler,
411  Thread_Control          *the_thread,
412  Scheduler_Node          *node
413)
414{
415  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
416
417  _Scheduler_SMP_Reconsider_help_request(
418    context,
419    the_thread,
420    node,
421    _Scheduler_EDF_SMP_Extract_from_ready
422  );
423}
424
425void _Scheduler_EDF_SMP_Withdraw_node(
426  const Scheduler_Control *scheduler,
427  Thread_Control          *the_thread,
428  Scheduler_Node          *node,
429  Thread_Scheduler_state   next_state
430)
431{
432  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
433
434  _Scheduler_SMP_Withdraw_node(
435    context,
436    the_thread,
437    node,
438    next_state,
439    _Scheduler_EDF_SMP_Extract_from_ready,
440    _Scheduler_EDF_SMP_Get_highest_ready,
441    _Scheduler_EDF_SMP_Move_from_ready_to_scheduled,
442    _Scheduler_SMP_Allocate_processor_lazy
443  );
444}
445
446void _Scheduler_EDF_SMP_Add_processor(
447  const Scheduler_Control *scheduler,
448  Thread_Control          *idle
449)
450{
451  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
452
453  _Scheduler_SMP_Add_processor(
454    context,
455    idle,
456    _Scheduler_EDF_SMP_Has_ready,
457    _Scheduler_EDF_SMP_Enqueue_scheduled_fifo
458  );
459}
460
461Thread_Control *_Scheduler_EDF_SMP_Remove_processor(
462  const Scheduler_Control *scheduler,
463  Per_CPU_Control         *cpu
464)
465{
466  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
467
468  return _Scheduler_SMP_Remove_processor(
469    context,
470    cpu,
471    _Scheduler_EDF_SMP_Extract_from_ready,
472    _Scheduler_EDF_SMP_Enqueue_fifo
473  );
474}
475
476void _Scheduler_EDF_SMP_Yield(
477  const Scheduler_Control *scheduler,
478  Thread_Control          *thread,
479  Scheduler_Node          *node
480)
481{
482  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
483
484  _Scheduler_SMP_Yield(
485    context,
486    thread,
487    node,
488    _Scheduler_EDF_SMP_Extract_from_ready,
489    _Scheduler_EDF_SMP_Enqueue_fifo,
490    _Scheduler_EDF_SMP_Enqueue_scheduled_fifo
491  );
492}
Note: See TracBrowser for help on using the repository browser.