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