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_byte_pool.h"
26 #include "tx_initialize.h"
27 #include "tx_mutex.h"
28 #include "tx_thread.h"
29 #include "txm_module.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _txm_module_manager_unload PORTABLE C */
37 /* 6.1 */
38 /* AUTHOR */
39 /* */
40 /* Scott Larson, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function unloads a previously loaded module. */
45 /* */
46 /* INPUT */
47 /* */
48 /* module_instance Module instance pointer */
49 /* */
50 /* OUTPUT */
51 /* */
52 /* status Completion status */
53 /* */
54 /* CALLS */
55 /* */
56 /* _tx_byte_release Release data area */
57 /* _tx_mutex_get Get protection mutex */
58 /* _tx_mutex_put Release protection mutex */
59 /* */
60 /* CALLED BY */
61 /* */
62 /* Application code */
63 /* */
64 /* RELEASE HISTORY */
65 /* */
66 /* DATE NAME DESCRIPTION */
67 /* */
68 /* 09-30-2020 Scott Larson Initial Version 6.1 */
69 /* */
70 /**************************************************************************/
_txm_module_manager_unload(TXM_MODULE_INSTANCE * module_instance)71 UINT _txm_module_manager_unload(TXM_MODULE_INSTANCE *module_instance)
72 {
73
74 TX_INTERRUPT_SAVE_AREA
75
76 TXM_MODULE_INSTANCE *next_module, *previous_module;
77 CHAR *memory_ptr;
78
79
80 /* Check for interrupt call. */
81 if (TX_THREAD_GET_SYSTEM_STATE() != 0)
82 {
83
84 /* Now, make sure the call is from an interrupt and not initialization. */
85 if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS)
86 {
87
88 /* Invalid caller of this function, return appropriate error code. */
89 return(TX_CALLER_ERROR);
90 }
91 }
92
93 /* Determine if the module manager has not been initialized yet. */
94 if (_txm_module_manager_ready != TX_TRUE)
95 {
96
97 /* Module manager has not been initialized. */
98 return(TX_NOT_AVAILABLE);
99 }
100
101 /* Determine if the module is valid. */
102 if (module_instance == TX_NULL)
103 {
104
105 /* Invalid module pointer. */
106 return(TX_PTR_ERROR);
107 }
108
109 /* Get module manager protection mutex. */
110 _tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER);
111
112 /* Determine if the module is already valid. */
113 if (module_instance -> txm_module_instance_id != TXM_MODULE_ID)
114 {
115
116 /* Release the protection mutex. */
117 _tx_mutex_put(&_txm_module_manager_mutex);
118
119 /* Invalid module pointer. */
120 return(TX_PTR_ERROR);
121 }
122
123 /* Determine if the module instance is in the state. */
124 if ((module_instance -> txm_module_instance_state != TXM_MODULE_LOADED) && (module_instance -> txm_module_instance_state != TXM_MODULE_STOPPED))
125 {
126
127 /* Release the protection mutex. */
128 _tx_mutex_put(&_txm_module_manager_mutex);
129
130 /* Return error if the module is not ready. */
131 return(TX_NOT_DONE);
132 }
133
134 /* Pickup the module data memory allocation address. */
135 memory_ptr = module_instance -> txm_module_instance_data_allocation_ptr;
136
137 /* Release the module's data memory. */
138 _tx_byte_release(memory_ptr);
139
140 /* Determine if there was memory allocated for the code. */
141 if (module_instance -> txm_module_instance_code_allocation_ptr)
142 {
143
144 /* Yes, release the module's code memory. */
145 memory_ptr = module_instance -> txm_module_instance_code_allocation_ptr;
146
147 /* Release the module's data memory. */
148 _tx_byte_release(memory_ptr);
149 }
150
151 /* Temporarily disable interrupts. */
152 TX_DISABLE
153
154 /* Clear some of the module information. */
155 module_instance -> txm_module_instance_id = 0;
156 module_instance -> txm_module_instance_state = TXM_MODULE_UNLOADED;
157
158 /* Call port-specific unload function. */
159 TXM_MODULE_MANAGER_MODULE_UNLOAD(module_instance);
160
161 /* Remove the module from the linked list of loaded modules. */
162
163 /* See if the module is the only one on the list. */
164 if ((--_txm_module_manger_loaded_count) == 0)
165 {
166
167 /* Only created module, just set the created list to NULL. */
168 _txm_module_manager_loaded_list_ptr = TX_NULL;
169 }
170 else
171 {
172
173 /* Otherwise, not the only created module, link-up the neighbors. */
174 next_module = module_instance -> txm_module_instance_loaded_next;
175 previous_module = module_instance -> txm_module_instance_loaded_previous;
176 next_module -> txm_module_instance_loaded_previous = previous_module;
177 previous_module -> txm_module_instance_loaded_next = next_module;
178
179 /* See if we have to update the created list head pointer. */
180 if (_txm_module_manager_loaded_list_ptr == module_instance)
181 {
182
183 /* Yes, move the head pointer to the next link. */
184 _txm_module_manager_loaded_list_ptr = next_module;
185 }
186 }
187
188 /* Restore interrupts. */
189 TX_RESTORE
190
191 /* Release the protection mutex. */
192 _tx_mutex_put(&_txm_module_manager_mutex);
193
194 /* Return success. */
195 return(TX_SUCCESS);
196 }
197