1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** ThreadX Component                                                     */
16 /**                                                                       */
17 /**   Initialize                                                          */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define TX_SOURCE_CODE
23 #define TX_THREAD_SMP_SOURCE_CODE
24 
25 
26 /* Include necessary system files.  */
27 
28 #include "tx_api.h"
29 #include "tx_initialize.h"
30 #include "tx_thread.h"
31 #include "tx_timer.h"
32 
33 
34 /* Define any port-specific scheduling data structures.  */
35 
36 TX_PORT_SPECIFIC_DATA
37 
38 
39 #ifdef TX_SAFETY_CRITICAL
40 TX_SAFETY_CRITICAL_EXCEPTION_HANDLER
41 #endif
42 
43 
44 /**************************************************************************/
45 /*                                                                        */
46 /*  FUNCTION                                               RELEASE        */
47 /*                                                                        */
48 /*    _tx_initialize_kernel_enter                        PORTABLE SMP     */
49 /*                                                           6.3.0        */
50 /*  AUTHOR                                                                */
51 /*                                                                        */
52 /*    William E. Lamie, Microsoft Corporation                             */
53 /*                                                                        */
54 /*  DESCRIPTION                                                           */
55 /*                                                                        */
56 /*    This function is the first ThreadX function called during           */
57 /*    initialization.  It is called from the application's "main()"       */
58 /*    function.  It is important to note that this routine never          */
59 /*    returns.  The processing of this function is relatively simple:     */
60 /*    it calls several ThreadX initialization functions (if needed),      */
61 /*    calls the application define function, and then invokes the         */
62 /*    scheduler.                                                          */
63 /*                                                                        */
64 /*  INPUT                                                                 */
65 /*                                                                        */
66 /*    None                                                                */
67 /*                                                                        */
68 /*  OUTPUT                                                                */
69 /*                                                                        */
70 /*    None                                                                */
71 /*                                                                        */
72 /*  CALLS                                                                 */
73 /*                                                                        */
74 /*    _tx_thread_smp_high_level_initialize  SMP initialization            */
75 /*    _tx_thread_smp_current_state_set  Set system state for all cores    */
76 /*    _tx_initialize_low_level          Low-level initialization          */
77 /*    _tx_initialize_high_level         High-level initialization         */
78 /*    tx_application_define             Application define function       */
79 /*    _tx_thread_scheduler              ThreadX scheduling loop           */
80 /*                                                                        */
81 /*  CALLED BY                                                             */
82 /*                                                                        */
83 /*    main                              Application main program          */
84 /*                                                                        */
85 /*  RELEASE HISTORY                                                       */
86 /*                                                                        */
87 /*    DATE              NAME                      DESCRIPTION             */
88 /*                                                                        */
89 /*  09-30-2020      William E. Lamie        Initial Version 6.1           */
90 /*  10-31-2023      Xiuwen Cai              Modified comment(s),          */
91 /*                                            added random generator      */
92 /*                                            initialization,             */
93 /*                                            resulting in version 6.3.0  */
94 /*                                                                        */
95 /**************************************************************************/
_tx_initialize_kernel_enter(VOID)96 VOID  _tx_initialize_kernel_enter(VOID)
97 {
98 
99 ULONG   other_core_status, i;
100 
101 
102     /* Determine if the compiler has pre-initialized ThreadX.  */
103     if (_tx_thread_system_state[0] != TX_INITIALIZE_ALMOST_DONE)
104     {
105 
106         /* No, the initialization still needs to take place.  */
107 
108         /* Ensure that the system state variable is set to indicate
109            initialization is in progress.  Note that this variable is
110            later used to represent interrupt nesting.  */
111         _tx_thread_smp_current_state_set(TX_INITIALIZE_IN_PROGRESS);
112 
113         /* Call any port specific preprocessing.  */
114         TX_PORT_SPECIFIC_PRE_INITIALIZATION
115 
116         /* Invoke the low-level initialization to handle all processor specific
117            initialization issues.  */
118         _tx_initialize_low_level();
119 
120         /* Call the high-level SMP  Initialization.  */
121         _tx_thread_smp_high_level_initialize();
122 
123         /* Invoke the high-level initialization to exercise all of the
124            ThreadX components and the application's initialization
125            function.  */
126         _tx_initialize_high_level();
127 
128         /* Call any port specific post-processing.  */
129         TX_PORT_SPECIFIC_POST_INITIALIZATION
130     }
131 
132     /* Optional processing extension.  */
133     TX_INITIALIZE_KERNEL_ENTER_EXTENSION
134 
135     /* Ensure that the system state variable is set to indicate
136        initialization is in progress.  Note that this variable is
137        later used to represent interrupt nesting.  */
138     _tx_thread_system_state[0] =  TX_INITIALIZE_IN_PROGRESS;
139 
140     /* Optional random number generator initialization.  */
141     TX_INITIALIZE_RANDOM_GENERATOR_INITIALIZATION
142 
143     /* Call the application provided initialization function.  Pass the
144        first available memory address to it.  */
145     tx_application_define(_tx_initialize_unused_memory);
146 
147     /* Call any port specific pre-scheduler processing.  */
148     TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION
149 
150     /* Now wait for all cores to become ready for scheduling.  */
151     do
152     {
153 
154         /* Release the other cores from initialization.  */
155         _tx_thread_smp_release_cores_flag =  TX_TRUE;
156 
157         /* Add all the status together...  Other cores must clear their system
158            state before they they are released.  */
159         other_core_status =  ((ULONG) 0);
160 
161 #ifndef TX_THREAD_SMP_DYNAMIC_CORE_MAX
162         for (i = ((ULONG) 1); i < ((ULONG) TX_THREAD_SMP_MAX_CORES); i++)
163 #else
164         for (i = ((ULONG) 1); i < _tx_thread_smp_max_cores; i++)
165 #endif
166         {
167 
168 
169             /* Call port-specific memory synchronization primitive.  */
170             TX_PORT_SPECIFIC_MEMORY_SYNCHRONIZATION
171 
172             /* Add the states of each subsequent core.  */
173             other_core_status =  other_core_status + _tx_thread_system_state[i];
174         }
175 
176     } while (other_core_status != ((ULONG) 0));
177 
178     /* Set the system state in preparation for entering the thread
179        scheduler.  */
180     _tx_thread_system_state[0] =  TX_INITIALIZE_IS_FINISHED;
181 
182     /* Call port-specific memory synchronization primitive.  */
183     TX_PORT_SPECIFIC_MEMORY_SYNCHRONIZATION
184 
185     /* Enter the scheduling loop to start executing threads!  */
186     _tx_thread_schedule();
187 
188 #ifdef TX_SAFETY_CRITICAL
189 
190     /* If we ever get here, raise safety critical exception.  */
191     TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0);
192 #endif
193 }
194 
195