source: rtems/cpukit/score/src/threadhandler.c @ 80cf60e

5
Last change on this file since 80cf60e was 80cf60e, checked in by Sebastian Huber <sebastian.huber@…>, on 04/15/20 at 07:48:32

Canonicalize config.h include

Use the following variant which was already used by most source files:

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

  • Property mode set to 100644
File size: 4.3 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief Thread Handler
5 *  @ingroup RTEMSScoreThread
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#ifdef 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#if defined(RTEMS_SMP)
101  _User_extensions_Thread_switch( NULL, executing );
102#endif
103
104  /*
105   * Do not use the level of the thread control block, since it has a
106   * different format.
107   */
108  _ISR_Local_disable( level );
109
110  /*
111   *  At this point, the dispatch disable level BETTER be 1.
112   */
113  cpu_self = _Per_CPU_Get();
114  _Assert( cpu_self->thread_dispatch_disable_level == 1 );
115
116  /*
117   * Make sure we lose no thread dispatch necessary update and execute the
118   * post-switch actions.  As a side-effect change the thread dispatch level
119   * from one to zero.  Do not use _Thread_Enable_dispatch() since there is no
120   * valid thread dispatch necessary indicator in this context.
121   */
122  _Thread_Do_dispatch( cpu_self, level );
123
124  /*
125   * Invoke the thread begin extensions in the context of the thread entry
126   * function with thread dispatching enabled.  This enables use of dynamic
127   * memory allocation, creation of POSIX keys and use of C++ thread local
128   * storage.  Blocking synchronization primitives are allowed also.
129   */
130  _User_extensions_Thread_begin( executing );
131
132  _Thread_Global_construction( executing );
133
134  /*
135   *  RTEMS supports multiple APIs and each API can define a different
136   *  thread/task prototype. The following code supports invoking the
137   *  user thread entry point using the prototype expected.
138   */
139  ( *executing->Start.Entry.adaptor )( executing );
140
141  /*
142   *  In the call above, the return code from the user thread body which return
143   *  something was placed in return_argument.  This assumed that if it
144   *  returned anything (which is not supporting in all APIs), then it would be
145   *  able to fit in a (void *).
146   */
147
148  _User_extensions_Thread_exitted( executing );
149
150  _Internal_error( INTERNAL_ERROR_THREAD_EXITTED );
151}
Note: See TracBrowser for help on using the repository browser.