source: rtems/cpukit/score/src/schedulerprioritysmp.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: 8.2 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/schedulersmpimpl.h>
30#include <rtems/score/wkspace.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->context;
36}
37
38static Scheduler_priority_SMP_Context *
39_Scheduler_priority_SMP_Self_from_SMP_base( Scheduler_SMP_Context *smp_base )
40{
41  return (Scheduler_priority_SMP_Context *)
42    ( (char *) smp_base
43      - offsetof( Scheduler_priority_SMP_Context, Base ) );
44}
45
46static Scheduler_priority_SMP_Node *_Scheduler_priority_SMP_Node_get(
47  Thread_Control *thread
48)
49{
50  return (Scheduler_priority_SMP_Node *) _Scheduler_Node_get( thread );
51}
52
53void _Scheduler_priority_SMP_Initialize( const Scheduler_Control *scheduler )
54{
55  Scheduler_priority_SMP_Context *self =
56    _Scheduler_priority_SMP_Get_context( scheduler );
57
58  _Scheduler_SMP_Initialize( &self->Base );
59  _Priority_bit_map_Initialize( &self->Bit_map );
60  _Scheduler_priority_Ready_queue_initialize( &self->Ready[ 0 ] );
61}
62
63bool _Scheduler_priority_SMP_Allocate(
64  const Scheduler_Control *scheduler,
65  Thread_Control *thread
66)
67{
68  Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread );
69
70  _Scheduler_SMP_Node_initialize( node );
71
72  return true;
73}
74
75void _Scheduler_priority_SMP_Update(
76  const Scheduler_Control *scheduler,
77  Thread_Control *thread
78)
79{
80  Scheduler_priority_SMP_Context *self =
81    _Scheduler_priority_SMP_Get_context( scheduler );
82  Scheduler_priority_SMP_Node *node =
83    _Scheduler_priority_SMP_Node_get( thread );
84
85  _Scheduler_priority_Ready_queue_update(
86    thread,
87    &node->Ready_queue,
88    &self->Bit_map,
89    &self->Ready[ 0 ]
90  );
91}
92
93static Thread_Control *_Scheduler_priority_SMP_Get_highest_ready(
94  Scheduler_SMP_Context *smp_base
95)
96{
97  Scheduler_priority_SMP_Context *self =
98    _Scheduler_priority_SMP_Self_from_SMP_base( smp_base );
99  Thread_Control *highest_ready = NULL;
100
101  if ( !_Priority_bit_map_Is_empty( &self->Bit_map ) ) {
102    highest_ready = _Scheduler_priority_Ready_queue_first(
103      &self->Bit_map,
104      &self->Ready[ 0 ]
105    );
106  }
107
108  return highest_ready;
109}
110
111static void _Scheduler_priority_SMP_Move_from_scheduled_to_ready(
112  Scheduler_SMP_Context *smp_base,
113  Thread_Control *scheduled_to_ready
114)
115{
116  Scheduler_priority_SMP_Context *self =
117    _Scheduler_priority_SMP_Self_from_SMP_base( smp_base );
118  Scheduler_priority_SMP_Node *node =
119    _Scheduler_priority_SMP_Node_get( scheduled_to_ready );
120
121  _Chain_Extract_unprotected( &scheduled_to_ready->Object.Node );
122  _Scheduler_priority_Ready_queue_enqueue_first(
123    scheduled_to_ready,
124    &node->Ready_queue,
125    &self->Bit_map
126  );
127}
128
129static void _Scheduler_priority_SMP_Move_from_ready_to_scheduled(
130  Scheduler_SMP_Context *smp_base,
131  Thread_Control *ready_to_scheduled
132)
133{
134  Scheduler_priority_SMP_Context *self =
135    _Scheduler_priority_SMP_Self_from_SMP_base( smp_base );
136  Scheduler_priority_SMP_Node *node =
137    _Scheduler_priority_SMP_Node_get( ready_to_scheduled );
138
139  _Scheduler_priority_Ready_queue_extract(
140    ready_to_scheduled,
141    &node->Ready_queue,
142    &self->Bit_map
143  );
144  _Scheduler_simple_Insert_priority_fifo(
145    &self->Base.Scheduled,
146    ready_to_scheduled
147  );
148}
149
150static void _Scheduler_priority_SMP_Insert_ready_lifo(
151  Scheduler_SMP_Context *smp_base,
152  Thread_Control *thread
153)
154{
155  Scheduler_priority_SMP_Context *self =
156    _Scheduler_priority_SMP_Self_from_SMP_base( smp_base );
157  Scheduler_priority_SMP_Node *node =
158    _Scheduler_priority_SMP_Node_get( thread );
159
160  _Scheduler_priority_Ready_queue_enqueue(
161    thread,
162    &node->Ready_queue,
163    &self->Bit_map
164  );
165}
166
167static void _Scheduler_priority_SMP_Insert_ready_fifo(
168  Scheduler_SMP_Context *smp_base,
169  Thread_Control *thread
170)
171{
172  Scheduler_priority_SMP_Context *self =
173    _Scheduler_priority_SMP_Self_from_SMP_base( smp_base );
174  Scheduler_priority_SMP_Node *node =
175    _Scheduler_priority_SMP_Node_get( thread );
176
177  _Scheduler_priority_Ready_queue_enqueue_first(
178    thread,
179    &node->Ready_queue,
180    &self->Bit_map
181  );
182}
183
184static void _Scheduler_priority_SMP_Do_extract(
185  Scheduler_SMP_Context *smp_base,
186  Thread_Control *thread
187)
188{
189  Scheduler_priority_SMP_Context *self =
190    _Scheduler_priority_SMP_Self_from_SMP_base( smp_base );
191  Scheduler_priority_SMP_Node *node =
192    _Scheduler_priority_SMP_Node_get( thread );
193
194  if ( node->Base.state == SCHEDULER_SMP_NODE_SCHEDULED ) {
195    _Scheduler_SMP_Node_change_state(
196      &node->Base,
197      SCHEDULER_SMP_NODE_IN_THE_AIR
198    );
199    _Chain_Extract_unprotected( &thread->Object.Node );
200  } else {
201    _Scheduler_SMP_Node_change_state(
202      &node->Base,
203      SCHEDULER_SMP_NODE_BLOCKED
204    );
205    _Scheduler_priority_Ready_queue_extract(
206      thread,
207      &node->Ready_queue,
208      &self->Bit_map
209    );
210  }
211}
212
213void _Scheduler_priority_SMP_Block(
214  const Scheduler_Control *scheduler,
215  Thread_Control *thread
216)
217{
218  Scheduler_priority_SMP_Context *self =
219    _Scheduler_priority_SMP_Get_context( scheduler );
220
221  _Scheduler_SMP_Block(
222    &self->Base,
223    thread,
224    _Scheduler_priority_SMP_Do_extract,
225    _Scheduler_priority_SMP_Get_highest_ready,
226    _Scheduler_priority_SMP_Move_from_ready_to_scheduled
227  );
228}
229
230static void _Scheduler_priority_SMP_Enqueue_ordered(
231  Scheduler_SMP_Context *self,
232  Thread_Control *thread,
233  Chain_Node_order order,
234  Scheduler_SMP_Insert insert_ready,
235  Scheduler_SMP_Insert insert_scheduled
236)
237{
238  _Scheduler_SMP_Enqueue_ordered(
239    self,
240    thread,
241    order,
242    _Scheduler_priority_SMP_Get_highest_ready,
243    insert_ready,
244    insert_scheduled,
245    _Scheduler_priority_SMP_Move_from_ready_to_scheduled,
246    _Scheduler_priority_SMP_Move_from_scheduled_to_ready
247  );
248}
249
250void _Scheduler_priority_SMP_Enqueue_lifo(
251  const Scheduler_Control *scheduler,
252  Thread_Control *thread
253)
254{
255  Scheduler_priority_SMP_Context *self =
256    _Scheduler_priority_SMP_Get_context( scheduler );
257
258  _Scheduler_priority_SMP_Enqueue_ordered(
259    &self->Base,
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
267void _Scheduler_priority_SMP_Enqueue_fifo(
268  const Scheduler_Control *scheduler,
269  Thread_Control *thread
270)
271{
272  Scheduler_priority_SMP_Context *self =
273    _Scheduler_priority_SMP_Get_context( scheduler );
274
275  _Scheduler_priority_SMP_Enqueue_ordered(
276    &self->Base,
277    thread,
278    _Scheduler_simple_Insert_priority_fifo_order,
279    _Scheduler_priority_SMP_Insert_ready_fifo,
280    _Scheduler_SMP_Insert_scheduled_fifo
281  );
282}
283
284void _Scheduler_priority_SMP_Extract(
285  const Scheduler_Control *scheduler,
286  Thread_Control *thread
287)
288{
289  Scheduler_priority_SMP_Context *self =
290    _Scheduler_priority_SMP_Get_context( scheduler );
291
292  _Scheduler_SMP_Extract(
293    &self->Base,
294    thread,
295    _Scheduler_priority_SMP_Do_extract
296  );
297}
298
299void _Scheduler_priority_SMP_Yield(
300  const Scheduler_Control *scheduler,
301  Thread_Control *thread
302)
303{
304  ISR_Level level;
305
306  _ISR_Disable( level );
307
308  _Scheduler_priority_SMP_Extract( scheduler, thread );
309  _Scheduler_priority_SMP_Enqueue_fifo( scheduler, thread );
310
311  _ISR_Enable( level );
312}
313
314void _Scheduler_priority_SMP_Schedule(
315  const Scheduler_Control *scheduler,
316  Thread_Control *thread
317)
318{
319  Scheduler_priority_SMP_Context *self =
320    _Scheduler_priority_SMP_Get_context( scheduler );
321
322  _Scheduler_SMP_Schedule(
323    &self->Base,
324    thread,
325    _Scheduler_priority_SMP_Get_highest_ready,
326    _Scheduler_priority_SMP_Move_from_ready_to_scheduled
327  );
328}
329
330void _Scheduler_priority_SMP_Start_idle(
331  const Scheduler_Control *scheduler,
332  Thread_Control *thread,
333  Per_CPU_Control *cpu
334)
335{
336  Scheduler_priority_SMP_Context *self =
337    _Scheduler_priority_SMP_Get_context( scheduler );
338
339  _Scheduler_SMP_Start_idle( &self->Base, thread, cpu );
340}
Note: See TracBrowser for help on using the repository browser.