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 /** USBX Component */
17 /** */
18 /** Utility */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23
24 /* Include necessary system files. */
25
26 #define UX_SOURCE_CODE
27
28 #include "ux_api.h"
29
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _ux_utility_memory_free PORTABLE C */
36 /* 6.1.10 */
37 /* AUTHOR */
38 /* */
39 /* Chaoqiong Xiao, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function frees a previously allocated memory block. */
44 /* */
45 /* INPUT */
46 /* */
47 /* memory Pointer to memory block */
48 /* */
49 /* OUTPUT */
50 /* */
51 /* None */
52 /* */
53 /* CALLS */
54 /* */
55 /* _ux_utility_mutex_on Start system protection */
56 /* _ux_utility_mutex_off End system protection */
57 /* */
58 /* CALLED BY */
59 /* */
60 /* USBX Components */
61 /* */
62 /* RELEASE HISTORY */
63 /* */
64 /* DATE NAME DESCRIPTION */
65 /* */
66 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
67 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
68 /* resulting in version 6.1 */
69 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
70 /* added standalone support, */
71 /* resulting in version 6.1.10 */
72 /* */
73 /**************************************************************************/
_ux_utility_memory_free(VOID * memory)74 VOID _ux_utility_memory_free(VOID *memory)
75 {
76
77 UX_MEMORY_BLOCK *memory_block;
78 UX_MEMORY_BLOCK *next_block;
79 ULONG memory_size_returned;
80 UCHAR *memory_address;
81 #ifdef UX_ENABLE_MEMORY_POOL_SANITY_CHECK
82 UCHAR *regular_start, *regular_end;
83 UCHAR *cache_safe_start, *cache_safe_end;
84 #endif
85
86 /* Get the mutex as this is a critical section. */
87 _ux_system_mutex_on(&_ux_system -> ux_system_mutex);
88
89 #ifdef UX_ENABLE_MEMORY_POOL_SANITY_CHECK
90
91 /* Sanity check, check if the memory is in memory pool. */
92 regular_start = (UCHAR *)_ux_system -> ux_system_regular_memory_pool_start;
93 regular_end = regular_start + _ux_system -> ux_system_regular_memory_pool_size;
94 regular_start += sizeof(UX_MEMORY_BLOCK);
95 cache_safe_start = (UCHAR *)_ux_system -> ux_system_cache_safe_memory_pool_start;
96 cache_safe_end = cache_safe_start + _ux_system -> ux_system_cache_safe_memory_pool_size;
97 cache_safe_start += sizeof(UX_MEMORY_BLOCK);
98 memory_address = (UCHAR *)memory;
99 if (!((memory_address >= regular_start && memory_address < regular_end) ||
100 (memory_address >= cache_safe_start && memory_address < cache_safe_end)))
101 {
102
103 /* Not valid. Release the protection. */
104 _ux_system_mutex_off(&_ux_system -> ux_system_mutex);
105
106 /* Error trap. */
107 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD,
108 UX_SYSTEM_CONTEXT_UTILITY, UX_MEMORY_CORRUPTED);
109
110 /* No action taken. */
111 return;
112 }
113 #endif
114
115 /* The memory block for this memory pointer is located right before the
116 memory. */
117 memory_block = (UX_MEMORY_BLOCK *) (((UCHAR *) memory) - sizeof(UX_MEMORY_BLOCK));
118
119 /* Keep track of the memory returned to the pool. */
120 memory_size_returned = memory_block -> ux_memory_block_size + (ULONG)sizeof(UX_MEMORY_BLOCK);
121
122 /* Check this memory block to see if it valid. */
123 if (memory_block -> ux_memory_block_status != (UX_MEMORY_USED | UX_REGULAR_MEMORY) &&
124 memory_block -> ux_memory_block_status != (UX_MEMORY_USED | UX_CACHE_SAFE_MEMORY))
125 {
126
127 /* Not valid. Release the protection. */
128 _ux_system_mutex_off(&_ux_system -> ux_system_mutex);
129
130 /* Error trap. */
131 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_UTILITY, UX_MEMORY_CORRUPTED);
132
133 /* If trace is enabled, insert this event into the trace buffer. */
134 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_CORRUPTED, memory, 0, 0, UX_TRACE_ERRORS, 0, 0)
135
136 /* Return to caller. */
137 return;
138 }
139
140 #ifdef UX_ENABLE_MEMORY_STATISTICS
141
142 /* Update allocate count, total size. */
143 if (memory_block -> ux_memory_block_status == (UX_MEMORY_USED | UX_REGULAR_MEMORY))
144 {
145 _ux_system -> ux_system_regular_memory_pool_alloc_count --;
146 _ux_system -> ux_system_regular_memory_pool_alloc_total -= memory_block -> ux_memory_block_size;
147 }
148 else
149 {
150 _ux_system -> ux_system_cache_safe_memory_pool_alloc_count --;
151 _ux_system -> ux_system_cache_safe_memory_pool_alloc_total -= memory_block -> ux_memory_block_size;
152 }
153 #endif
154
155 /* We mark this memory block as being unused. */
156 memory_block -> ux_memory_block_status = UX_MEMORY_UNUSED;
157
158 /* Now we must concatenate as many free blocks as possible,
159 that include the blocks before and the blocks after the current
160 block. Scan memory backwards. */
161
162 while (memory_block -> ux_memory_block_previous !=UX_NULL)
163 {
164
165 /* Check if the block is free. */
166 if (memory_block -> ux_memory_block_previous -> ux_memory_block_status == UX_MEMORY_UNUSED)
167
168 /* The memory block before is free. This will be our starting point to
169 concatenate memory. */
170 memory_block = memory_block -> ux_memory_block_previous;
171
172 else
173
174 /* The previous memory block is not free. */
175 break;
176 }
177
178 /* The pointer to the memory block is now our first free block. We use this
179 starting address to concatenate all the contiguous memory block. */
180 next_block = memory_block -> ux_memory_block_next;
181 while (next_block != UX_NULL)
182 {
183
184 /* Determine if the memory block is used. */
185 if (next_block -> ux_memory_block_status != UX_MEMORY_UNUSED)
186 {
187
188 /* Yes, move to next block. */
189 memory_block -> ux_memory_block_next = next_block;
190 next_block -> ux_memory_block_previous = memory_block;
191 break;
192 }
193
194 memory_block -> ux_memory_block_next = next_block -> ux_memory_block_next;
195 memory_block -> ux_memory_block_size += next_block -> ux_memory_block_size + (ULONG)sizeof(UX_MEMORY_BLOCK);
196 next_block = next_block -> ux_memory_block_next;
197 }
198
199 /* Update the memory free in the appropriate pool. We need to know if this
200 block is in regular memory or cache safe memory. */
201 if(_ux_system -> ux_system_cache_safe_memory_pool_start == _ux_system -> ux_system_regular_memory_pool_start)
202 {
203
204 /* There is only one regular memory pool. */
205 _ux_system -> ux_system_regular_memory_pool_free += memory_size_returned;
206
207 }
208 else
209 {
210
211 /* Which pool is this memory in ? */
212 memory_address = (UCHAR *) _ux_system -> ux_system_regular_memory_pool_start;
213
214 /* If the memory address is in this range, we are in the regular memory pool. */
215 if ((UCHAR *) memory_block >= memory_address && (UCHAR *) memory_block < (memory_address + _ux_system -> ux_system_regular_memory_pool_size))
216
217 /* Update the regular memory pool. */
218 _ux_system -> ux_system_regular_memory_pool_free += memory_size_returned;
219
220 else
221
222 /* Update the cache safe memory pool. */
223 _ux_system -> ux_system_cache_safe_memory_pool_free += memory_size_returned;
224
225 }
226
227 /* Release the protection. */
228 _ux_system_mutex_off(&_ux_system -> ux_system_mutex);
229
230 /* Return to caller. */
231 return;
232 }
233
234