memheap.c 24 KB

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