source: rtems/cpukit/score/src/threaddispatch.c @ 4f5baff

4.115
Last change on this file since 4f5baff was 04b5d17, checked in by Sebastian Huber <sebastian.huber@…>, on 11/28/12 at 09:45:38

score: Add API extensions post switch list

Move post switch hook from API_extensions_Control to new
API_extensions_Post_switch_control. Rename
_API_extensions_Run_postswitch() in _API_extensions_Run_post_switch().
Add _API_extensions_Post_switch_list and
_API_extensions_Add_post_switch().

  • Property mode set to 100644
File size: 5.6 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.com/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/system.h>
22#include <rtems/score/apiext.h>
23#include <rtems/score/context.h>
24#include <rtems/score/interr.h>
25#include <rtems/score/isr.h>
26#include <rtems/score/object.h>
27#include <rtems/score/priority.h>
28#include <rtems/score/states.h>
29#include <rtems/score/sysstate.h>
30#include <rtems/score/thread.h>
31#include <rtems/score/threadq.h>
32#include <rtems/score/userextimpl.h>
33#include <rtems/score/wkspace.h>
34
35#ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
36  #include <rtems/score/timestamp.h>
37#endif
38
39#if defined(RTEMS_SMP)
40  #include <rtems/score/smp.h>
41#endif
42
43void _Thread_Dispatch( void )
44{
45  Thread_Control   *executing;
46  Thread_Control   *heir;
47  ISR_Level         level;
48
49  #if defined(RTEMS_SMP)
50    /*
51     * WARNING: The SMP sequence has severe defects regarding the real-time
52     * performance.
53     *
54     * Consider the following scenario.  We have three tasks L (lowest
55     * priority), M (middle priority), and H (highest priority).  Now let a
56     * thread dispatch from M to L happen.  An interrupt occurs in
57     * _Thread_Dispatch() here:
58     *
59     * void _Thread_Dispatch( void )
60     * {
61     *   [...]
62     *
63     * post_switch:
64     *
65     *   _ISR_Enable( level );
66     *
67     *   <-- INTERRUPT
68     *   <-- AFTER INTERRUPT
69     *
70     *   _Thread_Unnest_dispatch();
71     *
72     *   _API_extensions_Run_post_switch();
73     * }
74     *
75     * The interrupt event makes task H ready.  The interrupt code will see
76     * _Thread_Dispatch_disable_level > 0 and thus doesn't perform a
77     * _Thread_Dispatch().  Now we return to position "AFTER INTERRUPT".  This
78     * means task L executes now although task H is ready!  Task H will execute
79     * once someone calls _Thread_Dispatch().
80     */
81    _Thread_Disable_dispatch();
82
83    /*
84     *  If necessary, send dispatch request to other cores.
85     */
86    _SMP_Request_other_cores_to_dispatch();
87  #endif
88
89  /*
90   *  Now determine if we need to perform a dispatch on the current CPU.
91   */
92  executing   = _Thread_Executing;
93  _ISR_Disable( level );
94  while ( _Thread_Dispatch_necessary == true ) {
95    heir = _Thread_Heir;
96    #ifndef RTEMS_SMP
97      _Thread_Dispatch_set_disable_level( 1 );
98    #endif
99    _Thread_Dispatch_necessary = false;
100    _Thread_Executing = heir;
101
102    /*
103     *  When the heir and executing are the same, then we are being
104     *  requested to do the post switch dispatching.  This is normally
105     *  done to dispatch signals.
106     */
107    if ( heir == executing )
108      goto post_switch;
109
110    /*
111     *  Since heir and executing are not the same, we need to do a real
112     *  context switch.
113     */
114#if __RTEMS_ADA__
115    executing->rtems_ada_self = rtems_ada_self;
116    rtems_ada_self = heir->rtems_ada_self;
117#endif
118    if ( heir->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE )
119      heir->cpu_time_budget = _Thread_Ticks_per_timeslice;
120
121    _ISR_Enable( level );
122
123    #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
124      {
125        Timestamp_Control uptime, ran;
126        _TOD_Get_uptime( &uptime );
127        _Timestamp_Subtract(
128          &_Thread_Time_of_last_context_switch,
129          &uptime,
130          &ran
131        );
132        _Timestamp_Add_to( &executing->cpu_time_used, &ran );
133        _Thread_Time_of_last_context_switch = uptime;
134      }
135    #else
136      {
137        _TOD_Get_uptime( &_Thread_Time_of_last_context_switch );
138        heir->cpu_time_used++;
139      }
140    #endif
141
142    /*
143     * Switch libc's task specific data.
144     */
145    if ( _Thread_libc_reent ) {
146      executing->libc_reent = *_Thread_libc_reent;
147      *_Thread_libc_reent = heir->libc_reent;
148    }
149
150    _User_extensions_Thread_switch( executing, heir );
151
152    /*
153     *  If the CPU has hardware floating point, then we must address saving
154     *  and restoring it as part of the context switch.
155     *
156     *  The second conditional compilation section selects the algorithm used
157     *  to context switch between floating point tasks.  The deferred algorithm
158     *  can be significantly better in a system with few floating point tasks
159     *  because it reduces the total number of save and restore FP context
160     *  operations.  However, this algorithm can not be used on all CPUs due
161     *  to unpredictable use of FP registers by some compilers for integer
162     *  operations.
163     */
164
165#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
166#if ( CPU_USE_DEFERRED_FP_SWITCH != TRUE )
167    if ( executing->fp_context != NULL )
168      _Context_Save_fp( &executing->fp_context );
169#endif
170#endif
171
172    _Context_Switch( &executing->Registers, &heir->Registers );
173
174#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
175#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
176    if ( (executing->fp_context != NULL) &&
177         !_Thread_Is_allocated_fp( executing ) ) {
178      if ( _Thread_Allocated_fp != NULL )
179        _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
180      _Context_Restore_fp( &executing->fp_context );
181      _Thread_Allocated_fp = executing;
182    }
183#else
184    if ( executing->fp_context != NULL )
185      _Context_Restore_fp( &executing->fp_context );
186#endif
187#endif
188
189    executing = _Thread_Executing;
190
191    _ISR_Disable( level );
192  }
193
194post_switch:
195  #ifndef RTEMS_SMP
196    _Thread_Dispatch_set_disable_level( 0 );
197  #endif
198
199  _ISR_Enable( level );
200
201  #ifdef RTEMS_SMP
202    _Thread_Unnest_dispatch();
203  #endif
204
205  _API_extensions_Run_post_switch( executing );
206}
Note: See TracBrowser for help on using the repository browser.