source: rtems/cpukit/score/src/threadhandler.c @ d4dc7c8

4.11
Last change on this file since d4dc7c8 was d4dc7c8, checked in by Jennifer Averett <Jennifer.Averett@…>, on May 26, 2011 at 6:07:07 PM

2011-05-26 Jennifer Averett <Jennifer.Averett@…>

PR 1796/cpukit

  • sapi/src/exshutdown.c, score/include/rtems/score/percpu.h, score/include/rtems/score/smp.h, score/src/smp.c, score/src/threaddispatch.c, score/src/threadhandler.c: Added SMP interprocess communications.
  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2 *  Thread Handler
3 *
4 *
5 *  COPYRIGHT (c) 1989-2011.
6 *  On-Line Applications Research Corporation (OAR).
7 *
8 *  The license and distribution terms for this file may be
9 *  found in the file LICENSE in this distribution or at
10 *  http://www.rtems.com/license/LICENSE.
11 *
12 *  $Id$
13 */
14
15#if HAVE_CONFIG_H
16#include "config.h"
17#endif
18
19#include <rtems/system.h>
20#include <rtems/score/apiext.h>
21#include <rtems/score/context.h>
22#include <rtems/score/interr.h>
23#include <rtems/score/isr.h>
24#include <rtems/score/object.h>
25#include <rtems/score/priority.h>
26#include <rtems/score/states.h>
27#include <rtems/score/sysstate.h>
28#include <rtems/score/thread.h>
29#include <rtems/score/threadq.h>
30#include <rtems/score/userext.h>
31#include <rtems/score/wkspace.h>
32
33#if defined(__AVR__)
34  #undef __USE_INIT_FINI__
35#endif
36
37#if defined(__USE_INIT_FINI__)
38  #if defined(__M32R__)
39    #define INIT_NAME __init
40  #else
41    #define INIT_NAME _init
42  #endif
43
44  extern void INIT_NAME(void);
45  #define EXECUTE_GLOBAL_CONSTRUCTORS
46#endif
47
48#if defined(__USE__MAIN__)
49  extern void _main(void);
50  #define INIT_NAME __main
51  #define EXECUTE_GLOBAL_CONSTRUCTORS
52#endif
53
54#if defined(RTEMS_SMP)
55  #include <rtems/score/smp.h>
56#endif
57
58
59/*PAGE
60 *
61 *  _Thread_Handler
62 *
63 *  This routine is the "primal" entry point for all threads.
64 *  _Context_Initialize() dummies up the thread's initial context
65 *  to cause the first Context_Switch() to jump to _Thread_Handler().
66 *
67 *  This routine is the default thread exitted error handler.  It is
68 *  returned to when a thread exits.  The configured fatal error handler
69 *  is invoked to process the exit.
70 *
71 *  NOTE:
72 *
73 *  On entry, it is assumed all interrupts are blocked and that this
74 *  routine needs to set the initial isr level.  This may or may not
75 *  actually be needed by the context switch routine and as a result
76 *  interrupts may already be at there proper level.  Either way,
77 *  setting the initial isr level properly here is safe.
78 *
79 *  Input parameters:   NONE
80 *
81 *  Output parameters:  NONE
82 */
83
84void _Thread_Handler( void )
85{
86  ISR_Level  level;
87  Thread_Control *executing;
88  #if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
89    static char doneConstructors;
90    char doneCons;
91  #endif
92
93  executing = _Thread_Executing;
94
95  /*
96   * Some CPUs need to tinker with the call frame or registers when the
97   * thread actually begins to execute for the first time.  This is a
98   * hook point where the port gets a shot at doing whatever it requires.
99   */
100  _Context_Initialization_at_thread_begin();
101
102  /*
103   * have to put level into a register for those cpu's that use
104   * inline asm here
105   */
106
107  level = executing->Start.isr_level;
108  _ISR_Set_level(level);
109
110  #if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
111    doneCons = doneConstructors;
112    doneConstructors = 1;
113  #endif
114
115  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
116    #if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
117      if ( (executing->fp_context != NULL) &&
118            !_Thread_Is_allocated_fp( executing ) ) {
119        if ( _Thread_Allocated_fp != NULL )
120          _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
121        _Thread_Allocated_fp = executing;
122      }
123    #endif
124  #endif
125
126  /*
127   * Take care that 'begin' extensions get to complete before
128   * 'switch' extensions can run.  This means must keep dispatch
129   * disabled until all 'begin' extensions complete.
130   */
131  _User_extensions_Thread_begin( executing );
132
133  /*
134   *  At this point, the dispatch disable level BETTER be 1.
135   */
136  _Thread_Enable_dispatch();
137
138  #if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
139    /*
140     *  _init could be a weak symbol and we SHOULD test it but it isn't
141     *  in any configuration I know of and it generates a warning on every
142     *  RTEMS target configuration.  --joel (12 May 2007)
143     */
144    if (!doneCons) /* && (volatile void *)_init) */ {
145      INIT_NAME ();
146   
147      #if defined(RTEMS_SMP)
148        _Thread_Disable_dispatch();
149          _SMP_Request_other_cores_to_perform_first_context_switch();
150        _Thread_Enable_dispatch();
151      #endif
152
153    }
154 #endif
155
156  if ( executing->Start.prototype == THREAD_START_NUMERIC ) {
157    executing->Wait.return_argument =
158      (*(Thread_Entry_numeric) executing->Start.entry_point)(
159        executing->Start.numeric_argument
160      );
161  }
162  #if defined(RTEMS_POSIX_API)
163    else if ( executing->Start.prototype == THREAD_START_POINTER ) {
164      executing->Wait.return_argument =
165        (*(Thread_Entry_pointer) executing->Start.entry_point)(
166          executing->Start.pointer_argument
167        );
168    }
169  #endif
170  #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
171    else if ( executing->Start.prototype == THREAD_START_BOTH_POINTER_FIRST ) {
172      executing->Wait.return_argument =
173         (*(Thread_Entry_both_pointer_first) executing->Start.entry_point)(
174           executing->Start.pointer_argument,
175           executing->Start.numeric_argument
176         );
177    }
178    else if ( executing->Start.prototype == THREAD_START_BOTH_NUMERIC_FIRST ) {
179      executing->Wait.return_argument =
180       (*(Thread_Entry_both_numeric_first) executing->Start.entry_point)(
181         executing->Start.numeric_argument,
182         executing->Start.pointer_argument
183       );
184    }
185  #endif
186
187  /*
188   *  In the switch above, the return code from the user thread body
189   *  was placed in return_argument.  This assumed that if it returned
190   *  anything (which is not supporting in all APIs), then it would be
191   *  able to fit in a (void *).
192   */
193
194  _User_extensions_Thread_exitted( executing );
195
196  _Internal_error_Occurred(
197    INTERNAL_ERROR_CORE,
198    true,
199    INTERNAL_ERROR_THREAD_EXITTED
200  );
201}
Note: See TracBrowser for help on using the repository browser.