source: rtems/cpukit/score/src/threaddispatch.c @ c499856

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 5.2 KB
Line 
1/**
2 * @file
3 *
4 * @brief Dispatch Thread
5 * @ingroup ScoreThread
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2009.
10 *  On-Line Applications Research Corporation (OAR).
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/threaddispatch.h>
22#include <rtems/score/apiext.h>
23#include <rtems/score/assert.h>
24#include <rtems/score/isr.h>
25#include <rtems/score/threadimpl.h>
26#include <rtems/score/todimpl.h>
27#include <rtems/score/userextimpl.h>
28#include <rtems/score/wkspace.h>
29
30void _Thread_Dispatch( void )
31{
32  Per_CPU_Control  *per_cpu;
33  Thread_Control   *executing;
34  Thread_Control   *heir;
35  ISR_Level         level;
36
37#if defined( RTEMS_SMP )
38  _ISR_Disable_without_giant( level );
39#endif
40
41  per_cpu = _Per_CPU_Get();
42  _Assert( per_cpu->thread_dispatch_disable_level == 0 );
43  _Profiling_Thread_dispatch_disable( per_cpu, 0 );
44  per_cpu->thread_dispatch_disable_level = 1;
45
46#if defined( RTEMS_SMP )
47  _ISR_Enable_without_giant( level );
48#endif
49
50  /*
51   *  Now determine if we need to perform a dispatch on the current CPU.
52   */
53  executing = per_cpu->executing;
54  _Per_CPU_ISR_disable_and_acquire( per_cpu, level );
55#if defined( RTEMS_SMP )
56  /*
57   * On SMP the complete context switch must be atomic with respect to one
58   * processor.  The scheduler must obtain the per-CPU lock to check if a
59   * thread is executing and to update the heir.  This ensures that a thread
60   * cannot execute on more than one processor at a time.  See also
61   * _Thread_Handler() since _Context_switch() may branch to this function.
62   */
63  if ( per_cpu->dispatch_necessary ) {
64#else
65  while ( per_cpu->dispatch_necessary ) {
66#endif
67    heir = per_cpu->heir;
68    per_cpu->dispatch_necessary = false;
69    per_cpu->executing = heir;
70#if defined( RTEMS_SMP )
71    executing->is_executing = false;
72    heir->is_executing = true;
73#endif
74
75    /*
76     *  When the heir and executing are the same, then we are being
77     *  requested to do the post switch dispatching.  This is normally
78     *  done to dispatch signals.
79     */
80    if ( heir == executing )
81      goto post_switch;
82
83    /*
84     *  Since heir and executing are not the same, we need to do a real
85     *  context switch.
86     */
87#if __RTEMS_ADA__
88    executing->rtems_ada_self = rtems_ada_self;
89    rtems_ada_self = heir->rtems_ada_self;
90#endif
91    if ( heir->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE )
92      heir->cpu_time_budget = _Thread_Ticks_per_timeslice;
93
94#if !defined( RTEMS_SMP )
95    _ISR_Enable( level );
96#endif
97
98    #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
99      _Thread_Update_cpu_time_used(
100        executing,
101        &per_cpu->time_of_last_context_switch
102      );
103    #else
104      {
105        _TOD_Get_uptime( &per_cpu->time_of_last_context_switch );
106        heir->cpu_time_used++;
107      }
108    #endif
109
110#if !defined(__DYNAMIC_REENT__)
111    /*
112     * Switch libc's task specific data.
113     */
114    if ( _Thread_libc_reent ) {
115      executing->libc_reent = *_Thread_libc_reent;
116      *_Thread_libc_reent = heir->libc_reent;
117    }
118#endif
119
120    _User_extensions_Thread_switch( executing, heir );
121
122    /*
123     *  If the CPU has hardware floating point, then we must address saving
124     *  and restoring it as part of the context switch.
125     *
126     *  The second conditional compilation section selects the algorithm used
127     *  to context switch between floating point tasks.  The deferred algorithm
128     *  can be significantly better in a system with few floating point tasks
129     *  because it reduces the total number of save and restore FP context
130     *  operations.  However, this algorithm can not be used on all CPUs due
131     *  to unpredictable use of FP registers by some compilers for integer
132     *  operations.
133     */
134
135#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
136#if ( CPU_USE_DEFERRED_FP_SWITCH != TRUE )
137    if ( executing->fp_context != NULL )
138      _Context_Save_fp( &executing->fp_context );
139#endif
140#endif
141
142    _Context_Switch( &executing->Registers, &heir->Registers );
143
144#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
145#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
146    if ( (executing->fp_context != NULL) &&
147         !_Thread_Is_allocated_fp( executing ) ) {
148      if ( _Thread_Allocated_fp != NULL )
149        _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
150      _Context_Restore_fp( &executing->fp_context );
151      _Thread_Allocated_fp = executing;
152    }
153#else
154    if ( executing->fp_context != NULL )
155      _Context_Restore_fp( &executing->fp_context );
156#endif
157#endif
158
159    /*
160     * We have to obtain this value again after the context switch since the
161     * heir thread may have migrated from another processor.  Values from the
162     * stack or non-volatile registers reflect the old execution environment.
163     */
164    per_cpu = _Per_CPU_Get();
165
166#if !defined( RTEMS_SMP )
167    _ISR_Disable( level );
168#endif
169  }
170
171post_switch:
172  _Assert( per_cpu->thread_dispatch_disable_level == 1 );
173  per_cpu->thread_dispatch_disable_level = 0;
174  _Profiling_Thread_dispatch_enable( per_cpu, 0 );
175
176  _Per_CPU_Release_and_ISR_enable( per_cpu, level );
177
178  _API_extensions_Run_post_switch( executing );
179}
Note: See TracBrowser for help on using the repository browser.