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