source: rtems/cpukit/score/src/schedulersimplesmp.c @ 3730a07f

4.115
Last change on this file since 3730a07f was 3730a07f, checked in by Sebastian Huber <sebastian.huber@…>, on 05/13/14 at 13:08:07

score: Use Scheduler_Context for SMP scheduler

Use the basic Scheduler_Context for the general SMP scheduler operations
to avoid usage of structure offsets to get the specialized context
variants.

  • Property mode set to 100644
File size: 6.5 KB
Line 
1/**
2 * @file
3 *
4 * @brief Simple SMP Scheduler Implementation
5 *
6 * @ingroup ScoreSchedulerSMPSimple
7 */
8
9/*
10 * Copyright (c) 2013-2014 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#include <rtems/score/wkspace.h>
24
25static Scheduler_simple_SMP_Context *
26_Scheduler_simple_SMP_Get_context( const Scheduler_Control *scheduler )
27{
28  return (Scheduler_simple_SMP_Context *) scheduler->context;
29}
30
31static Scheduler_simple_SMP_Context *
32_Scheduler_simple_SMP_Get_self( Scheduler_Context *context )
33{
34  return (Scheduler_simple_SMP_Context *) context;
35}
36
37void _Scheduler_simple_SMP_Initialize( const Scheduler_Control *scheduler )
38{
39  Scheduler_simple_SMP_Context *self =
40    _Scheduler_simple_SMP_Get_context( scheduler );
41
42  _Scheduler_SMP_Initialize( &self->Base );
43  _Chain_Initialize_empty( &self->Ready );
44}
45
46bool _Scheduler_simple_SMP_Allocate(
47  const Scheduler_Control *scheduler,
48  Thread_Control          *the_thread
49)
50{
51  Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( the_thread );
52
53  _Scheduler_SMP_Node_initialize( node );
54
55  return true;
56}
57
58static Thread_Control *_Scheduler_simple_SMP_Get_highest_ready(
59  Scheduler_Context *context
60)
61{
62  Scheduler_simple_SMP_Context *self =
63    _Scheduler_simple_SMP_Get_self( context );
64  Thread_Control *highest_ready = NULL;
65  Chain_Control *ready = &self->Ready;
66
67  if ( !_Chain_Is_empty( ready ) ) {
68    highest_ready = (Thread_Control *) _Chain_First( ready );
69  }
70
71  return highest_ready;
72}
73
74static void _Scheduler_simple_SMP_Move_from_scheduled_to_ready(
75  Scheduler_Context *context,
76  Thread_Control *scheduled_to_ready
77)
78{
79  Scheduler_simple_SMP_Context *self =
80    _Scheduler_simple_SMP_Get_self( context );
81
82  _Chain_Extract_unprotected( &scheduled_to_ready->Object.Node );
83  _Scheduler_simple_Insert_priority_lifo(
84    &self->Ready,
85    scheduled_to_ready
86  );
87}
88
89static void _Scheduler_simple_SMP_Move_from_ready_to_scheduled(
90  Scheduler_Context *context,
91  Thread_Control *ready_to_scheduled
92)
93{
94  Scheduler_simple_SMP_Context *self =
95    _Scheduler_simple_SMP_Get_self( context );
96
97  _Chain_Extract_unprotected( &ready_to_scheduled->Object.Node );
98  _Scheduler_simple_Insert_priority_fifo(
99    &self->Base.Scheduled,
100    ready_to_scheduled
101  );
102}
103
104static void _Scheduler_simple_SMP_Insert_ready_lifo(
105  Scheduler_Context *context,
106  Thread_Control *thread
107)
108{
109  Scheduler_simple_SMP_Context *self =
110    _Scheduler_simple_SMP_Get_self( context );
111
112  _Chain_Insert_ordered_unprotected(
113    &self->Ready,
114    &thread->Object.Node,
115    _Scheduler_simple_Insert_priority_lifo_order
116  );
117}
118
119static void _Scheduler_simple_SMP_Insert_ready_fifo(
120  Scheduler_Context *context,
121  Thread_Control *thread
122)
123{
124  Scheduler_simple_SMP_Context *self =
125    _Scheduler_simple_SMP_Get_self( context );
126
127  _Chain_Insert_ordered_unprotected(
128    &self->Ready,
129    &thread->Object.Node,
130    _Scheduler_simple_Insert_priority_fifo_order
131  );
132}
133
134static void _Scheduler_simple_SMP_Do_extract(
135  Scheduler_Context *context,
136  Thread_Control *thread
137)
138{
139  Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread );
140
141  (void) context;
142
143  if ( node->state == SCHEDULER_SMP_NODE_SCHEDULED ) {
144    _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_IN_THE_AIR );
145  } else {
146    _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED );
147  }
148
149  _Chain_Extract_unprotected( &thread->Object.Node );
150}
151
152void _Scheduler_simple_SMP_Block(
153  const Scheduler_Control *scheduler,
154  Thread_Control *thread
155)
156{
157  Scheduler_simple_SMP_Context *self =
158    _Scheduler_simple_SMP_Get_context( scheduler );
159
160  _Scheduler_SMP_Block(
161    &self->Base.Base,
162    thread,
163    _Scheduler_simple_SMP_Do_extract,
164    _Scheduler_simple_SMP_Get_highest_ready,
165    _Scheduler_simple_SMP_Move_from_ready_to_scheduled
166  );
167}
168
169static void _Scheduler_simple_SMP_Enqueue_ordered(
170  Scheduler_Context *context,
171  Thread_Control *thread,
172  Chain_Node_order order,
173  Scheduler_SMP_Insert insert_ready,
174  Scheduler_SMP_Insert insert_scheduled
175)
176{
177  _Scheduler_SMP_Enqueue_ordered(
178    context,
179    thread,
180    order,
181    _Scheduler_simple_SMP_Get_highest_ready,
182    insert_ready,
183    insert_scheduled,
184    _Scheduler_simple_SMP_Move_from_ready_to_scheduled,
185    _Scheduler_simple_SMP_Move_from_scheduled_to_ready
186  );
187}
188
189void _Scheduler_simple_SMP_Enqueue_priority_lifo(
190  const Scheduler_Control *scheduler,
191  Thread_Control *thread
192)
193{
194  Scheduler_simple_SMP_Context *self =
195    _Scheduler_simple_SMP_Get_context( scheduler );
196
197  _Scheduler_simple_SMP_Enqueue_ordered(
198    &self->Base.Base,
199    thread,
200    _Scheduler_simple_Insert_priority_lifo_order,
201    _Scheduler_simple_SMP_Insert_ready_lifo,
202    _Scheduler_SMP_Insert_scheduled_lifo
203  );
204}
205
206void _Scheduler_simple_SMP_Enqueue_priority_fifo(
207  const Scheduler_Control *scheduler,
208  Thread_Control *thread
209)
210{
211  Scheduler_simple_SMP_Context *self =
212    _Scheduler_simple_SMP_Get_context( scheduler );
213
214  _Scheduler_simple_SMP_Enqueue_ordered(
215    &self->Base.Base,
216    thread,
217    _Scheduler_simple_Insert_priority_fifo_order,
218    _Scheduler_simple_SMP_Insert_ready_fifo,
219    _Scheduler_SMP_Insert_scheduled_fifo
220  );
221}
222
223void _Scheduler_simple_SMP_Extract(
224  const Scheduler_Control *scheduler,
225  Thread_Control *thread
226)
227{
228  Scheduler_simple_SMP_Context *self =
229    _Scheduler_simple_SMP_Get_context( scheduler );
230
231  _Scheduler_SMP_Extract(
232    &self->Base.Base,
233    thread,
234    _Scheduler_simple_SMP_Do_extract
235  );
236}
237
238void _Scheduler_simple_SMP_Yield(
239  const Scheduler_Control *scheduler,
240  Thread_Control *thread
241)
242{
243  ISR_Level level;
244
245  _ISR_Disable( level );
246
247  _Scheduler_simple_SMP_Extract( scheduler, thread );
248  _Scheduler_simple_SMP_Enqueue_priority_fifo( scheduler, thread );
249
250  _ISR_Enable( level );
251}
252
253void _Scheduler_simple_SMP_Schedule(
254  const Scheduler_Control *scheduler,
255  Thread_Control *thread
256)
257{
258  Scheduler_simple_SMP_Context *self =
259    _Scheduler_simple_SMP_Get_context( scheduler );
260
261  _Scheduler_SMP_Schedule(
262    &self->Base.Base,
263    thread,
264    _Scheduler_simple_SMP_Get_highest_ready,
265    _Scheduler_simple_SMP_Move_from_ready_to_scheduled
266  );
267}
268
269void _Scheduler_simple_SMP_Start_idle(
270  const Scheduler_Control *scheduler,
271  Thread_Control *thread,
272  Per_CPU_Control *cpu
273)
274{
275  Scheduler_simple_SMP_Context *self =
276    _Scheduler_simple_SMP_Get_context( scheduler );
277
278  _Scheduler_SMP_Start_idle( &self->Base.Base, thread, cpu );
279}
Note: See TracBrowser for help on using the repository browser.