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 */ 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 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 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 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 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 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 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 650 void rt_free(void *rmem) 651 { 652 rt_memheap_free(rmem); 653 } 654 RTM_EXPORT(rt_free); 655 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 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