GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: core/src/ux_utility_memory_allocate.c Lines: 65 66 98.5 %
Date: 2026-03-06 18:57:10 Branches: 21 22 95.5 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
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
/*  FUNCTION                                               RELEASE        */
33
/*                                                                        */
34
/*    _ux_utility_memory_allocate                         PORTABLE C      */
35
/*                                                           6.3.0        */
36
/*  AUTHOR                                                                */
37
/*                                                                        */
38
/*    Chaoqiong Xiao, Microsoft Corporation                               */
39
/*                                                                        */
40
/*  DESCRIPTION                                                           */
41
/*                                                                        */
42
/*    This function allocates a block of memory for the specified size    */
43
/*    and alignment.                                                      */
44
/*                                                                        */
45
/*  INPUT                                                                 */
46
/*                                                                        */
47
/*    memory_alignment                      Memory alignment required     */
48
/*    memory_cache_flag                     Memory pool source            */
49
/*    memory_size_requested                 Number of bytes required      */
50
/*                                                                        */
51
/*  OUTPUT                                                                */
52
/*                                                                        */
53
/*    Pointer to block of memory                                          */
54
/*                                                                        */
55
/*  CALLS                                                                 */
56
/*                                                                        */
57
/*    _ux_utility_memory_free_block_best_get Get best fit block of memory */
58
/*    _ux_utility_memory_set                 Set block of memory          */
59
/*                                                                        */
60
/*  CALLED BY                                                             */
61
/*                                                                        */
62
/*    USBX Components                                                     */
63
/*                                                                        */
64
/**************************************************************************/
65
343630
VOID  *_ux_utility_memory_allocate(ULONG memory_alignment, ULONG memory_cache_flag,
66
                                   ULONG memory_size_requested)
67
{
68
UX_MEMORY_BYTE_POOL *pool_ptr;
69
UCHAR               *current_ptr;
70
UCHAR               *work_ptr;
71
UCHAR               *next_ptr;
72
ALIGN_TYPE          *free_ptr;
73
UCHAR               **this_block_link_ptr;
74
UCHAR               **next_block_link_ptr;
75
ULONG               available_bytes;
76
77
ALIGN_TYPE          int_memory_buffer;
78
#ifdef UX_ENABLE_MEMORY_STATISTICS
79
UINT                index;
80
#endif
81
82
    /* Get the pool ptr */
83
343630
    if (memory_cache_flag == UX_REGULAR_MEMORY)
84
    {
85
327526
        pool_ptr = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR];
86
    }
87
16104
    else if (memory_cache_flag == UX_CACHE_SAFE_MEMORY)
88
    {
89
16068
        pool_ptr = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE];
90
    }
91
    else
92
    {
93
36
        return(UX_NULL);
94
    }
95
96
    /* Check if pool_ptr is NX_NULL */
97
343594
    if (pool_ptr == UX_NULL)
98
    {
99
        return(UX_NULL);
100
    }
101
102
    /* Check if the memory size requested is 0.  */
103
343594
    if (memory_size_requested == 0)
104
    {
105
1
        return(UX_NULL);
106
    }
107
108
    /* Get the mutex as this is a critical section.  */
109
343593
    _ux_system_mutex_on(&_ux_system -> ux_system_mutex);
110
111
#ifdef UX_ENFORCE_SAFE_ALIGNMENT
112
113
    /* Check if safe alignment requested, in this case switch to UX_NO_ALIGN.  */
114
    if (memory_alignment == UX_SAFE_ALIGN)
