![]() |
|
|||
File indexing completed on 2025-05-11 08:24:12
0001 /* SPDX-License-Identifier: BSD-2-Clause */ 0002 0003 /** 0004 * @file 0005 * 0006 * @ingroup RTEMSScoreHeap 0007 * 0008 * @brief This header file provides interfaces of the 0009 * @ref RTEMSScoreHeap which are used by the implementation and the 0010 * @ref RTEMSImplApplConfig. 0011 */ 0012 0013 /* 0014 * COPYRIGHT (c) 1989-2006. 0015 * On-Line Applications Research Corporation (OAR). 0016 * 0017 * Redistribution and use in source and binary forms, with or without 0018 * modification, are permitted provided that the following conditions 0019 * are met: 0020 * 1. Redistributions of source code must retain the above copyright 0021 * notice, this list of conditions and the following disclaimer. 0022 * 2. Redistributions in binary form must reproduce the above copyright 0023 * notice, this list of conditions and the following disclaimer in the 0024 * documentation and/or other materials provided with the distribution. 0025 * 0026 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 0027 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 0028 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 0029 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 0030 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 0031 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 0032 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 0033 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 0034 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 0035 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 0036 * POSSIBILITY OF SUCH DAMAGE. 0037 */ 0038 0039 #ifndef _RTEMS_SCORE_HEAP_H 0040 #define _RTEMS_SCORE_HEAP_H 0041 0042 #include <rtems/score/cpu.h> 0043 #include <rtems/score/heapinfo.h> 0044 0045 #ifdef __cplusplus 0046 extern "C" { 0047 #endif 0048 0049 #ifdef RTEMS_DEBUG 0050 #define HEAP_PROTECTION 0051 #endif 0052 0053 /** 0054 * @defgroup RTEMSScoreHeap Heap Handler 0055 * 0056 * @ingroup RTEMSScore 0057 * 0058 * @brief This group contains the Heap Handler implementation. 0059 * 0060 * A heap is a doubly linked list of variable size blocks which are allocated 0061 * using the first fit method. Garbage collection is performed each time a 0062 * block is returned to the heap by coalescing neighbor blocks. Control 0063 * information for both allocated and free blocks is contained in the heap 0064 * area. A heap control structure contains control information for the heap. 0065 * 0066 * The alignment routines could be made faster should we require only powers of 0067 * two to be supported for page size, alignment and boundary arguments. The 0068 * minimum alignment requirement for pages is currently CPU_ALIGNMENT and this 0069 * value is only required to be multiple of two and explicitly not required to 0070 * be a power of two. 0071 * 0072 * There are two kinds of blocks. One sort describes a free block from which 0073 * we can allocate memory. The other blocks are used and provide an allocated 0074 * memory area. The free blocks are accessible via a list of free blocks. 0075 * 0076 * Blocks or areas cover a continuous set of memory addresses. They have a 0077 * begin and end address. The end address is not part of the set. The size of 0078 * a block or area equals the distance between the begin and end address in 0079 * units of bytes. 0080 * 0081 * Free blocks look like: 0082 * <table> 0083 * <tr> 0084 * <td rowspan=4>@ref Heap_Block</td><td>previous block size in case the 0085 * previous block is free, <br> otherwise it may contain data used by 0086 * the previous block</td> 0087 * </tr> 0088 * <tr> 0089 * <td>block size and a flag which indicates if the previous block is free 0090 * or used, <br> this field contains always valid data regardless of the 0091 * block usage</td> 0092 * </tr> 0093 * <tr><td>pointer to next block (this field is page size aligned)</td></tr> 0094 * <tr><td>pointer to previous block</td></tr> 0095 * <tr><td colspan=2>free space</td></tr> 0096 * </table> 0097 * 0098 * Used blocks look like: 0099 * <table> 0100 * <tr> 0101 * <td rowspan=4>@ref Heap_Block</td><td>previous block size in case the 0102 * previous block is free,<br>otherwise it may contain data used by 0103 * the previous block</td> 0104 * </tr> 0105 * <tr> 0106 * <td>block size and a flag which indicates if the previous block is free 0107 * or used, <br> this field contains always valid data regardless of the 0108 * block usage</td> 0109 * </tr> 0110 * <tr><td>begin of allocated area (this field is page size aligned)</td></tr> 0111 * <tr><td>allocated space</td></tr> 0112 * <tr><td colspan=2>allocated space</td></tr> 0113 * </table> 0114 * 0115 * The heap area after initialization contains two blocks and looks like: 0116 * <table> 0117 * <tr><th>Label</th><th colspan=2>Content</th></tr> 0118 * <tr><td>heap->area_begin</td><td colspan=2>heap area begin address</td></tr> 0119 * <tr> 0120 * <td>first_block->prev_size</td> 0121 * <td colspan=2> 0122 * subordinate heap area end address (this will be used to maintain a 0123 * linked list of scattered heap areas) 0124 * </td> 0125 * </tr> 0126 * <tr> 0127 * <td>first_block->size</td> 0128 * <td colspan=2>size available for allocation 0129 * | @c HEAP_PREV_BLOCK_USED</td> 0130 * </tr> 0131 * <tr> 0132 * <td>first_block->next</td><td>_Heap_Free_list_tail(heap)</td> 0133 * <td rowspan=3>memory area available for allocation</td> 0134 * </tr> 0135 * <tr><td>first_block->prev</td><td>_Heap_Free_list_head(heap)</td></tr> 0136 * <tr><td>...</td></tr> 0137 * <tr> 0138 * <td>last_block->prev_size</td><td colspan=2>size of first block</td> 0139 * </tr> 0140 * <tr> 0141 * <td>last_block->size</td> 0142 * <td colspan=2>first block begin address - last block begin address</td> 0143 * </tr> 0144 * <tr><td>heap->area_end</td><td colspan=2>heap area end address</td></tr> 0145 * </table> 0146 * The next block of the last block is the first block. Since the first 0147 * block indicates that the previous block is used, this ensures that the 0148 * last block appears as used for the _Heap_Is_used() and _Heap_Is_free() 0149 * functions. 0150 * 0151 * @{ 0152 */ 0153 0154 typedef struct Heap_Control Heap_Control; 0155 0156 typedef struct Heap_Block Heap_Block; 0157 0158 /** 0159 * @brief The heap error reason. 0160 * 0161 * @see _Heap_Protection_block_error(). 0162 */ 0163 typedef enum { 0164 /** 0165 * @brief There is an unexpected value in the heap block protector area. 0166 */ 0167 HEAP_ERROR_BROKEN_PROTECTOR, 0168 0169 /** 0170 * @brief There is an unexpected value in the free pattern of a free heap 0171 * block. 0172 */ 0173 HEAP_ERROR_FREE_PATTERN, 0174 0175 /** 0176 * @brief There is was an attempt to free the same block twice. 0177 */ 0178 HEAP_ERROR_DOUBLE_FREE, 0179 0180 /** 0181 * @brief The next block of a supposed to be used block does not indicate that 0182 * the block is used. 0183 */ 0184 HEAP_ERROR_BAD_USED_BLOCK, 0185 0186 /** 0187 * @brief A supposed to be free block is not inside the heap memory area. 0188 */ 0189 HEAP_ERROR_BAD_FREE_BLOCK 0190 } Heap_Error_reason; 0191 0192 /** 0193 * @brief Context of a heap error. 0194 * 0195 * @see _Heap_Protection_block_error(). 0196 */ 0197 typedef struct { 0198 /** 0199 * @brief The heap of the block. 0200 */ 0201 Heap_Control *heap; 0202 0203 /** 0204 * @brief The heap block causing the error. 0205 */ 0206 Heap_Block *block; 0207 0208 /** 0209 * @brief The heap error reason. 0210 */ 0211 Heap_Error_reason reason; 0212 } Heap_Error_context; 0213 0214 #ifndef HEAP_PROTECTION 0215 #define HEAP_PROTECTION_HEADER_SIZE 0 0216 #else 0217 #define HEAP_PROTECTOR_COUNT 2 0218 0219 #define HEAP_BEGIN_PROTECTOR_0 ((uintptr_t) 0xfd75a98f) 0220 #define HEAP_BEGIN_PROTECTOR_1 ((uintptr_t) 0xbfa1f177) 0221 #define HEAP_END_PROTECTOR_0 ((uintptr_t) 0xd6b8855e) 0222 #define HEAP_END_PROTECTOR_1 ((uintptr_t) 0x13a44a5b) 0223 0224 #define HEAP_FREE_PATTERN ((uintptr_t) 0xe7093cdf) 0225 0226 #define HEAP_PROTECTION_OBOLUS ((Heap_Block *) 1) 0227 0228 typedef void (*_Heap_Protection_handler)( 0229 Heap_Control *heap, 0230 Heap_Block *block 0231 ); 0232 0233 typedef void (*_Heap_Protection_error_handler)( 0234 Heap_Control *heap, 0235 Heap_Block *block, 0236 Heap_Error_reason reason 0237 ); 0238 0239 typedef struct { 0240 _Heap_Protection_handler block_initialize; 0241 _Heap_Protection_handler block_check; 0242 _Heap_Protection_error_handler block_error; 0243 void *handler_data; 0244 Heap_Block *first_delayed_free_block; 0245 Heap_Block *last_delayed_free_block; 0246 uintptr_t delayed_free_block_count; 0247 uintptr_t delayed_free_fraction; 0248 } Heap_Protection; 0249 0250 struct _Thread_Control; 0251 0252 typedef struct { 0253 uintptr_t protector [HEAP_PROTECTOR_COUNT]; 0254 Heap_Block *next_delayed_free_block; 0255 struct _Thread_Control *task; 0256 void *tag; 0257 } Heap_Protection_block_begin; 0258 0259 typedef struct { 0260 uintptr_t protector [HEAP_PROTECTOR_COUNT]; 0261 } Heap_Protection_block_end; 0262 0263 #define HEAP_PROTECTION_HEADER_SIZE \ 0264 (sizeof(Heap_Protection_block_begin) + sizeof(Heap_Protection_block_end)) 0265 #endif 0266 0267 /** 0268 * @brief The block header consists of the two size fields 0269 * (@ref Heap_Block.prev_size and @ref Heap_Block.size_and_flag). 0270 */ 0271 #define HEAP_BLOCK_HEADER_SIZE \ 0272 (2 * sizeof(uintptr_t) + HEAP_PROTECTION_HEADER_SIZE) 0273 0274 /** 0275 * @brief Description for free or used blocks. 0276 */ 0277 struct Heap_Block { 0278 /** 0279 * @brief Size of the previous block or part of the allocated area of the 0280 * previous block. 0281 * 0282 * This field is only valid if the previous block is free. This case is 0283 * indicated by a cleared @c HEAP_PREV_BLOCK_USED flag in the 0284 * @a size_and_flag field of the current block. 0285 * 0286 * In a used block only the @a size_and_flag field needs to be valid. The 0287 * @a prev_size field of the current block is maintained by the previous 0288 * block. The current block can use the @a prev_size field in the next block 0289 * for allocation. 0290 */ 0291 uintptr_t prev_size; 0292 0293 #ifdef HEAP_PROTECTION 0294 Heap_Protection_block_begin Protection_begin; 0295 #endif 0296 0297 /** 0298 * @brief Contains the size of the current block and a flag which indicates 0299 * if the previous block is free or used. 0300 * 0301 * If the flag @c HEAP_PREV_BLOCK_USED is set, then the previous block is 0302 * used, otherwise the previous block is free. A used previous block may 0303 * claim the @a prev_size field for allocation. This trick allows to 0304 * decrease the overhead in the used blocks by the size of the @a prev_size 0305 * field. As sizes are required to be multiples of two, the least 0306 * significant bits would be always zero. We use this bit to store the flag. 0307 * 0308 * This field is always valid. 0309 */ 0310 uintptr_t size_and_flag; 0311 0312 #ifdef HEAP_PROTECTION 0313 Heap_Protection_block_end Protection_end; 0314 #endif 0315 0316 /** 0317 * @brief Pointer to the next free block or part of the allocated area. 0318 * 0319 * This field is page size aligned and begins of the allocated area in case 0320 * the block is used. 0321 * 0322 * This field is only valid if the block is free and thus part of the free 0323 * block list. 0324 */ 0325 Heap_Block *next; 0326 0327 /** 0328 * @brief Pointer to the previous free block or part of the allocated area. 0329 * 0330 * This field is only valid if the block is free and thus part of the free 0331 * block list. 0332 */ 0333 Heap_Block *prev; 0334 }; 0335 0336 /** 0337 * @brief Control block used to manage a heap. 0338 */ 0339 struct Heap_Control { 0340 Heap_Block free_list; 0341 uintptr_t page_size; 0342 uintptr_t min_block_size; 0343 uintptr_t area_begin; 0344 uintptr_t area_end; 0345 Heap_Block *first_block; 0346 Heap_Block *last_block; 0347 Heap_Statistics stats; 0348 #ifdef HEAP_PROTECTION 0349 Heap_Protection Protection; 0350 #endif 0351 }; 0352 0353 /** 0354 * @brief Heap area structure for table based heap initialization and 0355 * extension. 0356 * 0357 * @see Heap_Initialization_or_extend_handler. 0358 */ 0359 typedef struct { 0360 void *begin; 0361 uintptr_t size; 0362 } Heap_Area; 0363 0364 /** 0365 * @brief Heap initialization and extend handler type. 0366 * 0367 * This helps to do a table based heap initialization and extension. Create a 0368 * table of Heap_Area elements and iterate through it. Set the handler to 0369 * _Heap_Initialize() in the first iteration and then to _Heap_Extend(). 0370 * 0371 * @see Heap_Area, _Heap_Initialize(), _Heap_Extend(), or _Heap_No_extend(). 0372 */ 0373 typedef uintptr_t (*Heap_Initialization_or_extend_handler)( 0374 Heap_Control *heap, 0375 void *area_begin, 0376 uintptr_t area_size, 0377 uintptr_t page_size_or_unused 0378 ); 0379 0380 /** 0381 * @brief Extends the memory available for the heap. 0382 * 0383 * There are no alignment requirements for the memory area. The memory area 0384 * must be big enough to contain some maintenance blocks. It must not overlap 0385 * parts of the current heap memory areas. Disconnected memory areas added to 0386 * the heap will lead to used blocks which cover the gaps. Extending with an 0387 * inappropriate memory area will corrupt the heap resulting in undefined 0388 * behaviour. 0389 * 0390 * @param[in, out] heap The heap to extend. 0391 * @param[out] area_begin The start address of the area to extend the @a heap with. 0392 * @param area_size The size of the area in bytes. 0393 * @param unused Is not used, only provided to have the same signature as _Heap_Initialize(). 0394 * 0395 * @retval some_value The extended space available for allocation after successful extension. 0396 * @retval 0 The heap extension failed. 0397 * 0398 * @see Heap_Initialization_or_extend_handler. 0399 */ 0400 uintptr_t _Heap_Extend( 0401 Heap_Control *heap, 0402 void *area_begin, 0403 uintptr_t area_size, 0404 uintptr_t unused 0405 ); 0406 0407 /** 0408 * @brief This function returns always zero. 0409 * 0410 * This function only returns zero and does nothing else. 0411 * 0412 * @param unused_0 This parameter does nothing. 0413 * @param unused_1 This parameter does nothing. 0414 * @param unused_2 This parameter does nothing. 0415 * @param unused_3 This parameter does nothing. 0416 * 0417 * @see Heap_Initialization_or_extend_handler. 0418 */ 0419 uintptr_t _Heap_No_extend( 0420 Heap_Control *unused_0, 0421 void *unused_1, 0422 uintptr_t unused_2, 0423 uintptr_t unused_3 0424 ); 0425 0426 /** 0427 * @brief Aligns the value to a given alignment, rounding up. 0428 * 0429 * @param value The value to be aligned. 0430 * @param alignment The alignment for the value. 0431 * 0432 * @return The @a value aligned to the given @a alignment, rounded up. 0433 */ 0434 static inline uintptr_t _Heap_Align_up( 0435 uintptr_t value, 0436 uintptr_t alignment 0437 ) 0438 { 0439 uintptr_t remainder = value % alignment; 0440 0441 if ( remainder != 0 ) { 0442 return value - remainder + alignment; 0443 } else { 0444 return value; 0445 } 0446 } 0447 0448 /** 0449 * @brief Returns the minimal Heap Block size for the given page_size. 0450 * 0451 * @param page_size The page size for the heap. 0452 * 0453 * @return The minimal Heap Block size for the given @a page_size. 0454 */ 0455 static inline uintptr_t _Heap_Min_block_size( uintptr_t page_size ) 0456 { 0457 return _Heap_Align_up( sizeof( Heap_Block ), page_size ); 0458 } 0459 0460 /** 0461 * @brief Returns the worst case overhead to manage a memory area. 0462 * 0463 * @param page_size The page size to calculate the worst case memory manage overhead. 0464 * 0465 * @return The worst case overhead to manage a memory area. 0466 */ 0467 static inline uintptr_t _Heap_Area_overhead( 0468 uintptr_t page_size 0469 ) 0470 { 0471 if ( page_size != 0 ) { 0472 page_size = _Heap_Align_up( page_size, CPU_ALIGNMENT ); 0473 } else { 0474 page_size = CPU_ALIGNMENT; 0475 } 0476 0477 /* 0478 * Account for a potential alignment of the area begin address to a page 0479 * boundary, the first block, and the last block. The last block consists 0480 * only of a block header. 0481 */ 0482 return page_size - 1 + _Heap_Min_block_size( page_size ) + 0483 HEAP_BLOCK_HEADER_SIZE; 0484 } 0485 0486 /** 0487 * @brief Returns the size with administration and alignment overhead for one 0488 * allocation. 0489 * 0490 * @param page_size The page size for the allocation. 0491 * @param size The size to allocate. 0492 * @param alignment The alignment that needs to be considered. 0493 * 0494 * @return The size with administration and alignment overhead for one allocation. 0495 */ 0496 static inline uintptr_t _Heap_Size_with_overhead( 0497 uintptr_t page_size, 0498 uintptr_t size, 0499 uintptr_t alignment 0500 ) 0501 { 0502 if ( page_size != 0 ) { 0503 page_size = _Heap_Align_up( page_size, CPU_ALIGNMENT ); 0504 } else { 0505 page_size = CPU_ALIGNMENT; 0506 } 0507 0508 if ( page_size < alignment ) { 0509 page_size = alignment; 0510 } 0511 0512 return HEAP_BLOCK_HEADER_SIZE + page_size - 1 + size; 0513 } 0514 0515 /** @} */ 0516 0517 #ifdef __cplusplus 0518 } 0519 #endif 0520 0521 #endif 0522 /* end of include file */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |