1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*
8 * File : memheap.c
9 *
10 * Change Logs:
11 * Date Author Notes
12 * 2012-04-10 Bernard first implementation
13 * 2012-10-16 Bernard add the mutex lock for heap object.
14 * 2012-12-29 Bernard memheap can be used as system heap.
15 * change mutex lock to semaphore lock.
16 * 2013-04-10 Bernard add rt_memheap_realloc function.
17 * 2013-05-24 Bernard fix the rt_memheap_realloc issue.
18 * 2013-07-11 Grissiom fix the memory block splitting issue.
19 * 2013-07-15 Grissiom optimize rt_memheap_realloc
20 */
21
22 #include <rthw.h>
23 #include <rtthread.h>
24
25 #ifdef RT_USING_MEMHEAP
26
27 /* dynamic pool magic and mask */
28 #define RT_MEMHEAP_MAGIC 0x1ea01ea0
29 #define RT_MEMHEAP_MASK 0xfffffffe
30 #define RT_MEMHEAP_USED 0x01
31 #define RT_MEMHEAP_FREED 0x00
32
33 #define RT_MEMHEAP_IS_USED(i) ((i)->magic & RT_MEMHEAP_USED)
34 #define RT_MEMHEAP_MINIALLOC 12
35
36 #define RT_MEMHEAP_SIZE RT_ALIGN(sizeof(struct rt_memheap_item), RT_ALIGN_SIZE)
37 #define MEMITEM_SIZE(item) ((rt_ubase_t)item->next - (rt_ubase_t)item - RT_MEMHEAP_SIZE)
38
39 /*
40 * The initialized memory pool will be:
41 * +-----------------------------------+--------------------------+
42 * | whole freed memory block | Used Memory Block Tailer |
43 * +-----------------------------------+--------------------------+
44 *
45 * block_list --> whole freed memory block
46 *
47 * The length of Used Memory Block Tailer is 0,
48 * which is prevents block merging across list
49 */
rt_memheap_init(struct rt_memheap * memheap,const char * name,void * start_addr,rt_size_t size)50 rt_err_t rt_memheap_init(struct rt_memheap *memheap,
51 const char *name,
52 void *start_addr,
53 rt_size_t size)
54 {
55 struct rt_memheap_item *item;
56
57 RT_ASSERT(memheap != RT_NULL);
58
59 /* initialize pool object */
60 rt_object_init(&(memheap->parent), RT_Object_Class_MemHeap, name);
61
62 memheap->start_addr = start_addr;
63 memheap->pool_size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
64 memheap->available_size = memheap->pool_size - (2 * RT_MEMHEAP_SIZE);
65 memheap->max_used_size = memheap->pool_size - memheap->available_size;
66
67 /* initialize the free list header */
68 item = &(memheap->free_header);
69 item->magic = RT_MEMHEAP_MAGIC;
70 item->pool_ptr = memheap;
71 item->next = RT_NULL;
72 item->prev = RT_NULL;
73 item->next_free = item;
74 item->prev_free = item;
75
76 /* set the free list to free list header */
77 memheap->free_list = item;
78
79 /* initialize the first big memory block */
80 item = (struct rt_memheap_item *)start_addr;
81 item->magic = RT_MEMHEAP_MAGIC;
82 item->pool_ptr = memheap;
83 item->next = RT_NULL;
84 item->prev = RT_NULL;
85 item->next_free = item;
86 item->prev_free = item;
87
88 item->next = (struct rt_memheap_item *)
89 ((rt_uint8_t *)item + memheap->available_size + RT_MEMHEAP_SIZE);
90 item->prev = item->next;
91
92 /* block list header */
93 memheap->block_list = item;
94
95 /* place the big memory block to free list */
96 item->next_free = memheap->free_list->next_free;
97 item->prev_free = memheap->free_list;
98 memheap->free_list->next_free->prev_free = item;
99 memheap->free_list->next_free = item;
100
101 /* move to the end of memory pool to build a small tailer block,
102 * which prevents block merging
103 */
104 item = item->next;
105 /* it's a used memory block */
106 item->magic = RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED;
107 item->pool_ptr = memheap;
108 item->next = (struct rt_memheap_item *)start_addr;
109 item->prev = (struct rt_memheap_item *)start_addr;
110 /* not in free list */
111 item->next_free = item->prev_free = RT_NULL;
112
113 /* initialize semaphore lock */
114 rt_sem_init(&(memheap->lock), name, 1, RT_IPC_FLAG_FIFO);
115
116 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
117 ("memory heap: start addr 0x%08x, size %d, free list header 0x%08x\n",
118 start_addr, size, &(memheap->free_header)));
119
120 return RT_EOK;
121 }
122 RTM_EXPORT(rt_memheap_init);
123
rt_memheap_detach(struct rt_memheap * heap)124 rt_err_t rt_memheap_detach(struct rt_memheap *heap)
125 {
126 RT_ASSERT(heap);
127 RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
128 RT_ASSERT(rt_object_is_systemobject(&heap->parent));
129
130 rt_object_detach(&(heap->lock.parent.parent));
131 rt_object_detach(&(heap->parent));
132
133 /* Return a successful completion. */
134 return RT_EOK;
135 }
136 RTM_EXPORT(rt_memheap_detach);
137
rt_memheap_alloc(struct rt_memheap * heap,rt_size_t size)138 void *rt_memheap_alloc(struct rt_memheap *heap, rt_size_t size)
139 {
140 rt_err_t result;
141 rt_uint32_t free_size;
142 struct rt_memheap_item *header_ptr;
143
144 RT_ASSERT(heap != RT_NULL);
145 RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
146
147 /* align allocated size */
148 size = RT_ALIGN(size, RT_ALIGN_SIZE);
149 if (size < RT_MEMHEAP_MINIALLOC)
150 size = RT_MEMHEAP_MINIALLOC;
151
152 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("allocate %d on heap:%8.*s",
153 size, RT_NAME_MAX, heap->parent.name));
154
155 if (size < heap->available_size)
156 {
157 /* search on free list */
158 free_size = 0;
159
160 /* lock memheap */
161 result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
162 if (result != RT_EOK)
163 {
164 rt_set_errno(result);
165
166 return RT_NULL;
167 }
168
169 /* get the first free memory block */
170 header_ptr = heap->free_list->next_free;
171 while (header_ptr != heap->free_list && free_size < size)
172 {
173 /* get current freed memory block size */
174 free_size = MEMITEM_SIZE(header_ptr);
175 if (free_size < size)
176 {
177 /* move to next free memory block */
178 header_ptr = header_ptr->next_free;
179 }
180 }
181
182 /* determine if the memory is available. */
183 if (free_size >= size)
184 {
185 /* a block that satisfies the request has been found. */
186
187 /* determine if the block needs to be split. */
188 if (free_size >= (size + RT_MEMHEAP_SIZE + RT_MEMHEAP_MINIALLOC))
189 {
190 struct rt_memheap_item *new_ptr;
191
192 /* split the block. */
193 new_ptr = (struct rt_memheap_item *)
194 (((rt_uint8_t *)header_ptr) + size + RT_MEMHEAP_SIZE);
195
196 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
197 ("split: block[0x%08x] nextm[0x%08x] prevm[0x%08x] to new[0x%08x]\n",
198 header_ptr,
199 header_ptr->next,
200 header_ptr->prev,
201 new_ptr));
202
203 /* mark the new block as a memory block and freed. */
204 new_ptr->magic = RT_MEMHEAP_MAGIC;
205
206 /* put the pool pointer into the new block. */
207 new_ptr->pool_ptr = heap;
208
209 /* break down the block list */
210 new_ptr->prev = header_ptr;
211 new_ptr->next = header_ptr->next;
212 header_ptr->next->prev = new_ptr;
213 header_ptr->next = new_ptr;
214
215 /* remove header ptr from free list */
216 header_ptr->next_free->prev_free = header_ptr->prev_free;
217 header_ptr->prev_free->next_free = header_ptr->next_free;
218 header_ptr->next_free = RT_NULL;
219 header_ptr->prev_free = RT_NULL;
220
221 /* insert new_ptr to free list */
222 new_ptr->next_free = heap->free_list->next_free;
223 new_ptr->prev_free = heap->free_list;
224 heap->free_list->next_free->prev_free = new_ptr;
225 heap->free_list->next_free = new_ptr;
226 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new ptr: next_free 0x%08x, prev_free 0x%08x\n",
227 new_ptr->next_free,
228 new_ptr->prev_free));
229
230 /* decrement the available byte count. */
231 heap->available_size = heap->available_size -
232 size -
233 RT_MEMHEAP_SIZE;
234 if (heap->pool_size - heap->available_size > heap->max_used_size)
235 heap->max_used_size = heap->pool_size - heap->available_size;
236 }
237 else
238 {
239 /* decrement the entire free size from the available bytes count. */
240 heap->available_size = heap->available_size - free_size;
241 if (heap->pool_size - heap->available_size > heap->max_used_size)
242 heap->max_used_size = heap->pool_size - heap->available_size;
243
244 /* remove header_ptr from free list */
245 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
246 ("one block: block[0x%08x], next_free 0x%08x, prev_free 0x%08x\n",
247 header_ptr,
248 header_ptr->next_free,
249 header_ptr->prev_free));
250
251 header_ptr->next_free->prev_free = header_ptr->prev_free;
252 header_ptr->prev_free->next_free = header_ptr->next_free;
253 header_ptr->next_free = RT_NULL;
254 header_ptr->prev_free = RT_NULL;
255 }
256
257 /* Mark the allocated block as not available. */
258 header_ptr->magic |= RT_MEMHEAP_USED;
259
260 /* release lock */
261 rt_sem_release(&(heap->lock));
262
263 /* Return a memory address to the caller. */
264 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
265 ("alloc mem: memory[0x%08x], heap[0x%08x], size: %d\n",
266 (void *)((rt_uint8_t *)header_ptr + RT_MEMHEAP_SIZE),
267 header_ptr,
268 size));
269
270 return (void *)((rt_uint8_t *)header_ptr + RT_MEMHEAP_SIZE);
271 }
272
273 /* release lock */
274 rt_sem_release(&(heap->lock));
275 }
276
277 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("allocate memory: failed\n"));
278
279 /* Return the completion status. */
280 return RT_NULL;
281 }
282 RTM_EXPORT(rt_memheap_alloc);
283
rt_memheap_realloc(struct rt_memheap * heap,void * ptr,rt_size_t newsize)284 void *rt_memheap_realloc(struct rt_memheap *heap, void *ptr, rt_size_t newsize)
285 {
286 rt_err_t result;
287 rt_size_t oldsize;
288 struct rt_memheap_item *header_ptr;
289 struct rt_memheap_item *new_ptr;
290
291 RT_ASSERT(heap);
292 RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
293
294 if (newsize == 0)
295 {
296 rt_memheap_free(ptr);
297
298 return RT_NULL;
299 }
300 /* align allocated size */
301 newsize = RT_ALIGN(newsize, RT_ALIGN_SIZE);
302 if (newsize < RT_MEMHEAP_MINIALLOC)
303 newsize = RT_MEMHEAP_MINIALLOC;
304
305 if (ptr == RT_NULL)
306 {
307 return rt_memheap_alloc(heap, newsize);
308 }
309
310 /* get memory block header and get the size of memory block */
311 header_ptr = (struct rt_memheap_item *)
312 ((rt_uint8_t *)ptr - RT_MEMHEAP_SIZE);
313 oldsize = MEMITEM_SIZE(header_ptr);
314 /* re-allocate memory */
315 if (newsize > oldsize)
316 {
317 void *new_ptr;
318 struct rt_memheap_item *next_ptr;
319
320 /* lock memheap */
321 result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
322 if (result != RT_EOK)
323 {
324 rt_set_errno(result);
325 return RT_NULL;
326 }
327
328 next_ptr = header_ptr->next;
329
330 /* header_ptr should not be the tail */
331 RT_ASSERT(next_ptr > header_ptr);
332
333 /* check whether the following free space is enough to expand */
334 if (!RT_MEMHEAP_IS_USED(next_ptr))
335 {
336 rt_int32_t nextsize;
337
338 nextsize = MEMITEM_SIZE(next_ptr);
339 RT_ASSERT(next_ptr > 0);
340
341 /* Here is the ASCII art of the situation that we can make use of
342 * the next free node without alloc/memcpy, |*| is the control
343 * block:
344 *
345 * oldsize free node
346 * |*|-----------|*|----------------------|*|
347 * newsize >= minialloc
348 * |*|----------------|*|-----------------|*|
349 */
350 if (nextsize + oldsize > newsize + RT_MEMHEAP_MINIALLOC)
351 {
352 /* decrement the entire free size from the available bytes count. */
353 heap->available_size = heap->available_size - (newsize - oldsize);
354 if (heap->pool_size - heap->available_size > heap->max_used_size)
355 heap->max_used_size = heap->pool_size - heap->available_size;
356
357 /* remove next_ptr from free list */
358 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
359 ("remove block: block[0x%08x], next_free 0x%08x, prev_free 0x%08x",
360 next_ptr,
361 next_ptr->next_free,
362 next_ptr->prev_free));
363
364 next_ptr->next_free->prev_free = next_ptr->prev_free;
365 next_ptr->prev_free->next_free = next_ptr->next_free;
366 next_ptr->next->prev = next_ptr->prev;
367 next_ptr->prev->next = next_ptr->next;
368
369 /* build a new one on the right place */
370 next_ptr = (struct rt_memheap_item *)((char *)ptr + newsize);
371
372 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
373 ("new free block: block[0x%08x] nextm[0x%08x] prevm[0x%08x]",
374 next_ptr,
375 next_ptr->next,
376 next_ptr->prev));
377
378 /* mark the new block as a memory block and freed. */
379 next_ptr->magic = RT_MEMHEAP_MAGIC;
380
381 /* put the pool pointer into the new block. */
382 next_ptr->pool_ptr = heap;
383
384 next_ptr->prev = header_ptr;
385 next_ptr->next = header_ptr->next;
386 header_ptr->next->prev = next_ptr;
387 header_ptr->next = next_ptr;
388
389 /* insert next_ptr to free list */
390 next_ptr->next_free = heap->free_list->next_free;
391 next_ptr->prev_free = heap->free_list;
392 heap->free_list->next_free->prev_free = next_ptr;
393 heap->free_list->next_free = next_ptr;
394 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new ptr: next_free 0x%08x, prev_free 0x%08x",
395 next_ptr->next_free,
396 next_ptr->prev_free));
397
398 /* release lock */
399 rt_sem_release(&(heap->lock));
400
401 return ptr;
402 }
403 }
404
405 /* release lock */
406 rt_sem_release(&(heap->lock));
407
408 /* re-allocate a memory block */
409 new_ptr = (void *)rt_memheap_alloc(heap, newsize);
410 if (new_ptr != RT_NULL)
411 {
412 rt_memcpy(new_ptr, ptr, oldsize < newsize ? oldsize : newsize);
413 rt_memheap_free(ptr);
414 }
415
416 return new_ptr;
417 }
418
419 /* don't split when there is less than one node space left */
420 if (newsize + RT_MEMHEAP_SIZE + RT_MEMHEAP_MINIALLOC >= oldsize)
421 return ptr;
422
423 /* lock memheap */
424 result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
425 if (result != RT_EOK)
426 {
427 rt_set_errno(result);
428
429 return RT_NULL;
430 }
431
432 /* split the block. */
433 new_ptr = (struct rt_memheap_item *)
434 (((rt_uint8_t *)header_ptr) + newsize + RT_MEMHEAP_SIZE);
435
436 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
437 ("split: block[0x%08x] nextm[0x%08x] prevm[0x%08x] to new[0x%08x]\n",
438 header_ptr,
439 header_ptr->next,
440 header_ptr->prev,
441 new_ptr));
442
443 /* mark the new block as a memory block and freed. */
444 new_ptr->magic = RT_MEMHEAP_MAGIC;
445 /* put the pool pointer into the new block. */
446 new_ptr->pool_ptr = heap;
447
448 /* break down the block list */
449 new_ptr->prev = header_ptr;
450 new_ptr->next = header_ptr->next;
451 header_ptr->next->prev = new_ptr;
452 header_ptr->next = new_ptr;
453
454 /* determine if the block can be merged with the next neighbor. */
455 if (!RT_MEMHEAP_IS_USED(new_ptr->next))
456 {
457 struct rt_memheap_item *free_ptr;
458
459 /* merge block with next neighbor. */
460 free_ptr = new_ptr->next;
461 heap->available_size = heap->available_size - MEMITEM_SIZE(free_ptr);
462
463 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
464 ("merge: right node 0x%08x, next_free 0x%08x, prev_free 0x%08x\n",
465 header_ptr, header_ptr->next_free, header_ptr->prev_free));
466
467 free_ptr->next->prev = new_ptr;
468 new_ptr->next = free_ptr->next;
469
470 /* remove free ptr from free list */
471 free_ptr->next_free->prev_free = free_ptr->prev_free;
472 free_ptr->prev_free->next_free = free_ptr->next_free;
473 }
474
475 /* insert the split block to free list */
476 new_ptr->next_free = heap->free_list->next_free;
477 new_ptr->prev_free = heap->free_list;
478 heap->free_list->next_free->prev_free = new_ptr;
479 heap->free_list->next_free = new_ptr;
480 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new free ptr: next_free 0x%08x, prev_free 0x%08x\n",
481 new_ptr->next_free,
482 new_ptr->prev_free));
483
484 /* increment the available byte count. */
485 heap->available_size = heap->available_size + MEMITEM_SIZE(new_ptr);
486
487 /* release lock */
488 rt_sem_release(&(heap->lock));
489
490 /* return the old memory block */
491 return ptr;
492 }
493 RTM_EXPORT(rt_memheap_realloc);
494
rt_memheap_free(void * ptr)495 void rt_memheap_free(void *ptr)
496 {
497 rt_err_t result;
498 struct rt_memheap *heap;
499 struct rt_memheap_item *header_ptr, *new_ptr;
500 rt_uint32_t insert_header;
501
502 /* NULL check */
503 if (ptr == RT_NULL) return;
504
505 /* set initial status as OK */
506 insert_header = 1;
507 new_ptr = RT_NULL;
508 header_ptr = (struct rt_memheap_item *)
509 ((rt_uint8_t *)ptr - RT_MEMHEAP_SIZE);
510
511 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("free memory: memory[0x%08x], block[0x%08x]\n",
512 ptr, header_ptr));
513
514 /* check magic */
515 RT_ASSERT((header_ptr->magic & RT_MEMHEAP_MASK) == RT_MEMHEAP_MAGIC);
516 RT_ASSERT(header_ptr->magic & RT_MEMHEAP_USED);
517 /* check whether this block of memory has been over-written. */
518 RT_ASSERT((header_ptr->next->magic & RT_MEMHEAP_MASK) == RT_MEMHEAP_MAGIC);
519
520 /* get pool ptr */
521 heap = header_ptr->pool_ptr;
522
523 RT_ASSERT(heap);
524 RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
525
526 /* lock memheap */
527 result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
528 if (result != RT_EOK)
529 {
530 rt_set_errno(result);
531
532 return ;
533 }
534
535 /* Mark the memory as available. */
536 header_ptr->magic &= ~RT_MEMHEAP_USED;
537 /* Adjust the available number of bytes. */
538 heap->available_size = heap->available_size + MEMITEM_SIZE(header_ptr);
539
540 /* Determine if the block can be merged with the previous neighbor. */
541 if (!RT_MEMHEAP_IS_USED(header_ptr->prev))
542 {
543 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("merge: left node 0x%08x\n",
544 header_ptr->prev));
545
546 /* adjust the available number of bytes. */
547 heap->available_size = heap->available_size + RT_MEMHEAP_SIZE;
548
549 /* yes, merge block with previous neighbor. */
550 (header_ptr->prev)->next = header_ptr->next;
551 (header_ptr->next)->prev = header_ptr->prev;
552
553 /* move header pointer to previous. */
554 header_ptr = header_ptr->prev;
555 /* don't insert header to free list */
556 insert_header = 0;
557 }
558
559 /* determine if the block can be merged with the next neighbor. */
560 if (!RT_MEMHEAP_IS_USED(header_ptr->next))
561 {
562 /* adjust the available number of bytes. */
563 heap->available_size = heap->available_size + RT_MEMHEAP_SIZE;
564
565 /* merge block with next neighbor. */
566 new_ptr = header_ptr->next;
567
568 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
569 ("merge: right node 0x%08x, next_free 0x%08x, prev_free 0x%08x\n",
570 new_ptr, new_ptr->next_free, new_ptr->prev_free));
571
572 new_ptr->next->prev = header_ptr;
573 header_ptr->next = new_ptr->next;
574
575 /* remove new ptr from free list */
576 new_ptr->next_free->prev_free = new_ptr->prev_free;
577 new_ptr->prev_free->next_free = new_ptr->next_free;
578 }
579
580 if (insert_header)
581 {
582 /* no left merge, insert to free list */
583 header_ptr->next_free = heap->free_list->next_free;
584 header_ptr->prev_free = heap->free_list;
585 heap->free_list->next_free->prev_free = header_ptr;
586 heap->free_list->next_free = header_ptr;
587
588 RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
589 ("insert to free list: next_free 0x%08x, prev_free 0x%08x\n",
590 header_ptr->next_free, header_ptr->prev_free));
591 }
592
593 /* release lock */
594 rt_sem_release(&(heap->lock));
595 }
596 RTM_EXPORT(rt_memheap_free);
597
598 #ifdef RT_USING_MEMHEAP_AS_HEAP
599 static struct rt_memheap _heap;
600
rt_system_heap_init(void * begin_addr,void * end_addr)601 void rt_system_heap_init(void *begin_addr, void *end_addr)
602 {
603 /* initialize a default heap in the system */
604 rt_memheap_init(&_heap,
605 "heap",
606 begin_addr,
607 (rt_uint32_t)end_addr - (rt_uint32_t)begin_addr);
608 }
609
rt_malloc(rt_size_t size)610 void *rt_malloc(rt_size_t size)
611 {
612 void *ptr;
613
614 /* try to allocate in system heap */
615 ptr = rt_memheap_alloc(&_heap, size);
616 if (ptr == RT_NULL)
617 {
618 struct rt_object *object;
619 struct rt_list_node *node;
620 struct rt_memheap *heap;
621 struct rt_object_information *information;
622
623 /* try to allocate on other memory heap */
624 information = rt_object_get_information(RT_Object_Class_MemHeap);
625 RT_ASSERT(information != RT_NULL);
626 for (node = information->object_list.next;
627 node != &(information->object_list);
628 node = node->next)
629 {
630 object = rt_list_entry(node, struct rt_object, list);
631 heap = (struct rt_memheap *)object;
632
633 RT_ASSERT(heap);
634 RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
635
636 /* not allocate in the default system heap */
637 if (heap == &_heap)
638 continue;
639
640 ptr = rt_memheap_alloc(heap, size);
641 if (ptr != RT_NULL)
642 break;
643 }
644 }
645
646 return ptr;
647 }
648 RTM_EXPORT(rt_malloc);
649
rt_free(void * rmem)650 void rt_free(void *rmem)
651 {
652 rt_memheap_free(rmem);
653 }
654 RTM_EXPORT(rt_free);
655
rt_realloc(void * rmem,rt_size_t newsize)656 void *rt_realloc(void *rmem, rt_size_t newsize)
657 {
658 void *new_ptr;
659 struct rt_memheap_item *header_ptr;
660
661 if (rmem == RT_NULL)
662 return rt_malloc(newsize);
663
664 if (newsize == 0)
665 {
666 rt_free(rmem);
667 return RT_NULL;
668 }
669
670 /* get old memory item */
671 header_ptr = (struct rt_memheap_item *)
672 ((rt_uint8_t *)rmem - RT_MEMHEAP_SIZE);
673
674 new_ptr = rt_memheap_realloc(header_ptr->pool_ptr, rmem, newsize);
675 if (new_ptr == RT_NULL && newsize != 0)
676 {
677 /* allocate memory block from other memheap */
678 new_ptr = rt_malloc(newsize);
679 if (new_ptr != RT_NULL && rmem != RT_NULL)
680 {
681 rt_size_t oldsize;
682
683 /* get the size of old memory block */
684 oldsize = MEMITEM_SIZE(header_ptr);
685 if (newsize > oldsize)
686 rt_memcpy(new_ptr, rmem, oldsize);
687 else
688 rt_memcpy(new_ptr, rmem, newsize);
689
690 rt_free(rmem);
691 }
692 }
693
694 return new_ptr;
695 }
696 RTM_EXPORT(rt_realloc);
697
rt_calloc(rt_size_t count,rt_size_t size)698 void *rt_calloc(rt_size_t count, rt_size_t size)
699 {
700 void *ptr;
701 rt_size_t total_size;
702
703 total_size = count * size;
704 ptr = rt_malloc(total_size);
705 if (ptr != RT_NULL)
706 {
707 /* clean memory */
708 rt_memset(ptr, 0, total_size);
709 }
710
711 return ptr;
712 }
713 RTM_EXPORT(rt_calloc);
714
715 #endif
716
717 #endif
718