115
    {
116
117
        /* We will use the memory_size_requested for the alignment.
118
           But we check to see if we have a minimum or maximum alignment.  */
119
        if (memory_size_requested < UX_ALIGN_MIN)
120
121
            /* No need to bother about alignment for small packets sizes.  */
122
            memory_alignment = UX_NO_ALIGN;
123
124
        /* Check if we are over the maximum.  */
125
        else if (memory_size_requested > UX_MAX_SCATTER_GATHER_ALIGNMENT)
126
127
            /* We are over the max alignment required. Use the maximum instead.  */
128
            memory_alignment = UX_MAX_SCATTER_GATHER_ALIGNMENT - 1;
129
130
        /* We are not over the maximum, so approximate the alignment according to the size of the memory.
131
            Check range for alignment on 4096 bytes.  */
132
        else if (memory_size_requested >= UX_ALIGN_2048 + 1)
133
            memory_alignment = UX_ALIGN_4096;
134
135
        /* Check range for alignment on 2048 bytes.  */
136
        else if (memory_size_requested >= UX_ALIGN_1024 + 1)
137
            memory_alignment = UX_ALIGN_2048;
138
139
        /* Check range for alignment on 1024 bytes.  */
140
        else if (memory_size_requested >= UX_ALIGN_512 + 1)
141
            memory_alignment = UX_ALIGN_1024;
142
143
        /* Check range for alignment on 512 bytes.  */
144
        else if (memory_size_requested >= UX_ALIGN_256 + 1)
145
            memory_alignment = UX_ALIGN_512;
146
147
        /* Check range for alignment on 256 bytes.  */
148
        else if (memory_size_requested >= UX_ALIGN_128 + 1)
149
            memory_alignment = UX_ALIGN_256;
150
151
        /* Check range for alignment on 128 bytes.  */
152
        else if (memory_size_requested >= UX_ALIGN_64 + 1)
153
            memory_alignment = UX_ALIGN_128;
154
155
        /* Check range for alignment on 64 bytes.  */
156
        else if (memory_size_requested >= UX_ALIGN_32 + 1)
157
            memory_alignment = UX_ALIGN_64;
158
159
        /* Check range for alignment on 32 bytes.  */
160
        else if (memory_size_requested >= UX_ALIGN_16 + 1)
161
            memory_alignment = UX_ALIGN_32;
162
163
        /* Check range for alignment on 16 bytes.  */
164
        else if (memory_size_requested >= UX_ALIGN_8 + 1)
165
            memory_alignment = UX_ALIGN_16;
166
167
        else
168
            memory_alignment = UX_ALIGN_MIN;
169
    }
170
171
#else
172
173
    /* Check if safe alignment requested, in this case switch to UX_NO_ALIGN.  */
174
343593
    if (memory_alignment == UX_SAFE_ALIGN)
175
7272
        memory_alignment = UX_NO_ALIGN;
176
177
#endif
178
179
    /* Ensure the alignment meats the minimum.  */
180
343593
    if (memory_alignment < UX_ALIGN_MIN)
181
342416
        memory_alignment =  UX_ALIGN_MIN;
182
183
    /* We need to make sure that the next memory block buffer is 8-byte aligned too. We
184
       do this by first adjusting the requested memory to be 8-byte aligned. One problem
185
       now is that the memory block might not be a size that is a multiple of 8, so we need
186
       to add the amount of memory required such that the memory buffer after the block has
187
       the correct alignment. For example, if the memory block has a size of 12, then we need
188
       to make sure it is placed on an 8-byte alignment that is after a 8-byte alignment so
189
       that the memory right after the memory block is 8-byte aligned (16).  */
190
343593
    memory_size_requested =  (memory_size_requested + UX_ALIGN_MIN) & (~(ULONG)UX_ALIGN_MIN);
191
343593
    memory_size_requested += (((ULONG)(UX_MEMORY_BLOCK_HEADER_SIZE + UX_ALIGN_MIN) & (~(ULONG)UX_ALIGN_MIN)) - (ULONG)UX_MEMORY_BLOCK_HEADER_SIZE);
192
193
343593
    if (memory_alignment <= UX_ALIGN_MIN)
194
342422
        current_ptr = _ux_utility_memory_byte_pool_search(pool_ptr, memory_size_requested);
195
    else
196
1171
        current_ptr = _ux_utility_memory_byte_pool_search(pool_ptr, memory_size_requested + memory_alignment);
197
198
    /* Check if we found a memory block.  */
