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

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

score: Introduce scheduler nodes

Rename scheduler per-thread information into scheduler nodes using
Scheduler_Node as the base type. Use inheritance for specialized
schedulers.

Move the scheduler specific states from the thread control block into
the scheduler node structure.

Validate the SMP scheduler node state transitions in case RTEMS_DEBUG is
defined.

  • 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_Self_from_SMP_base( Scheduler_SMP_Context *smp_base )
33{
34  return (Scheduler_simple_SMP_Context *)
35    ( (char *) smp_base - offsetof( Scheduler_simple_SMP_Context, Base ) );
36}
37
38void _Scheduler_simple_smp_Initialize( const Scheduler_Control *scheduler )
39{
40  Scheduler_simple_SMP_Context *self =
41    _Scheduler_simple_SMP_Get_context( scheduler );
42
43  _Scheduler_SMP_Initialize( &self->Base );
44  _Chain_Initialize_empty( &self->Ready );
45}
46
47bool _Scheduler_simple_smp_Allocate(
48  const Scheduler_Control *scheduler,
49  Thread_Control          *the_thread
50)
51{
52  Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( the_thread );
53
54  _Scheduler_SMP_Node_initialize( node );
55
56  return true;
57}
58
59static Thread_Control *_Scheduler_simple_smp_Get_highest_ready(
60  Scheduler_SMP_Context *smp_base
61)
62{
63  Scheduler_simple_SMP_Context *self =
64    _Scheduler_simple_SMP_Self_from_SMP_base( smp_base );
65  Thread_Control *highest_ready = NULL;
66  Chain_Control *ready = &self->Ready;
67
68  if ( !_Chain_Is_empty( ready ) ) {
69    highest_ready = (Thread_Control *) _Chain_First( ready );
70  }
71
72  return highest_ready;
73}
74
75static void _Scheduler_simple_smp_Move_from_scheduled_to_ready(
76  Scheduler_SMP_Context *smp_base,
77  Thread_Control *scheduled_to_ready
78)
79{
80  Scheduler_simple_SMP_Context *self =
81    _Scheduler_simple_SMP_Self_from_SMP_base( smp_base );
82
83  _Chain_Extract_unprotected( &scheduled_to_ready->Object.Node );
84  _Scheduler_simple_Insert_priority_lifo(
85    &self->Ready,
86    scheduled_to_ready
87  );
88}
89
90static void _Scheduler_simple_smp_Move_from_ready_to_scheduled(
91  Scheduler_SMP_Context *smp_base,
92  Thread_Control *ready_to_scheduled
93)
94{
95  _Chain_Extract_unprotected( &ready_to_scheduled->Object.Node );
96  _Scheduler_simple_Insert_priority_fifo(
97    &smp_base->Scheduled,
98    ready_to_scheduled
99  );
100}
101
102static void _Scheduler_simple_smp_Insert_ready_lifo(
103  Scheduler_SMP_Context *smp_base,
104  Thread_Control *thread
105)
106{
107  Scheduler_simple_SMP_Context *self =
108    _Scheduler_simple_SMP_Self_from_SMP_base( smp_base );
109
110  _Chain_Insert_ordered_unprotected(
111    &self->Ready,
112    &thread->Object.Node,
113    _Scheduler_simple_Insert_priority_lifo_order
114  );
115}
116
117static void _Scheduler_simple_smp_Insert_ready_fifo(
118  Scheduler_SMP_Context *smp_base,
119  Thread_Control *thread
120)
121{
122  Scheduler_simple_SMP_Context *self =
123    _Scheduler_simple_SMP_Self_from_SMP_base( smp_base );
124
125  _Chain_Insert_ordered_unprotected(
126    &self->Ready,
127    &thread->Object.Node,
128    _Scheduler_simple_Insert_priority_fifo_order
129  );
130}
131
132static void _Scheduler_simple_smp_Do_extract(
133  Scheduler_SMP_Context *smp_base,
134  Thread_Control *thread
135)
136{
137  Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread );
138
139  (void) smp_base;
140
141  if ( node->state == SCHEDULER_SMP_NODE_SCHEDULED ) {
142    _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_IN_THE_AIR );
143  } else {
144    _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED );
145  }
146
147  _Chain_Extract_unprotected( &thread->Object.Node );
148}
149
150void _Scheduler_simple_smp_Block(
151  const Scheduler_Control *scheduler,
152  Thread_Control *thread
153)
154{
155  Scheduler_simple_SMP_Context *self =
156    _Scheduler_simple_SMP_Get_context( scheduler );
157
158  _Scheduler_SMP_Block(
159    &self->Base,
160    thread,
161    _Scheduler_simple_smp_Do_extract,
162    _Scheduler_simple_smp_Get_highest_ready,
163    _Scheduler_simple_smp_Move_from_ready_to_scheduled
164  );
165}
166
167static void _Scheduler_simple_smp_Enqueue_ordered(
168  Scheduler_SMP_Context *smp_base,
169  Thread_Control *thread,
170  Chain_Node_order order,
171  Scheduler_SMP_Insert insert_ready,
172  Scheduler_SMP_Insert insert_scheduled
173)
174{
175  _Scheduler_SMP_Enqueue_ordered(
176    smp_base,
177    thread,
178    order,
179    _Scheduler_simple_smp_Get_highest_ready,
180    insert_ready,
181    insert_scheduled,
182    _Scheduler_simple_smp_Move_from_ready_to_scheduled,
183    _Scheduler_simple_smp_Move_from_scheduled_to_ready
184  );
185}
186
187void _Scheduler_simple_smp_Enqueue_priority_lifo(
188  const Scheduler_Control *scheduler,
189  Thread_Control *thread
190)
191{
192  Scheduler_simple_SMP_Context *self =
193    _Scheduler_simple_SMP_Get_context( scheduler );
194
195  _Scheduler_simple_smp_Enqueue_ordered(
196    &self->Base,
197    thread,
198    _Scheduler_simple_Insert_priority_lifo_order,
199    _Scheduler_simple_smp_Insert_ready_lifo,
200    _Scheduler_SMP_Insert_scheduled_lifo
201  );
202}
203
204void _Scheduler_simple_smp_Enqueue_priority_fifo(
205  const Scheduler_Control *scheduler,
206  Thread_Control *thread
207)
208{
209  Scheduler_simple_SMP_Context *self =
210    _Scheduler_simple_SMP_Get_context( scheduler );
211
212  _Scheduler_simple_smp_Enqueue_ordered(
213    &self->Base,
214    thread,
215    _Scheduler_simple_Insert_priority_fifo_order,
216    _Scheduler_simple_smp_Insert_ready_fifo,
217    _Scheduler_SMP_Insert_scheduled_fifo
218  );
219}
220
221void _Scheduler_simple_smp_Extract(
222  const Scheduler_Control *scheduler,
223  Thread_Control *thread
224)
225{
226  Scheduler_simple_SMP_Context *self =
227    _Scheduler_simple_SMP_Get_context( scheduler );
228
229  _Scheduler_SMP_Extract(
230    &self->Base,
231    thread,
232    _Scheduler_simple_smp_Do_extract
233  );
234}
235
236void _Scheduler_simple_smp_Yield(
237  const Scheduler_Control *scheduler,
238  Thread_Control *thread
239)
240{
241  ISR_Level level;
242
243  _ISR_Disable( level );
244
245  _Scheduler_simple_smp_Extract( scheduler, thread );
246  _Scheduler_simple_smp_Enqueue_priority_fifo( scheduler, thread );
247
248  _ISR_Enable( level );
249}
250
251void _Scheduler_simple_smp_Schedule(
252  const Scheduler_Control *scheduler,
253  Thread_Control *thread
254)
255{
256  Scheduler_simple_SMP_Context *self =
257    _Scheduler_simple_SMP_Get_context( scheduler );
258
259  _Scheduler_SMP_Schedule(
260    &self->Base,
261    thread,
262    _Scheduler_simple_smp_Get_highest_ready,
263    _Scheduler_simple_smp_Move_from_ready_to_scheduled
264  );
265}
266
267void _Scheduler_simple_smp_Start_idle(
268  const Scheduler_Control *scheduler,
269  Thread_Control *thread,
270  Per_CPU_Control *cpu
271)
272{
273  Scheduler_simple_SMP_Context *self =
274    _Scheduler_simple_SMP_Get_context( scheduler );
275
276  _Scheduler_SMP_Start_idle( &self->Base, thread, cpu );
277}
Note: See TracBrowser for help on using the repository browser.