source: rtems/cpukit/score/src/schedulersimplesmp.c @ 5c3d250

4.115
Last change on this file since 5c3d250 was 5c3d250, checked in by Sebastian Huber <sebastian.huber@…>, on 07/04/14 at 12:34:23

score: Implement scheduler helping protocol

The following scheduler operations return a thread in need for help

  • unblock,
  • change priority, and
  • yield.

A thread in need for help is a thread that encounters a scheduler state
change from scheduled to ready or a thread that cannot be scheduled in
an unblock operation. Such a thread can ask threads which depend on
resources owned by this thread for help.

Add a new ask for help scheduler operation. This operation is used by
_Scheduler_Ask_for_help() to help threads in need for help returned by
the operations mentioned above. This operation is also used by
_Scheduler_Thread_change_resource_root() in case the root of a resource
sub-tree changes. A use case is the ownership change of a resource.

In case it is not possible to schedule a thread in need for help, then
the corresponding scheduler node will be placed into the set of ready
scheduler nodes of the scheduler instance. Once a state change from
ready to scheduled happens for this scheduler node it may be used to
schedule the thread in need for help.

  • Property mode set to 100644
File size: 9.2 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
24static Scheduler_simple_SMP_Context *
25_Scheduler_simple_SMP_Get_context( const Scheduler_Control *scheduler )
26{
27  return (Scheduler_simple_SMP_Context *) _Scheduler_Get_context( scheduler );
28}
29
30static Scheduler_simple_SMP_Context *
31_Scheduler_simple_SMP_Get_self( Scheduler_Context *context )
32{
33  return (Scheduler_simple_SMP_Context *) context;
34}
35
36void _Scheduler_simple_SMP_Initialize( const Scheduler_Control *scheduler )
37{
38  Scheduler_simple_SMP_Context *self =
39    _Scheduler_simple_SMP_Get_context( scheduler );
40
41  _Scheduler_SMP_Initialize( &self->Base );
42  _Chain_Initialize_empty( &self->Ready );
43}
44
45void _Scheduler_simple_SMP_Node_initialize(
46  const Scheduler_Control *scheduler,
47  Thread_Control          *the_thread
48)
49{
50  Scheduler_SMP_Node *node = _Scheduler_SMP_Thread_get_own_node( the_thread );
51
52  _Scheduler_SMP_Node_initialize( node, the_thread );
53}
54
55static void _Scheduler_simple_SMP_Do_update(
56  Scheduler_Context *context,
57  Scheduler_Node    *node_to_update,
58  Priority_Control   new_priority
59)
60{
61  Scheduler_SMP_Node *node = _Scheduler_SMP_Node_downcast( node_to_update );
62
63  (void) context;
64
65  _Scheduler_SMP_Node_update_priority( node, new_priority );
66}
67
68void _Scheduler_simple_SMP_Update_priority(
69  const Scheduler_Control *scheduler,
70  Thread_Control          *thread,
71  Priority_Control         new_priority
72)
73{
74  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
75  Scheduler_Node *node = _Scheduler_Thread_get_node( thread );
76
77  _Scheduler_simple_SMP_Do_update( context, node, new_priority );
78}
79
80static Scheduler_Node *_Scheduler_simple_SMP_Get_highest_ready(
81  Scheduler_Context *context,
82  Scheduler_Node    *node
83)
84{
85  Scheduler_simple_SMP_Context *self =
86    _Scheduler_simple_SMP_Get_self( context );
87
88  (void) node;
89
90  return (Scheduler_Node *) _Chain_First( &self->Ready );
91}
92
93static void _Scheduler_simple_SMP_Move_from_scheduled_to_ready(
94  Scheduler_Context *context,
95  Scheduler_Node    *scheduled_to_ready
96)
97{
98  Scheduler_simple_SMP_Context *self =
99    _Scheduler_simple_SMP_Get_self( context );
100
101  _Chain_Extract_unprotected( &scheduled_to_ready->Node );
102  _Chain_Insert_ordered_unprotected(
103    &self->Ready,
104    &scheduled_to_ready->Node,
105    _Scheduler_SMP_Insert_priority_lifo_order
106  );
107}
108
109static void _Scheduler_simple_SMP_Move_from_ready_to_scheduled(
110  Scheduler_Context *context,
111  Scheduler_Node    *ready_to_scheduled
112)
113{
114  Scheduler_simple_SMP_Context *self =
115    _Scheduler_simple_SMP_Get_self( context );
116
117  _Chain_Extract_unprotected( &ready_to_scheduled->Node );
118  _Chain_Insert_ordered_unprotected(
119    &self->Base.Scheduled,
120    &ready_to_scheduled->Node,
121    _Scheduler_SMP_Insert_priority_fifo_order
122  );
123}
124
125static void _Scheduler_simple_SMP_Insert_ready_lifo(
126  Scheduler_Context *context,
127  Scheduler_Node    *node_to_insert
128)
129{
130  Scheduler_simple_SMP_Context *self =
131    _Scheduler_simple_SMP_Get_self( context );
132
133  _Chain_Insert_ordered_unprotected(
134    &self->Ready,
135    &node_to_insert->Node,
136    _Scheduler_SMP_Insert_priority_lifo_order
137  );
138}
139
140static void _Scheduler_simple_SMP_Insert_ready_fifo(
141  Scheduler_Context *context,
142  Scheduler_Node    *node_to_insert
143)
144{
145  Scheduler_simple_SMP_Context *self =
146    _Scheduler_simple_SMP_Get_self( context );
147
148  _Chain_Insert_ordered_unprotected(
149    &self->Ready,
150    &node_to_insert->Node,
151    _Scheduler_SMP_Insert_priority_fifo_order
152  );
153}
154
155static void _Scheduler_simple_SMP_Extract_from_ready(
156  Scheduler_Context *context,
157  Scheduler_Node    *node_to_extract
158)
159{
160  (void) context;
161
162  _Chain_Extract_unprotected( &node_to_extract->Node );
163}
164
165static Thread_Control *_Scheduler_simple_SMP_Get_idle_thread(
166  Scheduler_Context *context
167)
168{
169  return _Scheduler_SMP_Get_idle_thread(
170    context,
171    _Scheduler_simple_SMP_Extract_from_ready
172  );
173}
174
175static void _Scheduler_simple_SMP_Release_idle_thread(
176  Scheduler_Context *context,
177  Thread_Control    *idle
178)
179{
180  _Scheduler_SMP_Release_idle_thread(
181    context,
182    idle,
183    _Scheduler_simple_SMP_Insert_ready_fifo
184  );
185}
186
187void _Scheduler_simple_SMP_Block(
188  const Scheduler_Control *scheduler,
189  Thread_Control *thread
190)
191{
192  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
193
194  _Scheduler_SMP_Block(
195    context,
196    thread,
197    _Scheduler_simple_SMP_Extract_from_ready,
198    _Scheduler_simple_SMP_Get_highest_ready,
199    _Scheduler_simple_SMP_Move_from_ready_to_scheduled,
200    _Scheduler_SMP_Allocate_processor_lazy,
201    _Scheduler_simple_SMP_Get_idle_thread
202  );
203}
204
205static Thread_Control *_Scheduler_simple_SMP_Enqueue_ordered(
206  Scheduler_Context    *context,
207  Scheduler_Node       *node,
208  Thread_Control       *needs_help,
209  Chain_Node_order      order,
210  Scheduler_SMP_Insert  insert_ready,
211  Scheduler_SMP_Insert  insert_scheduled
212)
213{
214  return _Scheduler_SMP_Enqueue_ordered(
215    context,
216    node,
217    needs_help,
218    order,
219    insert_ready,
220    insert_scheduled,
221    _Scheduler_simple_SMP_Move_from_scheduled_to_ready,
222    _Scheduler_SMP_Get_lowest_scheduled,
223    _Scheduler_SMP_Allocate_processor_lazy,
224    _Scheduler_simple_SMP_Release_idle_thread
225  );
226}
227
228static Thread_Control *_Scheduler_simple_SMP_Enqueue_lifo(
229  Scheduler_Context *context,
230  Scheduler_Node    *node,
231  Thread_Control    *needs_help
232)
233{
234  return _Scheduler_simple_SMP_Enqueue_ordered(
235    context,
236    node,
237    needs_help,
238    _Scheduler_SMP_Insert_priority_lifo_order,
239    _Scheduler_simple_SMP_Insert_ready_lifo,
240    _Scheduler_SMP_Insert_scheduled_lifo
241  );
242}
243
244static Thread_Control *_Scheduler_simple_SMP_Enqueue_fifo(
245  Scheduler_Context *context,
246  Scheduler_Node    *node,
247  Thread_Control    *needs_help
248)
249{
250  return _Scheduler_simple_SMP_Enqueue_ordered(
251    context,
252    node,
253    needs_help,
254    _Scheduler_SMP_Insert_priority_fifo_order,
255    _Scheduler_simple_SMP_Insert_ready_fifo,
256    _Scheduler_SMP_Insert_scheduled_fifo
257  );
258}
259
260static Thread_Control *_Scheduler_simple_SMP_Enqueue_scheduled_ordered(
261  Scheduler_Context *context,
262  Scheduler_Node *node,
263  Chain_Node_order order,
264  Scheduler_SMP_Insert insert_ready,
265  Scheduler_SMP_Insert insert_scheduled
266)
267{
268  return _Scheduler_SMP_Enqueue_scheduled_ordered(
269    context,
270    node,
271    order,
272    _Scheduler_simple_SMP_Extract_from_ready,
273    _Scheduler_simple_SMP_Get_highest_ready,
274    insert_ready,
275    insert_scheduled,
276    _Scheduler_simple_SMP_Move_from_ready_to_scheduled,
277    _Scheduler_SMP_Allocate_processor_lazy,
278    _Scheduler_simple_SMP_Get_idle_thread,
279    _Scheduler_simple_SMP_Release_idle_thread
280  );
281}
282
283static Thread_Control *_Scheduler_simple_SMP_Enqueue_scheduled_lifo(
284  Scheduler_Context *context,
285  Scheduler_Node *node
286)
287{
288  return _Scheduler_simple_SMP_Enqueue_scheduled_ordered(
289    context,
290    node,
291    _Scheduler_SMP_Insert_priority_lifo_order,
292    _Scheduler_simple_SMP_Insert_ready_lifo,
293    _Scheduler_SMP_Insert_scheduled_lifo
294  );
295}
296
297static Thread_Control *_Scheduler_simple_SMP_Enqueue_scheduled_fifo(
298  Scheduler_Context *context,
299  Scheduler_Node *node
300)
301{
302  return _Scheduler_simple_SMP_Enqueue_scheduled_ordered(
303    context,
304    node,
305    _Scheduler_SMP_Insert_priority_fifo_order,
306    _Scheduler_simple_SMP_Insert_ready_fifo,
307    _Scheduler_SMP_Insert_scheduled_fifo
308  );
309}
310
311Thread_Control *_Scheduler_simple_SMP_Unblock(
312  const Scheduler_Control *scheduler,
313  Thread_Control *thread
314)
315{
316  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
317
318  return _Scheduler_SMP_Unblock(
319    context,
320    thread,
321    _Scheduler_simple_SMP_Enqueue_fifo,
322    _Scheduler_simple_SMP_Release_idle_thread
323  );
324}
325
326Thread_Control *_Scheduler_simple_SMP_Change_priority(
327  const Scheduler_Control *scheduler,
328  Thread_Control          *thread,
329  Priority_Control         new_priority,
330  bool                     prepend_it
331)
332{
333  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
334
335  return _Scheduler_SMP_Change_priority(
336    context,
337    thread,
338    new_priority,
339    prepend_it,
340    _Scheduler_simple_SMP_Extract_from_ready,
341    _Scheduler_simple_SMP_Do_update,
342    _Scheduler_simple_SMP_Enqueue_fifo,
343    _Scheduler_simple_SMP_Enqueue_lifo,
344    _Scheduler_simple_SMP_Enqueue_scheduled_fifo,
345    _Scheduler_simple_SMP_Enqueue_scheduled_lifo
346  );
347}
348
349Thread_Control *_Scheduler_simple_SMP_Ask_for_help(
350  const Scheduler_Control *scheduler,
351  Thread_Control          *offers_help,
352  Thread_Control          *needs_help
353)
354{
355  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
356
357  return _Scheduler_SMP_Ask_for_help(
358    context,
359    offers_help,
360    needs_help,
361    _Scheduler_simple_SMP_Enqueue_fifo,
362    _Scheduler_simple_SMP_Release_idle_thread
363  );
364}
365
366Thread_Control *_Scheduler_simple_SMP_Yield(
367  const Scheduler_Control *scheduler,
368  Thread_Control *thread
369)
370{
371  Scheduler_Context *context = _Scheduler_Get_context( scheduler );
372
373  return _Scheduler_SMP_Yield(
374    context,
375    thread,
376    _Scheduler_simple_SMP_Extract_from_ready,
377    _Scheduler_simple_SMP_Enqueue_fifo,
378    _Scheduler_simple_SMP_Enqueue_scheduled_fifo
379  );
380}
Note: See TracBrowser for help on using the repository browser.