199
343593
    if (current_ptr == UX_NULL)
200
    {
201
202
        /* We could not find a memory block.  */
203
15342
        _ux_system_mutex_off(&_ux_system -> ux_system_mutex);
204
205
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, memory_size_requested, 0, 0, UX_TRACE_ERRORS, 0, 0)
206
207
        /* Error trap. */
208
15342
        _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_UTILITY, UX_MEMORY_INSUFFICIENT);
209
210
15342
        return(UX_NULL);
211
    }
212
213
    /* Pickup the next block's pointer.  */
214
328251
    this_block_link_ptr =  UX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr);
215
328251
    next_ptr =             *this_block_link_ptr;
216
217
    /* Calculate the number of bytes available in this block.  */
218
328251
    available_bytes =   UX_UCHAR_POINTER_DIF(next_ptr, current_ptr);
219
328251
    available_bytes =   available_bytes - UX_MEMORY_BLOCK_HEADER_SIZE;
220
221
    /* Get the memory buffer for this block.  */
222
328251
    int_memory_buffer = (ALIGN_TYPE) (UX_UCHAR_POINTER_ADD(current_ptr, UX_MEMORY_BLOCK_HEADER_SIZE));
223
224
    /* In case we are not aligned  */
225
328251
    if ((int_memory_buffer & memory_alignment) != 0)
226
    {
227
228
        /* No, we need to align the memory buffer.  */
229
936
        int_memory_buffer += (ALIGN_TYPE)UX_MEMORY_BLOCK_HEADER_SIZE;
230
936
        int_memory_buffer += memory_alignment;
231
936
        int_memory_buffer &=  ~((ALIGN_TYPE) memory_alignment);
232
936
        int_memory_buffer -= (ALIGN_TYPE)UX_MEMORY_BLOCK_HEADER_SIZE;
233
234
        /* Setup the new free block.  */
235
936
        next_ptr = (UCHAR *)int_memory_buffer;
236
237
        /* Setup the new free block.  */
238
936
        next_block_link_ptr =   UX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(next_ptr);
239
936
        *next_block_link_ptr =  *this_block_link_ptr;
240
936
        work_ptr =              UX_UCHAR_POINTER_ADD(next_ptr, (sizeof(UCHAR *)));
241
936
        free_ptr =              UX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(work_ptr);
242
936
        *free_ptr =             UX_BYTE_BLOCK_FREE;
243
244
        /* Increase the total fragment counter.  */
245
936
        pool_ptr -> ux_byte_pool_fragments++;
246
247
        /* Update the current pointer to point at the newly created block.  */
248
936
        *this_block_link_ptr =  next_ptr;
249
250
        /* Calculate the available bytes.  */
251
936
        available_bytes -=  UX_UCHAR_POINTER_DIF(next_ptr, current_ptr);
252
253
        /* Set Current pointer to the aligned memory buffer.  */
254
936
        current_ptr = next_ptr;
255
    }
256
257
    /* Now we are aligned, determine if we need to split this block.  */
258
328251
    if ((available_bytes - memory_size_requested) >= ((ULONG) UX_BYTE_BLOCK_MIN))
259
    {
260
261
        /* Split the block.  */
262
16514
        next_ptr =  UX_UCHAR_POINTER_ADD(current_ptr, (memory_size_requested + UX_MEMORY_BLOCK_HEADER_SIZE));
263
264
        /* Setup the new free block.  */
265
16514
        next_block_link_ptr =   UX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(next_ptr);
266
16514
        this_block_link_ptr =   UX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr);
267
16514
        *next_block_link_ptr =  *this_block_link_ptr;
268
16514
        work_ptr =              UX_UCHAR_POINTER_ADD(next_ptr, (sizeof(UCHAR *)));
269
16514
        free_ptr =              UX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(work_ptr);
270
16514
        *free_ptr =             UX_BYTE_BLOCK_FREE;
271
272
        /* Increase the total fragment counter.  */
273
16514
        pool_ptr -> ux_byte_pool_fragments++;
