source: rtems/cpukit/score/src/threadhandler.c @ 28bf4ca

5
Last change on this file since 28bf4ca was 28bf4ca, checked in by Sebastian Huber <sebastian.huber@…>, on 11/14/18 at 06:00:59

or1k: Support GCC 9

Close #3602.

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