source: rtems/cpukit/score/inline/rtems/score/heap.inl @ fb29a8de

4.104.115
Last change on this file since fb29a8de was fb29a8de, checked in by Joel Sherrill <joel.sherrill@…>, on 08/01/09 at 18:18:26

2009-08-01 Joel Sherrill <joel.sherrill@…>

  • score/inline/rtems/score/heap.inl, score/src/heapresizeblock.c: Simplify routine.
  • Property mode set to 100644
File size: 9.8 KB
Line 
1/**
2 *  @file  rtems/score/heap.inl
3 *
4 *  This file contains the static inline implementation of the inlined
5 *  routines from the heap handler.
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2008.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.com/license/LICENSE.
15 *
16 *  $Id$
17 */
18
19#ifndef _RTEMS_SCORE_HEAP_H
20# error "Never use <rtems/score/heap.inl> directly; include <rtems/score/heap.h> instead."
21#endif
22
23#ifndef _RTEMS_SCORE_HEAP_INL
24#define _RTEMS_SCORE_HEAP_INL
25
26/**
27 *  @addtogroup ScoreHeap
28 *  @{
29 */
30
31#include <rtems/score/address.h>
32
33/**
34 *  This function returns the head of the specified heap.
35 *
36 *  @param[in] the_heap points to the heap being operated upon
37 *
38 *  @return This method returns a pointer to the dummy head of the free
39 *          block list.
40 */
41RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Head (
42  Heap_Control *the_heap
43)
44{
45  return &the_heap->free_list;
46}
47
48/**
49 *  This function returns the tail of the specified heap.
50 *
51 *  @param[in] the_heap points to the heap being operated upon
52 *
53 *  @return This method returns a pointer to the dummy tail of the heap
54 *          free list.
55 */
56RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Tail (
57  Heap_Control *the_heap
58)
59{
60  return &the_heap->free_list;
61}
62
63/**
64 *  Return the first free block of the specified heap.
65 *
66 *  @param[in] the_heap points to the heap being operated upon
67 *
68 *  @return This method returns a pointer to the first free block.
69 */
70RTEMS_INLINE_ROUTINE Heap_Block *_Heap_First (
71  Heap_Control *the_heap
72)
73{
74  return _Heap_Head(the_heap)->next;
75}
76
77/**
78 *  Return the last free block of the specified heap.
79 *
80 *  @param[in] the_heap points to the heap being operated upon
81 *
82 *  @return This method returns a pointer to the last block on the free list.
83 */
84RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Last (
85  Heap_Control *the_heap
86)
87{
88  return _Heap_Tail(the_heap)->prev;
89}
90
91/**
92 *  This function removes 'the_block' from doubly-linked list.
93 *
94 *  @param[in] the_block is the block to remove from the heap used block
95 *             list.
96 */
97RTEMS_INLINE_ROUTINE void _Heap_Block_remove (
98  Heap_Block *the_block
99)
100{
101  Heap_Block *block = the_block;
102
103  Heap_Block *next = block->next;
104  Heap_Block *prev = block->prev;
105  prev->next = next;
106  next->prev = prev;
107}
108
109/**
110 *  This function replaces @a old_block by @a new_block in doubly-linked list.
111 *  When a block is allocated, the memory is allocated from the low memory
112 *  address range of the block.  This means that the upper address range of
113 *  the memory block must be added to the free block list in place of the
114 *  lower address portion being allocated.  This method is also used as part
115 *  of resizing a block.
116 *
117 *  @param[in] old_block is the block which is currently on the list.
118 *  @param[in] new_block is the new block which will replace it on the list.
119 */
120
121RTEMS_INLINE_ROUTINE void _Heap_Block_replace (
122  Heap_Block *old_block,
123  Heap_Block *new_block
124)
125{
126  Heap_Block *block = old_block;
127  Heap_Block *next = block->next;
128  Heap_Block *prev = block->prev;
129
130  block = new_block;
131  block->next = next;
132  block->prev = prev;
133  next->prev = prev->next = block;
134}
135
136/**
137 *  This function inserts @a the_block after @a prev_block
138 *  in the doubly-linked free block list.
139 *
140 *  @param[in] prev_block is the previous block in the free list.
141 *  @param[in] the_block is the block being freed.
142 */
143RTEMS_INLINE_ROUTINE void _Heap_Block_insert_after (
144  Heap_Block *prev_block,
145  Heap_Block *the_block
146)
147{
148  Heap_Block *prev = prev_block;
149  Heap_Block *block = the_block;
150
151  Heap_Block *next = prev->next;
152  block->next  = next;
153  block->prev  = prev;
154  next->prev = prev->next = block;
155}
156
157/**
158 *  Return true if @a value is a multiple of @a alignment,  false otherwise
159 *
160 *  @param[in] value is the address to verify alignment of.
161 *  @param[in] alignment is the alignment factor to verify.
162 *
163 *  @return This method returns true if the address is aligned and false
164 *          otherwise.
165 */
166RTEMS_INLINE_ROUTINE bool _Heap_Is_aligned (
167  uint32_t  value,
168  uint32_t  alignment
169)
170{
171  return (value % alignment) == 0;
172}
173
174/**
175 *  Align @a *value up to the nearest multiple of @a alignment.
176 *
177 *  @param[in] value is a pointer to be aligned.
178 *  @param[in] alignment is the alignment value.
179 *
180 *  @return Upon return, @a value will contain the aligned result.
181 */
182RTEMS_INLINE_ROUTINE void _Heap_Align_up (
183  uint32_t *value,
184  uint32_t  alignment
185)
186{
187  uint32_t v = *value;
188  uint32_t a = alignment;
189  uint32_t r = v % a;
190  *value = r ? v - r + a : v;
191}
192
193/**
194 *  Align @a *value down to the nearest multiple of @a alignment.
195 *
196 *  @param[in] value is a pointer to be aligned.
197 *  @param[in] alignment is the alignment value.
198 *
199 *  @return Upon return, @a value will contain the aligned result.
200 */
201RTEMS_INLINE_ROUTINE void _Heap_Align_down (
202  uint32_t *value,
203  uint32_t  alignment
204)
205{
206  uint32_t v = *value;
207  *value = v - (v % alignment);
208}
209
210/**
211 *  Return true if @a ptr is aligned at @a alignment boundary,
212 *  false otherwise.
213 *
214 *  @param[in] ptr is the pointer to verify alignment of.
215 *  @param[in] alignment is the alignment factor.
216 *
217 *  @return This method returns true if @a ptr is aligned at @a alignment
218 *          boundary, and false otherwise.
219 */
220RTEMS_INLINE_ROUTINE bool _Heap_Is_aligned_ptr (
221  void      *ptr,
222  uint32_t  alignment
223)
224{
225  return (_H_p2u(ptr) % alignment) == 0;
226}
227
228/**
229 *  Align @a *value up to the nearest multiple of @a alignment.
230 *
231 *  @param[in] value is a pointer to be aligned.
232 *  @param[in] alignment is the alignment value.
233 *
234 *  @return Upon return, @a value will contain the aligned result.
235 */
236RTEMS_INLINE_ROUTINE void _Heap_Align_up_uptr (
237  _H_uptr_t *value,
238  uint32_t  alignment
239)
240{
241  _H_uptr_t remainder;
242  _H_uptr_t v = *value;
243
244  remainder = v % alignment;
245
246  if ( remainder )
247    *value = v - remainder + alignment;
248}
249
250/**
251 *  Align @a *value down to the nearest multiple of @a alignment.
252 *
253 *  @param[in] value is a pointer to be aligned.
254 *  @param[in] alignment is the alignment value.
255 *
256 *  @return Upon return, @a value will contain the aligned result.
257 */
258RTEMS_INLINE_ROUTINE void _Heap_Align_down_uptr (
259  _H_uptr_t *value,
260  uint32_t  alignment
261)
262{
263  _H_uptr_t v = *value;
264  *value = v - (v % alignment);
265}
266
267/**
268 *  This function calculates and returns a block's location (address)
269 *  in the heap based upon a base address @a base and an @a offset.
270 *
271 *  @param[in] base is the base address of the memory area.
272 *  @param[in] offset is the byte offset into @a base.
273 *
274 *  @return This method returns a pointer to the block's address.
275 */
276RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Block_at(
277  void     *base,
278  int32_t   offset
279)
280{
281  return (Heap_Block *) _Addresses_Add_offset( base, offset );
282}
283
284/**
285 *  This function returns the starting address of the portion of @a the_block
286 *  which the user may access.
287 *
288 *  @param[in] the_block is the heap block to find the user area of.
289 *
290 *  @return This method returns a pointer to the start of the user area in
291 *          the block.
292 */
293RTEMS_INLINE_ROUTINE void *_Heap_User_area (
294  Heap_Block *the_block
295)
296{
297  return (void *) _Addresses_Add_offset ( the_block, HEAP_BLOCK_USER_OFFSET );
298}
299
300/**
301 *  Fill @a *the_block with the address of the beginning of the block given
302 *  pointer to the user accessible area @a base.
303 *
304 *  @param[in] the_heap points to the heap being operated upon
305 *  @param[in] base points to the user area in the block.
306 *  @param[in] the_block will be the address of the heap block.
307 *
308 *  @return This method returns a pointer to the heap block based upon the
309 *               given heap and user pointer.
310 */
311RTEMS_INLINE_ROUTINE void _Heap_Start_of_block (
312  Heap_Control  *the_heap,
313  void          *base,
314  Heap_Block   **the_block
315)
316{
317  _H_uptr_t addr = _H_p2u(base);
318  /* The address passed could be greater than the block address plus
319   * HEAP_BLOCK_USER_OFFSET as _Heap_Allocate_aligned() may produce such user
320   * pointers. To get rid of this offset we need to align the address down
321   * to the nearest 'page_size' boundary. */
322  _Heap_Align_down_uptr ( &addr, the_heap->page_size );
323  *the_block = (Heap_Block *)(addr - HEAP_BLOCK_USER_OFFSET);
324}
325
326/**
327 *  This function returns true if the previous block of @a the_block
328 *  is in use, and false otherwise.
329 *
330 *  @param[in] the_block is the block to operate upon.
331 *
332 *  @return This method returns true if the previous block is used and false
333 *          if the previous block is free.
334 */
335RTEMS_INLINE_ROUTINE bool _Heap_Is_prev_used (
336  Heap_Block *the_block
337)
338{
339  return (the_block->size & HEAP_PREV_USED);
340}
341
342/**
343 *  This function returns the size of @a the_block in bytes.
344 *
345 *  @param[in] the_block is the block to operate upon.
346 *
347 *  @return This method returns the size of the specified heap block in bytes.
348 */
349RTEMS_INLINE_ROUTINE uint32_t _Heap_Block_size (
350  Heap_Block *the_block
351)
352{
353  return (the_block->size & ~HEAP_PREV_USED);
354}
355
356/**
357 *  This function returns true if @a the_block is within the memory area
358 *  managed by @a the_heap, and false otherwise.
359 *
360 *  @param[in] the_heap points to the heap being operated upon
361 *  @param[in] the_block is the block address to check.
362 *
363 *  @return This method returns true if @a the_block appears to have been
364 *          allocated from @a the_heap, and false otherwise.
365 */
366RTEMS_INLINE_ROUTINE bool _Heap_Is_block_in (
367  Heap_Control *the_heap,
368  Heap_Block   *the_block
369)
370{
371  return _Addresses_Is_in_range( the_block, the_heap->start, the_heap->final );
372}
373
374/**
375 *  This function returns the maximum size of the heap.
376 *
377 *  @param[in] the_heap points to the heap being operated upon
378 *
379 *  @return This method returns the total amount of memory
380 *          allocated to the heap.
381 */
382RTEMS_INLINE_ROUTINE int32_t _Heap_Get_size (
383  Heap_Control *the_heap
384)
385{
386  return _Addresses_Subtract( the_heap->end, the_heap->begin );
387}
388
389/**@}*/
390
391#endif
392/* end of include file */
Note: See TracBrowser for help on using the repository browser.