source: rtems/cpukit/score/include/rtems/score/heap.h @ 235aaf0

4.104.115
Last change on this file since 235aaf0 was 235aaf0, checked in by Joel Sherrill <joel.sherrill@…>, on 08/09/09 at 15:23:10

2009-08-09 Xi Yang <hiyangxi@…>

  • libcsupport/Makefile.am, posix/Makefile.am, rtems/Makefile.am, sapi/Makefile.am, score/Makefile.am, score/include/rtems/score/heap.h: HEAP_BLOCK_USED_OVERHEAD was under by one uint32_t. This showed up in the unlimited and heapwalk tests on ARM targets.
  • Property mode set to 100644
File size: 16.7 KB
Line 
1/**
2 *  @file  rtems/score/heap.h
3 *
4 *  This include file contains the information pertaining to the Heap
5 *  Handler.  A heap is a doubly linked list of variable size
6 *  blocks which are allocated using the first fit method.  Garbage
7 *  collection is performed each time a block is returned to the heap by
8 *  coalescing neighbor blocks.  Control information for both allocated
9 *  and unallocated blocks is contained in the heap space.  A heap control
10 *  structure contains control information for the heap.
11 *
12 *  FIXME: the alignment routines could be made faster should we require only
13 *         powers of two to be supported both for 'page_size' and for
14 *         'alignment' arguments. However, both workspace and malloc heaps are
15 *         initialized with CPU_HEAP_ALIGNMENT as 'page_size', and while all
16 *         the BSPs seem to use CPU_ALIGNMENT (that is power of two) as
17 *         CPU_HEAP_ALIGNMENT, for whatever reason CPU_HEAP_ALIGNMENT is only
18 *         required to be multiple of CPU_ALIGNMENT and explicitly not
19 *         required to be a power of two.
20 *
21 *  COPYRIGHT (c) 1989-2006.
22 *  On-Line Applications Research Corporation (OAR).
23 *
24 *  The license and distribution terms for this file may be
25 *  found in the file LICENSE in this distribution or at
26 *  http://www.rtems.com/license/LICENSE.
27 *
28 *  $Id$
29 */
30
31#ifndef _RTEMS_SCORE_HEAP_H
32#define _RTEMS_SCORE_HEAP_H
33
34/**
35 *  @defgroup ScoreHeap Heap Handler
36 *
37 *  This handler encapsulates functionality which provides the foundation
38 *  Heap services used in all of the APIs supported by RTEMS.
39 */
40/**@{*/
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/**
47 * This type defines unsigned integer type to store 'void*'. Analog of C99
48 * 'uintptr_t'. This should work on 16/32/64 bit architectures.
49 *
50 * FIXME: Something like this should better be defined by
51 *        'rtems/score/types.h' and used here.
52 */
53
54typedef uintptr_t _H_uptr_t;
55
56/**
57 *  Forward reference
58 *
59 *  @ref Heap_Block
60 */
61typedef struct Heap_Block_struct Heap_Block;
62
63/**
64 *  The following defines the data structure used to manage individual blocks
65 *  in a heap.  When the block is allocated, the 'next' and 'prev' fields, as
66 *  well as 'prev_size' field of the next block, are not used by the heap
67 *  manager and thus the address returned for the block starts at the address
68 *  of the 'next' field and the size of the user accessible area includes the
69 *  size of the 'prev_size' field.
70 *
71 *  @note The 'next' and 'prev' pointers are only valid when the block is free.
72 *     Caution must be taken to ensure that every block is large enough to
73 *     hold them and that they are not accessed while the block is actually
74 *     allocated (i.e., not free).
75 *
76 *  @note The 'prev_size' field is only valid when HEAP_PREV_USED bit is clear
77 *     in the 'size' field indicating that previous block is not allocated.
78 *     If the bit is set, the 'prev_size' field is part of user-accessible
79 *     space of the previous allocated block and thus shouldn't be accessed
80 *     by the heap manager code. This trick allows to further decrease
81 *     overhead in the used blocks to the size of 'size' field (4 bytes).
82 *
83 */
84
85struct Heap_Block_struct {
86  /** size of prev block (if prev block is free) */
87  uint32_t  prev_size;
88  /** size of block in bytes and status of prev block */
89  uint32_t  size;
90  /** pointer to the next free block */
91  Heap_Block *next;
92  /** pointer to the previous free block */
93  Heap_Block *prev;
94};
95
96/**
97 *  This flag used in the 'size' field of each heap block to indicate
98 *  if previous block is free or in use. As sizes are always multiples of
99 *  4, the 2 least significant bits would always be 0, and we use one of them
100 *  to store the flag.
101 */
102
103#define HEAP_PREV_USED    1u    /* indicates previous block is in use */
104
105/**
106 *  The following constants reflect various requirements of the
107 *  heap data structures which impact the management of a heap.
108 */
109
110#define HEAP_MIN_BLOCK_SIZE (sizeof(Heap_Block))
111
112/**
113 *  Offset of the block header from the block pointer. Equal to the
114 *  offsetof(Heap_Block.size).
115 */
116#define HEAP_BLOCK_HEADER_OFFSET (sizeof(uint32_t))
117
118/**
119 *  Offset of user data pointer from the block pointer. Equal to the
120 *  offset of(Heap_Block.next).
121 */
122#define HEAP_BLOCK_USER_OFFSET (sizeof(uint32_t) * 2)
123
124/**
125 *  This is the number of bytes of overhead in a used block.
126 *  Equal to the sizeof(Heap_Block.previous and next).
127 */
128#define HEAP_BLOCK_USED_OVERHEAD (sizeof(uint32_t) * 2)
129
130/** Size of the permanent dummy last block. */
131#define HEAP_OVERHEAD HEAP_BLOCK_USER_OFFSET
132
133/**
134 *  Run-time heap statistics.
135 *
136 *  @note (double)searches/allocs gives mean number of searches per alloc while
137 *        max_search gives maximum number of searches ever performed on a
138 *        single call to alloc.
139 *
140 *  @note the statistics is always gathered. I believe the imposed overhead is
141 *        rather small. Feel free to make it compile-time option if you think
142 *        the overhead is too high for your application.
143 */
144typedef struct {
145  /** instance number of this heap */
146  uint32_t instance;
147  /** the size of the memory for heap */
148  intptr_t size;
149  /** current free size */
150  intptr_t free_size;
151  /** minimum free size ever */
152  intptr_t min_free_size;
153  /** current number of free blocks */
154  uint32_t free_blocks;
155  /** maximum number of free blocks ever */
156  uint32_t max_free_blocks;
157  /** current number of used blocks */
158  uint32_t used_blocks;
159  /** maximum number of blocks searched ever */
160  uint32_t max_search;
161  /** total number of successful calls to alloc */
162  uint32_t allocs;
163  /** total number of searches ever */
164  uint32_t searches;
165  /** total number of suceessful calls to free */
166  uint32_t frees;
167  /** total number of successful resizes */
168  uint32_t resizes;
169} Heap_Statistics;
170
171/**
172 *  Control block used to manage each heap.
173 */
174typedef struct {
175  /** head and tail of circular list of free blocks */
176  Heap_Block  free_list;
177  /** allocation unit and alignment */
178  uint32_t  page_size;
179  /** minimum block size aligned on page_size */
180  uint32_t  min_block_size;
181  /** first address of memory for the heap */
182  void       *begin;
183  /** first address past end of memory for the heap */
184  void       *end;
185  /** first valid block address in the heap */
186  Heap_Block *start;
187  /** last valid block address in the heap */
188  Heap_Block *final;
189  /** run-time statistics */
190  Heap_Statistics stats;
191} Heap_Control;
192
193/**
194 *  Status codes for _Heap_Extend
195 */
196
197typedef enum {
198  HEAP_EXTEND_SUCCESSFUL,
199  HEAP_EXTEND_ERROR,
200  HEAP_EXTEND_NOT_IMPLEMENTED
201} Heap_Extend_status;
202
203/**
204 *  Status codes for _Heap_Resize_block
205 */
206
207typedef enum {
208  HEAP_RESIZE_SUCCESSFUL,
209  HEAP_RESIZE_UNSATISFIED,
210  HEAP_RESIZE_FATAL_ERROR
211} Heap_Resize_status;
212
213/**
214 *  Status codes for _Heap_Get_information
215 */
216
217typedef enum {
218  HEAP_GET_INFORMATION_SUCCESSFUL = 0,
219  HEAP_GET_INFORMATION_BLOCK_ERROR
220} Heap_Get_information_status;
221
222/**
223 *  Information block returned by the Heap routines used to
224 *  obtain heap information.  This information is returned about
225 *  either free or used blocks.
226 */
227typedef struct {
228  /** Number of blocks of this type. */
229  uint32_t number;
230  /** Largest blocks of this type. */
231  uint32_t largest;
232  /** Total size of the blocks of this type. */
233  uint32_t total;
234} Heap_Information;
235
236/**
237 *  Information block returned by _Heap_Get_information
238 */
239typedef struct {
240  /** This field is information on the used blocks in the heap. */
241  Heap_Information Free;
242  /** This field is information on the used blocks in the heap. */
243  Heap_Information Used;
244} Heap_Information_block;
245
246/**
247 *  This routine initializes @a the_heap record to manage the
248 *  contiguous heap of @a size bytes which starts at @a starting_address.
249 *  Blocks of memory are allocated from the heap in multiples of
250 *  @a page_size byte units. If @a page_size is 0 or is not multiple of
251 *  CPU_ALIGNMENT, it's aligned up to the nearest CPU_ALIGNMENT boundary.
252 *
253 *  @param[in] the_heap is the heap to operate upon
254 *  @param[in] starting_address is the starting address of the memory for
255 *         the heap
256 *  @param[in] size is the size in bytes of the memory area for the heap
257 *  @param[in] page_size is the size in bytes of the allocation unit
258 *
259 *  @return This method returns the maximum memory available.  If
260 *          unsuccessful, 0 will be returned.
261 */
262uint32_t   _Heap_Initialize(
263  Heap_Control *the_heap,
264  void         *starting_address,
265  intptr_t      size,
266  uint32_t      page_size
267);
268
269/**
270 *  This routine grows @a the_heap memory area using the size bytes which
271 *  begin at @a starting_address.
272 *
273 *  @param[in] the_heap is the heap to operate upon
274 *  @param[in] starting_address is the starting address of the memory
275 *         to add to the heap
276 *  @param[in] size is the size in bytes of the memory area to add
277 *  @param[in] amount_extended points to a user area to return the
278 *  @return a status indicating success or the reason for failure
279 *  @return *size filled in with the amount of memory added to the heap
280 */
281Heap_Extend_status _Heap_Extend(
282  Heap_Control *the_heap,
283  void         *starting_address,
284  intptr_t      size,
285  intptr_t     *amount_extended
286);
287
288/**
289 *  This function attempts to allocate a block of @a size bytes from
290 *  @a the_heap.  If insufficient memory is free in @a the_heap to allocate
291 *  a block of the requested size, then NULL is returned.
292 *
293 *  @param[in] the_heap is the heap to operate upon
294 *  @param[in] size is the amount of memory to allocate in bytes
295 *  @return NULL if unsuccessful and a pointer to the block if successful
296 */
297void *_Heap_Allocate(
298  Heap_Control *the_heap,
299  intptr_t      size
300);
301
302/**
303 *  This function attempts to allocate a memory block of @a size bytes from
304 *  @a the_heap so that the start of the user memory is aligned on the
305 *  @a alignment boundary. If @a alignment is 0, it is set to CPU_ALIGNMENT.
306 *  Any other value of @a alignment is taken "as is", i.e., even odd
307 *  alignments are possible.
308 *  Returns pointer to the start of the memory block if success, NULL if
309 *  failure.
310 *
311 *  @param[in] the_heap is the heap to operate upon
312 *  @param[in] size is the amount of memory to allocate in bytes
313 *  @param[in] alignment the required alignment
314 *  @return NULL if unsuccessful and a pointer to the block if successful
315 */
316void *_Heap_Allocate_aligned(
317  Heap_Control *the_heap,
318  intptr_t      size,
319  uint32_t      alignment
320);
321
322/**
323 *  This function sets @a *size to the size of the block of user memory
324 *  which begins at @a starting_address. The size returned in @a *size could
325 *  be greater than the size requested for allocation.
326 *  Returns true if the @a starting_address is in the heap, and false
327 *  otherwise.
328 *
329 *  @param[in] the_heap is the heap to operate upon
330 *  @param[in] starting_address is the starting address of the user block
331 *         to obtain the size of
332 *  @param[in] size points to a user area to return the size in
333 *  @return true if successfully able to determine the size, false otherwise
334 *  @return *size filled in with the size of the user area for this block
335 */
336bool _Heap_Size_of_user_area(
337  Heap_Control        *the_heap,
338  void                *starting_address,
339  intptr_t            *size
340);
341
342/**
343 *  This function tries to resize in place the block that is pointed to by the
344 *  @a starting_address to the new @a size.
345 *
346 *  @param[in] the_heap is the heap to operate upon
347 *  @param[in] starting_address is the starting address of the user block
348 *         to be resized
349 *  @param[in] size is the new size
350 *  @param[in] old_mem_size points to a user area to return the size of the
351 *         user memory area of the block before resizing.
352 *  @param[in] avail_mem_size points to a user area to return the size of
353 *         the user memory area of the free block that has been enlarged or
354 *         created due to resizing, 0 if none.
355 *  @return HEAP_RESIZE_SUCCESSFUL if successfully able to resize the block,
356 *          HEAP_RESIZE_UNSATISFIED if the block can't be resized in place,
357 *          HEAP_RESIZE_FATAL_ERROR if failure
358 *  @return *old_mem_size filled in with the size of the user memory area of
359 *          the block before resizing.
360 *  @return *avail_mem_size filled in with the size of the user memory area
361 *          of the free block that has been enlarged or created due to
362 *          resizing, 0 if none.
363 */
364Heap_Resize_status _Heap_Resize_block(
365  Heap_Control *the_heap,
366  void         *starting_address,
367  intptr_t      size,
368  intptr_t     *old_mem_size,
369  intptr_t     *avail_mem_size
370);
371
372/**
373 *  This routine returns the block of memory which begins
374 *  at @a starting_address to @a the_heap.  Any coalescing which is
375 *  possible with the freeing of this routine is performed.
376 *
377 *  @param[in] the_heap is the heap to operate upon
378 *  @param[in] start_address is the starting address of the user block
379 *         to free
380 *  @return true if successfully freed, false otherwise
381 */
382bool _Heap_Free(
383  Heap_Control *the_heap,
384  void         *start_address
385);
386
387/**
388 *  This routine walks the heap to verify its integrity.
389 *
390 *  @param[in] the_heap is the heap to operate upon
391 *  @param[in] source is a user specified integer which may be used to
392 *         indicate where in the application this was invoked from
393 *  @param[in] do_dump is set to true if errors should be printed
394 *  @return true if the test passed fine, false otherwise.
395 */
396bool _Heap_Walk(
397  Heap_Control *the_heap,
398  int           source,
399  bool          do_dump
400);
401
402/**
403 *  This routine walks the heap and tots up the free and allocated
404 *  sizes.
405 *
406 *  @param[in] the_heap pointer to heap header
407 *  @param[in] the_info pointer to a status information area
408 *  @return *the_info is filled with status information
409 *  @return 0=success, otherwise heap is corrupt.
410 */
411Heap_Get_information_status _Heap_Get_information(
412  Heap_Control            *the_heap,
413  Heap_Information_block  *the_info
414);
415
416/**
417 *  This heap routine returns information about the free blocks
418 *  in the specified heap.
419 *
420 *  @param[in] the_heap pointer to heap header.
421 *  @param[in] info pointer to the free block information.
422 *
423 *  @return free block information filled in.
424 */
425void _Heap_Get_free_information(
426  Heap_Control        *the_heap,
427  Heap_Information    *info
428);
429
430#if !defined(__RTEMS_APPLICATION__)
431
432/**
433 *  A pointer to unsigned integer conversion.
434 */
435#define _H_p2u(_p) ((_H_uptr_t)(_p))
436
437#include <rtems/score/heap.inl>
438
439/**
440 *  Convert user requested 'size' of memory block to the block size.
441 *
442 *  @note This is an internal routine used by _Heap_Allocate() and
443 *  _Heap_Allocate_aligned().  Refer to 'heap.c' for details.
444 *
445 *  @param[in] size is the size of the block requested
446 *  @param[in] page_size is the page size of this heap instance
447 *  @param[in] min_size is minimum size block that should be allocated
448 *         from this heap instance
449 *
450 *  @return This method returns block size on success, 0 if overflow occured.
451 */
452size_t _Heap_Calc_block_size(
453  size_t   size,
454  uint32_t page_size,
455  uint32_t min_size
456);
457
458/**
459 *  This method allocates a block of size @a alloc_size from @a the_block
460 *  belonging to @a the_heap. Split @a the_block if possible, otherwise
461 *  allocate it entirely.  When split, make the lower part used, and leave
462 *  the upper part free.
463 *
464 *  This is an internal routines used by _Heap_Allocate() and
465 *  _Heap_Allocate_aligned().  Refer to 'heap.c' for details.
466 *
467 *  @param[in] the_heap is the heap to operate upon
468 *  @param[in] the_block is the block to allocates the requested size from
469 *  @param[in] alloc_size is the requested number of bytes to take out of
470 *         the block
471 *
472 *  @return This methods returns the size of the allocated block.
473 */
474uint32_t _Heap_Block_allocate(
475  Heap_Control* the_heap,
476  Heap_Block*   the_block,
477  uint32_t      alloc_size
478);
479
480/**
481 *  Align @a *value up to the nearest multiple of @a alignment.
482 *
483 *  @param[in] value is a pointer to be aligned.
484 *  @param[in] alignment is the alignment value.
485 *
486 *  @return Upon return, @a value will contain the aligned result.
487 */
488void _Heap_Align_up_uptr (
489  _H_uptr_t *value,
490  uint32_t  alignment
491);
492
493/*
494 * Debug support
495 */
496
497#if defined(RTEMS_DEBUG)
498#define RTEMS_HEAP_DEBUG
499#endif
500
501/**
502 *  We do asserts only for heaps with instance number greater than 0 assuming
503 *  that the heap used for malloc is initialized first and thus has instance
504 *  number 0. Asserting malloc heap may lead to troubles as printf may invoke
505 *  malloc thus probably leading to infinite recursion.
506 */
507#if defined(RTEMS_HEAP_DEBUG)
508#include <assert.h>
509
510#define _HAssert(cond_) \
511  do { \
512    if (the_heap->stats.instance && !(cond_)) \
513      __assert(__FILE__, __LINE__, #cond_);  \
514  } while(0)
515
516#else  /* !defined(RTEMS_HEAP_DEBUG) */
517
518#define _HAssert(cond_) ((void)0)
519
520#endif /* !defined(RTEMS_HEAP_DEBUG) */
521
522#endif /* !defined(__RTEMS_APPLICATION__) */
523
524#ifdef __cplusplus
525}
526#endif
527
528/**@}*/
529
530#endif
531/* end of include file */
Note: See TracBrowser for help on using the repository browser.