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 /**   Module Manager                                                      */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define TX_SOURCE_CODE
23 
24 #include "tx_api.h"
25 #include "tx_mutex.h"
26 #include "tx_queue.h"
27 #include "tx_thread.h"
28 #include "txm_module.h"
29 
30 
31 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _txm_module_manager_start                           PORTABLE C      */
36 /*                                                           6.1.3        */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Scott Larson, Microsoft Corporation                                 */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function starts execution of the specified module.             */
44 /*                                                                        */
45 /*  INPUT                                                                 */
46 /*                                                                        */
47 /*    module_instance                   Module instance pointer           */
48 /*                                                                        */
49 /*  OUTPUT                                                                */
50 /*                                                                        */
51 /*    status                            Completion status                 */
52 /*                                                                        */
53 /*  CALLS                                                                 */
54 /*                                                                        */
55 /*    _txm_module_manager_thread_create     Module thread create          */
56 /*    _tx_mutex_get                         Get protection mutex          */
57 /*    _tx_mutex_put                         Release protection mutex      */
58 /*    _tx_queue_create                      Create module callback queue  */
59 /*    _tx_queue_delete                      Delete module callback queue  */
60 /*    _tx_thread_resume                     Resume start thread           */
61 /*                                                                        */
62 /*  CALLED BY                                                             */
63 /*                                                                        */
64 /*    Application code                                                    */
65 /*                                                                        */
66 /*  RELEASE HISTORY                                                       */
67 /*                                                                        */
68 /*    DATE              NAME                      DESCRIPTION             */
69 /*                                                                        */
70 /*  09-30-2020      Scott Larson            Initial Version 6.1           */
71 /*  12-31-2020      Scott Larson            Modified comment(s),          */
72 /*                                            resulting in version 6.1.3  */
73 /*                                                                        */
74 /**************************************************************************/
_txm_module_manager_start(TXM_MODULE_INSTANCE * module_instance)75 UINT  _txm_module_manager_start(TXM_MODULE_INSTANCE *module_instance)
76 {
77 
78 UINT    status;
79 
80 
81     /* Determine if the module manager has not been initialized yet.  */
82     if (_txm_module_manager_ready != TX_TRUE)
83     {
84 
85         /* Module manager has not been initialized.  */
86         return(TX_NOT_AVAILABLE);
87     }
88 
89     /* Determine if the module is valid.  */
90     if (module_instance == TX_NULL)
91     {
92 
93         /* Invalid module pointer.  */
94         return(TX_PTR_ERROR);
95     }
96 
97     /* Get module manager protection mutex.  */
98     _tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
99 
100     /* Determine if the module instance is valid.  */
101     if (module_instance -> txm_module_instance_id != TXM_MODULE_ID)
102     {
103 
104         /* Release the protection mutex.  */
105         _tx_mutex_put(&_txm_module_manager_mutex);
106 
107         /* Invalid module pointer.  */
108         return(TX_PTR_ERROR);
109     }
110 
111     /* Determine if the module instance is in the loaded state.  */
112     if ((module_instance -> txm_module_instance_state != TXM_MODULE_LOADED) && (module_instance -> txm_module_instance_state != TXM_MODULE_STOPPED))
113     {
114 
115         /* Release the protection mutex.  */
116         _tx_mutex_put(&_txm_module_manager_mutex);
117 
118         /* Return error if the module is not ready.  */
119         return(TX_START_ERROR);
120     }
121 
122     /* Check the priorities of the start/stop and callback request threads. */
123     if (module_instance -> txm_module_instance_start_stop_priority < module_instance -> txm_module_instance_maximum_priority ||
124         module_instance -> txm_module_instance_callback_priority < module_instance -> txm_module_instance_maximum_priority)
125     {
126 
127         /* Release the protection mutex.  */
128         _tx_mutex_put(&_txm_module_manager_mutex);
129 
130         /* At least one thread has an invalid priority.  */
131         return(TX_PRIORITY_ERROR);
132     }
133 
134     /* Create the module's callback request queue.  */
135     status = _tx_queue_create(&(module_instance -> txm_module_instance_callback_request_queue), "Module Callback Request Queue", (sizeof(TXM_MODULE_CALLBACK_MESSAGE)/sizeof(ULONG)),
136                               module_instance -> txm_module_instance_callback_request_queue_area, sizeof(module_instance -> txm_module_instance_callback_request_queue_area));
137 
138     /* Determine if there was an error.  */
139     if (status)
140     {
141 
142         /* Release the protection mutex.  */
143         _tx_mutex_put(&_txm_module_manager_mutex);
144 
145         /* Return error if the module is not ready.  */
146         return(TX_START_ERROR);
147     }
148 
149     /* Create the module start thread.  */
150     status =  _txm_module_manager_thread_create(&(module_instance -> txm_module_instance_start_stop_thread),
151                                                 "Module Start Thread",
152                                                 module_instance -> txm_module_instance_shell_entry_function,
153                                                 module_instance -> txm_module_instance_start_thread_entry,
154                                                 module_instance -> txm_module_instance_application_module_id,
155                                                 module_instance -> txm_module_instance_start_stop_stack_start_address,
156                                                 module_instance -> txm_module_instance_start_stop_stack_size,
157                                                 (UINT) module_instance -> txm_module_instance_start_stop_priority,
158                                                 (UINT) module_instance -> txm_module_instance_start_stop_priority,
159                                                 TXM_MODULE_TIME_SLICE,
160                                                 TX_DONT_START,
161                                                 sizeof(TX_THREAD),
162                                                 module_instance);
163 
164     /* Determine if the thread create was successful.  */
165     if (status != TX_SUCCESS)
166     {
167 
168         /* Delete the callback notification queue.  */
169         _tx_queue_delete(&(module_instance -> txm_module_instance_callback_request_queue));
170 
171         /* Release the protection mutex.  */
172         _tx_mutex_put(&_txm_module_manager_mutex);
173 
174         /* Return the error status.  */
175         return(status);
176     }
177 
178     /* Create the module callback thread.  */
179     status =  _txm_module_manager_thread_create(&(module_instance -> txm_module_instance_callback_request_thread),
180                                                 "Module Callback Request Thread",
181                                                 module_instance -> txm_module_instance_shell_entry_function,
182                                                 module_instance -> txm_module_instance_callback_request_thread_entry,
183                                                 module_instance -> txm_module_instance_application_module_id,
184                                                 module_instance -> txm_module_instance_callback_stack_start_address,
185                                                 module_instance -> txm_module_instance_callback_stack_size,
186                                                 (UINT) module_instance -> txm_module_instance_callback_priority,
187                                                 (UINT) module_instance -> txm_module_instance_callback_priority,
188                                                 TX_NO_TIME_SLICE,
189                                                 TX_DONT_START,
190                                                 sizeof(TX_THREAD),
191                                                 module_instance);
192 
193     /* Determine if the thread create was successful.  */
194     if (status != TX_SUCCESS)
195     {
196 
197         /* Terminate the start thread.  */
198         _tx_thread_terminate(&(module_instance -> txm_module_instance_start_stop_thread));
199 
200         /* Delete the start thread.  */
201         _tx_thread_delete(&(module_instance -> txm_module_instance_start_stop_thread));
202 
203         /* Delete the callback notification queue.  */
204         _tx_queue_delete(&(module_instance -> txm_module_instance_callback_request_queue));
205 
206         /* Release the protection mutex.  */
207         _tx_mutex_put(&_txm_module_manager_mutex);
208 
209         /* Return the error status.  */
210         return(status);
211     }
212 
213 
214     /* Set the module state to started.  */
215     module_instance -> txm_module_instance_state =  TXM_MODULE_STARTED;
216 
217     /* Release the protection mutex.  */
218     _tx_mutex_put(&_txm_module_manager_mutex);
219 
220     /* Resume the module's start thread.  */
221     _tx_thread_resume(&(module_instance -> txm_module_instance_start_stop_thread));
222 
223     /* Return success.  */
224     return(TX_SUCCESS);
225 }
226 
227