source: rtems/cpukit/score/src/threadhandler.c @ 2afb22b

5
Last change on this file since 2afb22b was a7dcef97, checked in by Sebastian Huber <sebastian.huber@…>, on 11/17/17 at 05:36:54

score: Simplify global construction

Update #3243.

  • Property mode set to 100644
File size: 4.2 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.org/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/assert.h>
23#include <rtems/score/interr.h>
24#include <rtems/score/isrlevel.h>
25#include <rtems/score/userextimpl.h>
26
27/*
28 *  Conditional magic to determine what style of C++ constructor
29 *  initialization this target and compiler version uses.
30 */
31#if defined(__USE_INIT_FINI__)
32  #if defined(__ARM_EABI__)
33    #define INIT_NAME __libc_init_array
34  #else
35    #define INIT_NAME _init
36  #endif
37
38  extern void INIT_NAME(void);
39  #define EXECUTE_GLOBAL_CONSTRUCTORS
40#endif
41
42#if defined(__USE__MAIN__)
43  extern void __main(void);
44  #define INIT_NAME __main
45  #define EXECUTE_GLOBAL_CONSTRUCTORS
46#endif
47
48Objects_Id _Thread_Global_constructor;
49
50static void _Thread_Global_construction( Thread_Control *executing )
51{
52#if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
53  if ( executing->Object.id == _Thread_Global_constructor ) {
54    /*
55     * Prevent double construction in case the initialization thread is deleted
56     * and then recycled.  There is not need for extra synchronization since
57     * this variable is set during the sequential system boot procedure.
58     */
59    _Thread_Global_constructor = 0;
60
61    /*
62     *  _init could be a weak symbol and we SHOULD test it but it isn't
63     *  in any configuration I know of and it generates a warning on every
64     *  RTEMS target configuration.  --joel (12 May 2007)
65     */
66    INIT_NAME();
67  }
68#endif
69}
70
71void _Thread_Handler( void )
72{
73  Thread_Control  *executing;
74  ISR_Level        level;
75  Per_CPU_Control *cpu_self;
76
77  /*
78   * Some CPUs need to tinker with the call frame or registers when the
79   * thread actually begins to execute for the first time.  This is a
80   * hook point where the port gets a shot at doing whatever it requires.
81   */
82  _Context_Initialization_at_thread_begin();
83  executing = _Thread_Executing;
84
85  /*
86   * have to put level into a register for those cpu's that use
87   * inline asm here
88   */
89  level = executing->Start.isr_level;
90  _ISR_Set_level( level );
91
92  /*
93   * Initialize the floating point context because we do not come
94   * through _Thread_Dispatch on our first invocation. So the normal
95   * code path for performing the FP context switch is not hit.
96   */
97  _Thread_Restore_fp( executing );
98
99  /*
100   * Do not use the level of the thread control block, since it has a
101   * different format.
102   */
103  _ISR_Local_disable( level );
104
105  /*
106   *  At this point, the dispatch disable level BETTER be 1.
107   */
108  cpu_self = _Per_CPU_Get();
109  _Assert( cpu_self->thread_dispatch_disable_level == 1 );
110
111  /*
112   * Make sure we lose no thread dispatch necessary update and execute the
113   * post-switch actions.  As a side-effect change the thread dispatch level
114   * from one to zero.  Do not use _Thread_Enable_dispatch() since there is no
115   * valid thread dispatch necessary indicator in this context.
116   */
117  _Thread_Do_dispatch( cpu_self, level );
118
119  /*
120   * Invoke the thread begin extensions in the context of the thread entry
121   * function with thread dispatching enabled.  This enables use of dynamic
122   * memory allocation, creation of POSIX keys and use of C++ thread local
123   * storage.  Blocking synchronization primitives are allowed also.
124   */
125  _User_extensions_Thread_begin( executing );
126
127  _Thread_Global_construction( executing );
128
129  /*
130   *  RTEMS supports multiple APIs and each API can define a different
131   *  thread/task prototype. The following code supports invoking the
132   *  user thread entry point using the prototype expected.
133   */
134  ( *executing->Start.Entry.adaptor )( executing );
135
136  /*
137   *  In the call above, the return code from the user thread body which return
138   *  something was placed in return_argument.  This assumed that if it
139   *  returned anything (which is not supporting in all APIs), then it would be
140   *  able to fit in a (void *).
141   */
142
143  _User_extensions_Thread_exitted( executing );
144
145  _Internal_error( INTERNAL_ERROR_THREAD_EXITTED );
146}
Note: See TracBrowser for help on using the repository browser.