source: rtems/cpukit/score/src/threadhandler.c @ 5618c37a

4.115
Last change on this file since 5618c37a was 5618c37a, checked in by Sebastian Huber <sebastian.huber@…>, on 07/24/13 at 13:14:48

score: Create thread implementation header

Move implementation specific parts of thread.h and thread.inl into new
header file threadimpl.h. The thread.h contains now only the
application visible API.

Remove superfluous header file includes from various files.

  • Property mode set to 100644
File size: 5.0 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief Thread Handler
5 *  @ingroup ScoreThread
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2012.
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/score/threadimpl.h>
22#include <rtems/score/interr.h>
23#include <rtems/score/isrlevel.h>
24#include <rtems/score/userextimpl.h>
25
26/*
27 *  Conditional magic to determine what style of C++ constructor
28 *  initialization this target and compiler version uses.
29 */
30#if defined(__USE_INIT_FINI__)
31  #if defined(__M32R__)
32    #define INIT_NAME __init
33  #elif defined(__ARM_EABI__)
34    #define INIT_NAME __libc_init_array
35  #else
36    #define INIT_NAME _init
37  #endif
38
39  extern void INIT_NAME(void);
40  #define EXECUTE_GLOBAL_CONSTRUCTORS
41#endif
42
43#if defined(__USE__MAIN__)
44  extern void __main(void);
45  #define INIT_NAME __main
46  #define EXECUTE_GLOBAL_CONSTRUCTORS
47#endif
48
49void _Thread_Handler( void )
50{
51  ISR_Level  level;
52  Thread_Control *executing;
53  #if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
54    static bool doneConstructors;
55    bool doCons;
56  #endif
57
58  executing = _Thread_Executing;
59
60  /*
61   * Some CPUs need to tinker with the call frame or registers when the
62   * thread actually begins to execute for the first time.  This is a
63   * hook point where the port gets a shot at doing whatever it requires.
64   */
65  _Context_Initialization_at_thread_begin();
66
67  /*
68   * have to put level into a register for those cpu's that use
69   * inline asm here
70   */
71  level = executing->Start.isr_level;
72  _ISR_Set_level(level);
73
74  #if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
75    #if defined(RTEMS_MULTIPROCESSING)
76      doCons = !doneConstructors
77        && _Objects_Get_API( executing->Object.id ) != OBJECTS_INTERNAL_API;
78      if (doCons)
79        doneConstructors = true;
80    #else
81      doCons = !doneConstructors;
82      doneConstructors = true;
83    #endif
84  #endif
85
86  /*
87   * Initialize the floating point context because we do not come
88   * through _Thread_Dispatch on our first invocation. So the normal
89   * code path for performing the FP context switch is not hit.
90   */
91  #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
92    #if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
93      if ( (executing->fp_context != NULL) &&
94            !_Thread_Is_allocated_fp( executing ) ) {
95        if ( _Thread_Allocated_fp != NULL )
96          _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
97        _Thread_Allocated_fp = executing;
98      }
99    #endif
100  #endif
101
102  /*
103   * Take care that 'begin' extensions get to complete before
104   * 'switch' extensions can run.  This means must keep dispatch
105   * disabled until all 'begin' extensions complete.
106   */
107  _User_extensions_Thread_begin( executing );
108
109  /*
110   *  At this point, the dispatch disable level BETTER be 1.
111   */
112  _Thread_Enable_dispatch();
113
114  #if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
115    /*
116     *  _init could be a weak symbol and we SHOULD test it but it isn't
117     *  in any configuration I know of and it generates a warning on every
118     *  RTEMS target configuration.  --joel (12 May 2007)
119     */
120    if (doCons) /* && (volatile void *)_init) */ {
121      INIT_NAME ();
122    }
123 #endif
124
125  /*
126   *  RTEMS supports multiple APIs and each API can define a different
127   *  thread/task prototype. The following code supports invoking the
128   *  user thread entry point using the prototype expected.
129   */
130  if ( executing->Start.prototype == THREAD_START_NUMERIC ) {
131    executing->Wait.return_argument =
132      (*(Thread_Entry_numeric) executing->Start.entry_point)(
133        executing->Start.numeric_argument
134      );
135  }
136  #if defined(RTEMS_POSIX_API)
137    else if ( executing->Start.prototype == THREAD_START_POINTER ) {
138      executing->Wait.return_argument =
139        (*(Thread_Entry_pointer) executing->Start.entry_point)(
140          executing->Start.pointer_argument
141        );
142    }
143  #endif
144  #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
145    else if ( executing->Start.prototype == THREAD_START_BOTH_POINTER_FIRST ) {
146      executing->Wait.return_argument =
147         (*(Thread_Entry_both_pointer_first) executing->Start.entry_point)(
148           executing->Start.pointer_argument,
149           executing->Start.numeric_argument
150         );
151    }
152    else if ( executing->Start.prototype == THREAD_START_BOTH_NUMERIC_FIRST ) {
153      executing->Wait.return_argument =
154       (*(Thread_Entry_both_numeric_first) executing->Start.entry_point)(
155         executing->Start.numeric_argument,
156         executing->Start.pointer_argument
157       );
158    }
159  #endif
160
161  /*
162   *  In the switch above, the return code from the user thread body
163   *  was placed in return_argument.  This assumed that if it returned
164   *  anything (which is not supporting in all APIs), then it would be
165   *  able to fit in a (void *).
166   */
167
168  _User_extensions_Thread_exitted( executing );
169
170  _Internal_error_Occurred(
171    INTERNAL_ERROR_CORE,
172    true,
173    INTERNAL_ERROR_THREAD_EXITTED
174  );
175}
Note: See TracBrowser for help on using the repository browser.