source: rtems/cpukit/score/src/schedulerdefaulttick.c @ 80fca28

4.115
Last change on this file since 80fca28 was 701dd96f, checked in by Sebastian Huber <sebastian.huber@…>, on 06/12/14 at 12:37:57

score: PR2181: Add _Thread_Yield()

The _Scheduler_Yield() was called by the executing thread with thread
dispatching disabled and interrupts enabled. The rtems_task_suspend()
is explicitly allowed in ISRs:

http://rtems.org/onlinedocs/doc-current/share/rtems/html/c_user/Interrupt-Manager-Directives-Allowed-from-an-ISR.html#Interrupt-Manager-Directives-Allowed-from-an-ISR

Unlike the other scheduler operations the locking was performed inside
the operation. This lead to the following race condition. Suppose a
ISR suspends the executing thread right before the yield scheduler
operation. Now the executing thread is not longer in the set of ready
threads. The typical scheduler operations did not check the thread
state and will now extract the thread again and enqueue it. This
corrupted data structures.

Add _Thread_Yield() and do the scheduler yield operation with interrupts
disabled. This has a negligible effect on the interrupt latency.

  • Property mode set to 100644
File size: 2.2 KB
Line 
1/**
2 * @file
3 *
4 * @brief Default Scheduler At Tick Handler
5 *
6 * @ingroup ScoreScheduler
7 */
8
9/*
10 *  COPYRIGHT (c) 1989-2009.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.org/license/LICENSE.
16 */
17
18#if HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <rtems/score/schedulerimpl.h>
23#include <rtems/score/threadimpl.h>
24#include <rtems/score/smp.h>
25#include <rtems/config.h>
26
27void _Scheduler_default_Tick(
28  const Scheduler_Control *scheduler,
29  Thread_Control          *executing
30)
31{
32  (void) scheduler;
33
34  #ifdef __RTEMS_USE_TICKS_FOR_STATISTICS__
35    /*
36     *  Increment the number of ticks this thread has been executing
37     */
38    executing->cpu_time_used++;
39  #endif
40
41  /*
42   *  If the thread is not preemptible or is not ready, then
43   *  just return.
44   */
45
46  if ( !executing->is_preemptible )
47    return;
48
49  if ( !_States_Is_ready( executing->current_state ) )
50    return;
51
52  /*
53   *  The cpu budget algorithm determines what happens next.
54   */
55
56  switch ( executing->budget_algorithm ) {
57    case THREAD_CPU_BUDGET_ALGORITHM_NONE:
58      break;
59
60    case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
61    #if defined(RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE)
62      case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE:
63    #endif
64      if ( (int)(--executing->cpu_time_budget) <= 0 ) {
65
66        /*
67         *  A yield performs the ready chain mechanics needed when
68         *  resetting a timeslice.  If no other thread's are ready
69         *  at the priority of the currently executing thread, then the
70         *  executing thread's timeslice is reset.  Otherwise, the
71         *  currently executing thread is placed at the rear of the
72         *  FIFO for this priority and a new heir is selected.
73         */
74        _Thread_Yield( executing );
75        executing->cpu_time_budget =
76          rtems_configuration_get_ticks_per_timeslice();
77      }
78      break;
79
80    #if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT)
81      case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT:
82        if ( --executing->cpu_time_budget == 0 )
83          (*executing->budget_callout)( executing );
84        break;
85    #endif
86  }
87}
Note: See TracBrowser for help on using the repository browser.