source: rtems/cpukit/score/include/rtems/score/schedulerimpl.h @ 27270b0d

4.115
Last change on this file since 27270b0d was 27270b0d, checked in by Sebastian Huber <sebastian.huber@…>, on 04/09/14 at 08:09:39

rtems: Add task get/set scheduler

  • Property mode set to 100644
File size: 12.6 KB
Line 
1/**
2 * @file
3 *
4 * @brief Inlined Routines Associated with the Manipulation of the Scheduler
5 *
6 * This inline file contains all of the inlined routines associated with
7 * the manipulation of the scheduler.
8 */
9
10/*
11 *  Copyright (C) 2010 Gedare Bloom.
12 *  Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.org/license/LICENSE.
17 */
18
19#ifndef _RTEMS_SCORE_SCHEDULERIMPL_H
20#define _RTEMS_SCORE_SCHEDULERIMPL_H
21
22#include <rtems/score/scheduler.h>
23#include <rtems/score/cpusetimpl.h>
24#include <rtems/score/threadimpl.h>
25
26#ifdef __cplusplus
27extern "C" {
28#endif
29
30/**
31 * @addtogroup ScoreScheduler
32 */
33/**@{**/
34
35/**
36 *  @brief Initializes the scheduler to the policy chosen by the user.
37 *
38 *  This routine initializes the scheduler to the policy chosen by the user
39 *  through confdefs, or to the priority scheduler with ready chains by
40 *  default.
41 */
42void _Scheduler_Handler_initialization( void );
43
44/**
45 * The preferred method to add a new scheduler is to define the jump table
46 * entries and add a case to the _Scheduler_Initialize routine.
47 *
48 * Generic scheduling implementations that rely on the ready queue only can
49 * be found in the _Scheduler_queue_XXX functions.
50 */
51
52/*
53 * Passing the Scheduler_Control* to these functions allows for multiple
54 * scheduler's to exist simultaneously, which could be useful on an SMP
55 * system.  Then remote Schedulers may be accessible.  How to protect such
56 * accesses remains an open problem.
57 */
58
59/**
60 * @brief Scheduler schedule.
61 *
62 * This kernel routine implements the scheduling decision logic for
63 * the scheduler. It does NOT dispatch.
64 *
65 * @param[in] the_thread The thread which state changed previously.
66 */
67RTEMS_INLINE_ROUTINE void _Scheduler_Schedule(
68  const Scheduler_Control *scheduler,
69  Thread_Control          *the_thread
70)
71{
72  ( *scheduler->Operations.schedule )( scheduler, the_thread );
73}
74
75/**
76 * @brief Scheduler yield with a particular thread.
77 *
78 * This routine is invoked when a thread wishes to voluntarily transfer control
79 * of the processor to another thread.
80 *
81 * @param[in] the_thread The yielding thread.
82 */
83RTEMS_INLINE_ROUTINE void _Scheduler_Yield(
84  const Scheduler_Control *scheduler,
85  Thread_Control          *the_thread
86)
87{
88  ( *scheduler->Operations.yield )( scheduler, the_thread );
89}
90
91/**
92 * @brief Scheduler block.
93 *
94 * This routine removes @a the_thread from the scheduling decision for
95 * the scheduler. The primary task is to remove the thread from the
96 * ready queue.  It performs any necessary schedulering operations
97 * including the selection of a new heir thread.
98 */
99RTEMS_INLINE_ROUTINE void _Scheduler_Block(
100  const Scheduler_Control *scheduler,
101  Thread_Control               *the_thread
102)
103{
104  ( *scheduler->Operations.block )( scheduler, the_thread );
105}
106
107/**
108 * @brief Scheduler unblock.
109 *
110 * This routine adds @a the_thread to the scheduling decision for
111 * the scheduler.  The primary task is to add the thread to the
112 * ready queue per the schedulering policy and update any appropriate
113 * scheduling variables, for example the heir thread.
114 */
115RTEMS_INLINE_ROUTINE void _Scheduler_Unblock(
116  const Scheduler_Control *scheduler,
117  Thread_Control          *the_thread
118)
119{
120  ( *scheduler->Operations.unblock )( scheduler, the_thread );
121}
122
123/**
124 * @brief Scheduler allocate.
125 *
126 * This routine allocates @a the_thread->scheduler
127 */
128RTEMS_INLINE_ROUTINE bool _Scheduler_Allocate(
129  const Scheduler_Control *scheduler,
130  Thread_Control          *the_thread
131)
132{
133  return ( *scheduler->Operations.allocate )( scheduler, the_thread );
134}
135
136/**
137 * @brief Scheduler free.
138 *
139 * This routine frees @a the_thread->scheduler
140 */
141RTEMS_INLINE_ROUTINE void _Scheduler_Free(
142  const Scheduler_Control *scheduler,
143  Thread_Control          *the_thread
144)
145{
146  ( *scheduler->Operations.free )( scheduler, the_thread );
147}
148
149/**
150 * @brief Scheduler update.
151 *
152 * This routine updates @a the_thread->scheduler
153 */
154RTEMS_INLINE_ROUTINE void _Scheduler_Update(
155  const Scheduler_Control *scheduler,
156  Thread_Control          *the_thread
157)
158{
159  ( *scheduler->Operations.update )( scheduler, the_thread );
160}
161
162/**
163 * @brief Scheduler enqueue.
164 *
165 * This routine enqueue @a the_thread->scheduler
166 */
167RTEMS_INLINE_ROUTINE void _Scheduler_Enqueue(
168  const Scheduler_Control *scheduler,
169  Thread_Control          *the_thread
170)
171{
172  ( *scheduler->Operations.enqueue )( scheduler, the_thread );
173}
174
175/**
176 * @brief Scheduler enqueue first.
177 *
178 * This routine enqueue_first @a the_thread->scheduler
179 */
180RTEMS_INLINE_ROUTINE void _Scheduler_Enqueue_first(
181  const Scheduler_Control *scheduler,
182  Thread_Control          *the_thread
183)
184{
185  ( *scheduler->Operations.enqueue_first )( scheduler, the_thread );
186}
187
188/**
189 * @brief Scheduler extract.
190 *
191 * This routine extract @a the_thread->scheduler
192 */
193RTEMS_INLINE_ROUTINE void _Scheduler_Extract(
194  const Scheduler_Control *scheduler,
195  Thread_Control          *the_thread
196)
197{
198  ( *scheduler->Operations.extract )( scheduler, the_thread );
199}
200
201/**
202 * @brief Scheduler priority compare.
203 *
204 * This routine compares two priorities.
205 */
206RTEMS_INLINE_ROUTINE int _Scheduler_Priority_compare(
207  const Scheduler_Control *scheduler,
208  Priority_Control         p1,
209  Priority_Control         p2
210)
211{
212  return ( *scheduler->Operations.priority_compare )( p1, p2 );
213}
214
215/**
216 * @brief Scheduler release job.
217 *
218 * This routine is called when a new period of task is issued.
219 */
220RTEMS_INLINE_ROUTINE void _Scheduler_Release_job(
221  const Scheduler_Control *scheduler,
222  Thread_Control          *the_thread,
223  uint32_t                 length
224)
225{
226  ( *scheduler->Operations.release_job )( scheduler, the_thread, length );
227}
228
229/**
230 * @brief Scheduler method invoked at each clock tick.
231 *
232 * This method is invoked at each clock tick to allow the scheduler
233 * implementation to perform any activities required.  For the
234 * scheduler which support standard RTEMS features, this includes
235 * time-slicing management.
236 */
237RTEMS_INLINE_ROUTINE void _Scheduler_Tick(
238  const Scheduler_Control *scheduler
239)
240{
241  ( *scheduler->Operations.tick )( scheduler );
242}
243
244/**
245 * @brief Starts the idle thread for a particular processor.
246 *
247 * @param[in,out] the_thread The idle thread for the processor.
248 * @parma[in,out] processor The processor for the idle thread.
249 *
250 * @see _Thread_Create_idle().
251 */
252RTEMS_INLINE_ROUTINE void _Scheduler_Start_idle(
253  const Scheduler_Control *scheduler,
254  Thread_Control          *the_thread,
255  Per_CPU_Control         *cpu
256)
257{
258  ( *scheduler->Operations.start_idle )( scheduler, the_thread, cpu );
259}
260
261#if defined(__RTEMS_HAVE_SYS_CPUSET_H__)
262
263RTEMS_INLINE_ROUTINE void _Scheduler_Get_processor_set(
264  const Scheduler_Control *scheduler,
265  size_t                   cpusetsize,
266  cpu_set_t               *cpuset
267)
268{
269  uint32_t cpu_count = _SMP_Get_processor_count();
270  uint32_t cpu_index;
271
272  (void) scheduler;
273
274  CPU_ZERO_S( cpusetsize, cpuset );
275
276  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
277    CPU_SET_S( (int) cpu_index, cpusetsize, cpuset );
278  }
279}
280
281RTEMS_INLINE_ROUTINE bool _Scheduler_default_Get_affinity_body(
282  const Scheduler_Control *scheduler,
283  Thread_Control          *the_thread,
284  size_t                   cpusetsize,
285  cpu_set_t               *cpuset
286)
287{
288  (void) the_thread;
289
290  _Scheduler_Get_processor_set( scheduler, cpusetsize, cpuset );
291
292  return true;
293}
294
295bool _Scheduler_Get_affinity(
296  const Scheduler_Control *scheduler,
297  Thread_Control          *the_thread,
298  size_t                   cpusetsize,
299  cpu_set_t               *cpuset
300);
301
302RTEMS_INLINE_ROUTINE bool _Scheduler_default_Set_affinity_body(
303  const Scheduler_Control *scheduler,
304  Thread_Control          *the_thread,
305  size_t                   cpusetsize,
306  const cpu_set_t         *cpuset
307)
308{
309  size_t   cpu_max   = _CPU_set_Maximum_CPU_count( cpusetsize );
310  uint32_t cpu_count = _SMP_Get_processor_count();
311  uint32_t cpu_index;
312  bool     ok = true;
313
314  (void) scheduler;
315  (void) the_thread;
316
317  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
318    ok = ok && CPU_ISSET_S( (int) cpu_index, cpusetsize, cpuset );
319  }
320
321  for ( ; cpu_index < cpu_max ; ++cpu_index ) {
322    ok = ok && !CPU_ISSET_S( (int) cpu_index, cpusetsize, cpuset );
323  }
324
325  return ok;
326}
327
328bool _Scheduler_Set_affinity(
329  const Scheduler_Control *scheduler,
330  Thread_Control          *the_thread,
331  size_t                   cpusetsize,
332  const cpu_set_t         *cpuset
333);
334
335#endif /* defined(__RTEMS_HAVE_SYS_CPUSET_H__) */
336
337RTEMS_INLINE_ROUTINE void _Scheduler_Update_heir(
338  Thread_Control *heir,
339  bool force_dispatch
340)
341{
342  Thread_Control *executing = _Thread_Executing;
343
344  _Thread_Heir = heir;
345
346  if ( executing != heir && ( force_dispatch || executing->is_preemptible ) )
347    _Thread_Dispatch_necessary = true;
348}
349
350RTEMS_INLINE_ROUTINE void _Scheduler_Generic_block(
351  const Scheduler_Control *scheduler,
352  Thread_Control          *the_thread,
353  void                  ( *extract )(
354                             const Scheduler_Control *,
355                             Thread_Control * ),
356  void                  ( *schedule )(
357                             const Scheduler_Control *,
358                             Thread_Control *,
359                             bool )
360)
361{
362  ( *extract )( scheduler, the_thread );
363
364  /* TODO: flash critical section? */
365
366  if ( _Thread_Is_executing( the_thread ) || _Thread_Is_heir( the_thread ) ) {
367    ( *schedule )( scheduler, the_thread, true );
368  }
369}
370
371/**
372 * @brief Returns true if @p1 encodes a lower priority than @a p2 in the
373 * intuitive sense of priority.
374 */
375RTEMS_INLINE_ROUTINE bool _Scheduler_Is_priority_lower_than(
376  const Scheduler_Control *scheduler,
377  Priority_Control         p1,
378  Priority_Control         p2
379)
380{
381  return _Scheduler_Priority_compare( scheduler, p1,  p2 ) < 0;
382}
383
384/**
385 * @brief Returns true if @p1 encodes a higher priority than @a p2 in the
386 * intuitive sense of priority.
387 */
388RTEMS_INLINE_ROUTINE bool _Scheduler_Is_priority_higher_than(
389  const Scheduler_Control *scheduler,
390  Priority_Control         p1,
391  Priority_Control         p2
392)
393{
394  return _Scheduler_Priority_compare( scheduler, p1,  p2 ) > 0;
395}
396
397/**
398 * @brief Returns the priority encoding @a p1 or @a p2 with the higher priority
399 * in the intuitive sense of priority.
400 */
401RTEMS_INLINE_ROUTINE Priority_Control _Scheduler_Highest_priority_of_two(
402  const Scheduler_Control *scheduler,
403  Priority_Control         p1,
404  Priority_Control         p2
405)
406{
407  return _Scheduler_Is_priority_higher_than( scheduler, p1, p2 ) ? p1 : p2;
408}
409
410/**
411 * @brief Sets the thread priority to @a priority if it is higher than the
412 * current priority of the thread in the intuitive sense of priority.
413 */
414RTEMS_INLINE_ROUTINE void _Scheduler_Set_priority_if_higher(
415  const Scheduler_Control *scheduler,
416  Thread_Control          *the_thread,
417  Priority_Control         priority
418)
419{
420  Priority_Control current = the_thread->current_priority;
421
422  if ( _Scheduler_Is_priority_higher_than( scheduler, priority, current ) ) {
423    _Thread_Set_priority( the_thread, priority );
424  }
425}
426
427/**
428 * @brief Changes the thread priority to @a priority if it is higher than the
429 * current priority of the thread in the intuitive sense of priority.
430 */
431RTEMS_INLINE_ROUTINE void _Scheduler_Change_priority_if_higher(
432  const Scheduler_Control *scheduler,
433  Thread_Control          *the_thread,
434  Priority_Control         priority,
435  bool                     prepend_it
436)
437{
438  Priority_Control current = the_thread->current_priority;
439
440  if ( _Scheduler_Is_priority_higher_than( scheduler, priority, current ) ) {
441    _Thread_Change_priority( the_thread, priority, prepend_it );
442  }
443}
444
445RTEMS_INLINE_ROUTINE const Scheduler_Control *_Scheduler_Get(
446  Thread_Control *the_thread
447)
448{
449  (void) the_thread;
450
451  return &_Scheduler_Table[ 0 ];
452}
453
454RTEMS_INLINE_ROUTINE bool _Scheduler_Set(
455  const Scheduler_Control *scheduler,
456  Thread_Control          *the_thread
457)
458{
459  bool ok;
460
461  (void) scheduler;
462
463  if ( _States_Is_dormant( the_thread->current_state ) ) {
464    ok = true;
465  } else {
466    ok = false;
467  }
468
469  return ok;
470}
471
472RTEMS_INLINE_ROUTINE Objects_Id _Scheduler_Build_id( uint32_t scheduler_index )
473{
474  return _Objects_Build_id(
475    OBJECTS_FAKE_OBJECTS_API,
476    OBJECTS_FAKE_OBJECTS_SCHEDULERS,
477    _Objects_Local_node,
478    scheduler_index + 1
479  );
480}
481
482RTEMS_INLINE_ROUTINE bool _Scheduler_Get_by_id(
483  Objects_Id                id,
484  const Scheduler_Control **scheduler
485)
486{
487  uint32_t minimum_id = _Scheduler_Build_id( 0 );
488  uint32_t index = id - minimum_id;
489
490  *scheduler = &_Scheduler_Table[ index ];
491
492  return index < _Scheduler_Count;
493}
494
495RTEMS_INLINE_ROUTINE uint32_t _Scheduler_Get_index(
496  const Scheduler_Control *scheduler
497)
498{
499  return (uint32_t) (scheduler - &_Scheduler_Table[ 0 ]);
500}
501
502/** @} */
503
504#ifdef __cplusplus
505}
506#endif
507
508#endif
509/* end of include file */
Note: See TracBrowser for help on using the repository browser.