274
275
        /* Update the current pointer to point at the newly created block.  */
276
16514
        *this_block_link_ptr =  next_ptr;
277
278
        /* Set available equal to memory size for subsequent calculation.  */
279
16514
        available_bytes =  memory_size_requested;
280
    }
281
282
    /* In any case, mark the current block as allocated.  */
283
328251
    work_ptr =              UX_UCHAR_POINTER_ADD(current_ptr, (sizeof(UCHAR *)));
284
328251
    this_block_link_ptr =   UX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(work_ptr);
285
328251
    *this_block_link_ptr =  UX_BYTE_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr);
286
287
    /* Reduce the number of available bytes in the pool.  */
288
328251
    pool_ptr -> ux_byte_pool_available =  pool_ptr -> ux_byte_pool_available - (available_bytes + UX_MEMORY_BLOCK_HEADER_SIZE);
289
290
    /* Determine if the search pointer needs to be updated. This is only done
291
        if the search pointer matches the block to be returned.  */
292
328251
    if (current_ptr == pool_ptr -> ux_byte_pool_search)
293
    {
294
295
        /* Yes, update the search pointer to the next block.  */
296
11150
        this_block_link_ptr =   UX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(current_ptr);
297
11150
        pool_ptr -> ux_byte_pool_search =  *this_block_link_ptr;
298
    }
299
300
    /* Adjust the pointer for the application.  */
301
328251
    work_ptr =  UX_UCHAR_POINTER_ADD(current_ptr, UX_MEMORY_BLOCK_HEADER_SIZE);
302
303
    /* Clear the memory block.  */
304
328251
    _ux_utility_memory_set(work_ptr, 0, available_bytes); /* Use case of memset is verified. */
305
306
#ifdef UX_ENABLE_MEMORY_STATISTICS
307
308
    /* Update allocate count, total size.  */
309
    if (memory_cache_flag == UX_REGULAR_MEMORY)
310
        index = UX_MEMORY_BYTE_POOL_REGULAR;
311
    else
312
        index = UX_MEMORY_BYTE_POOL_CACHE_SAFE;
313
314
    /* Update allocate count, total size.  */
315
    _ux_system -> ux_system_memory_byte_pool[index] -> ux_byte_pool_alloc_count ++;
316
    _ux_system -> ux_system_memory_byte_pool[index] -> ux_byte_pool_alloc_total += (available_bytes + UX_MEMORY_BLOCK_HEADER_SIZE);
317
318
    if (_ux_system -> ux_system_memory_byte_pool[index] -> ux_byte_pool_alloc_max_count < _ux_system -> ux_system_memory_byte_pool[index] -> ux_byte_pool_alloc_count)
319
        _ux_system -> ux_system_memory_byte_pool[index] -> ux_byte_pool_alloc_max_count = _ux_system -> ux_system_memory_byte_pool[index] -> ux_byte_pool_alloc_count;
320
321
    if (_ux_system -> ux_system_memory_byte_pool[index] -> ux_byte_pool_alloc_max_total < _ux_system -> ux_system_memory_byte_pool[index] -> ux_byte_pool_alloc_total)
322
        _ux_system -> ux_system_memory_byte_pool[index] -> ux_byte_pool_alloc_max_total = _ux_system -> ux_system_memory_byte_pool[index] -> ux_byte_pool_alloc_total;
323
324
    /* Log max usage of memory pool.  */
325
    if (_ux_system -> ux_system_memory_byte_pool[index] -> ux_byte_pool_min_free > _ux_system -> ux_system_memory_byte_pool[index] -> ux_byte_pool_available)
326
        _ux_system -> ux_system_memory_byte_pool[index] -> ux_byte_pool_min_free = _ux_system -> ux_system_memory_byte_pool[index] -> ux_byte_pool_available;
327
#endif
328
329
    /* Release the protection.  */
330
328251
    _ux_system_mutex_off(&_ux_system -> ux_system_mutex);
331
332
328251
    return(work_ptr);
333
}