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