source: rtems/c/src/exec/score/src/threadhandler.c @ 48f89683

4.104.114.84.95
Last change on this file since 48f89683 was 48f89683, checked in by Joel Sherrill <joel.sherrill@…>, on May 14, 2002 at 5:45:36 PM

2001-05-14 Till Straumann <strauman@…>

  • src/threaddispatch.c, src/threadhandler.c: Per PR211 fix saving/restoring floating point context. The fpsave and fprestore routines are only used in a executing context which _is_ fp and hence has the FPU enabled. The current behavior required the FPU always to be on which is very dangerous if lazy context switching is used. [Joel Note: Some ports explicitly enabled the FPU in the FP save and restore routines to avoid this.]

The patch also makes sure (on powerpc only) that the FPU is disabled
for integer tasks. Note that this is crucial if deferred fp context
switching is used. Otherwise, fp context corruption may go undetected!
Also note that even tasks which merely push/pop FP registers to/from
the stack without modifying them still MUST be FP tasks - otherwise
(if lazy FP context switching is used), FP register corruption (of
other, FP, tasks may occur)!

Furthermore, (on PPC) by default, lazy FP context save/restore
is _disabled_.

  • Property mode set to 100644
File size: 4.3 KB
Line 
1/*
2 *  Thread Handler
3 *
4 *
5 *  COPYRIGHT (c) 1989-1999.
6 *  On-Line Applications Research Corporation (OAR).
7 *
8 *  The license and distribution terms for this file may be
9 *  found in found in the file LICENSE in this distribution or at
10 *  http://www.OARcorp.com/rtems/license.html.
11 *
12 *  $Id$
13 */
14
15#include <rtems/system.h>
16#include <rtems/score/apiext.h>
17#include <rtems/score/context.h>
18#include <rtems/score/interr.h>
19#include <rtems/score/isr.h>
20#include <rtems/score/object.h>
21#include <rtems/score/priority.h>
22#include <rtems/score/states.h>
23#include <rtems/score/sysstate.h>
24#include <rtems/score/thread.h>
25#include <rtems/score/threadq.h>
26#include <rtems/score/userext.h>
27#include <rtems/score/wkspace.h>
28
29/*PAGE
30 *
31 *  _Thread_Handler
32 *
33 *  This routine is the "primal" entry point for all threads.
34 *  _Context_Initialize() dummies up the thread's initial context
35 *  to cause the first Context_Switch() to jump to _Thread_Handler().
36 *
37 *  This routine is the default thread exitted error handler.  It is
38 *  returned to when a thread exits.  The configured fatal error handler
39 *  is invoked to process the exit.
40 *
41 *  NOTE:
42 *
43 *  On entry, it is assumed all interrupts are blocked and that this
44 *  routine needs to set the initial isr level.  This may or may not
45 *  actually be needed by the context switch routine and as a result
46 *  interrupts may already be at there proper level.  Either way,
47 *  setting the initial isr level properly here is safe.
48 * 
49 *  Currently this is only really needed for the posix port,
50 *  ref: _Context_Switch in unix/cpu.c
51 *
52 *  Input parameters:   NONE
53 *
54 *  Output parameters:  NONE
55 */
56
57void _Thread_Handler( void )
58{
59  ISR_Level  level;
60  Thread_Control *executing;
61#if defined(__USE_INIT_FINI__) || defined(__USE__MAIN__)
62  static char doneConstructors;
63  char doneCons;
64#endif
65 
66  executing = _Thread_Executing;
67 
68  /*
69   * have to put level into a register for those cpu's that use
70   * inline asm here
71   */
72 
73  level = executing->Start.isr_level;
74  _ISR_Set_level(level);
75
76#if defined(__USE_INIT_FINI__) || defined(__USE__MAIN__)
77  doneCons = doneConstructors;
78  doneConstructors = 1;
79#endif
80
81#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
82#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
83  if ( (executing->fp_context != NULL) && !_Thread_Is_allocated_fp( executing ) ) {
84    if ( _Thread_Allocated_fp != NULL )
85      _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
86    _Thread_Allocated_fp = executing;
87  }
88#endif
89#endif
90
91
92  /*
93   * Take care that 'begin' extensions get to complete before
94   * 'switch' extensions can run.  This means must keep dispatch
95   * disabled until all 'begin' extensions complete.
96   */
97 
98  _User_extensions_Thread_begin( executing );
99 
100  /*
101   *  At this point, the dispatch disable level BETTER be 1.
102   */
103
104  _Thread_Enable_dispatch();
105#if defined(__USE_INIT_FINI__)
106  if (!doneCons)
107    _init ();
108#endif
109#if defined(__USE__MAIN__)
110  if (!doneCons)
111    __main ();
112#endif
113
114 
115  switch ( executing->Start.prototype ) {
116    case THREAD_START_NUMERIC:
117      executing->Wait.return_argument = 
118        (*(Thread_Entry_numeric) executing->Start.entry_point)(
119          executing->Start.numeric_argument
120      );
121      break;
122    case THREAD_START_POINTER:
123      executing->Wait.return_argument =
124        (*(Thread_Entry_pointer) executing->Start.entry_point)(
125          executing->Start.pointer_argument
126        );
127      break;
128    case THREAD_START_BOTH_POINTER_FIRST:
129      executing->Wait.return_argument = 
130         (*(Thread_Entry_both_pointer_first) executing->Start.entry_point)( 
131           executing->Start.pointer_argument,
132           executing->Start.numeric_argument
133         );
134      break;
135    case THREAD_START_BOTH_NUMERIC_FIRST:
136      executing->Wait.return_argument = 
137         (*(Thread_Entry_both_numeric_first) executing->Start.entry_point)( 
138           executing->Start.numeric_argument,
139           executing->Start.pointer_argument
140         );
141      break;
142  }
143
144  /*
145   *  In the switch above, the return code from the user thread body
146   *  was placed in return_argument.  This assumed that if it returned
147   *  anything (which is not supporting in all APIs), then it would be
148   *  able to fit in a (void *).
149   */
150
151  _User_extensions_Thread_exitted( executing );
152
153  _Internal_error_Occurred(
154    INTERNAL_ERROR_CORE,
155    TRUE,
156    INTERNAL_ERROR_THREAD_EXITTED
157  );
158}
Note: See TracBrowser for help on using the repository browser.