in RISC-V_RV32_THEAD_SMART_CDS/libs/mm/mm_free.c [70:177]
void mm_free(struct mm_heap_s *heap, void *mem, void *caller)
{
struct mm_freenode_s *node;
struct mm_freenode_s *prev;
struct mm_freenode_s *next;
(void)caller;
//mvdbg("Freeing %p\n", mem);
/* Protect against attempts to free a NULL reference */
if (!mem)
{
return;
}
#if defined(CONFIG_MM_DETECT_ERROR)
struct m_dbg_hdr *hdr = (struct m_dbg_hdr *)((uint8_t *)mem - MDBG_SZ_HEAD);
if (!mdbg_check_magic_hdr(hdr)) {
printf("mm magic hdr err %p,%p\n", hdr->caller, caller);
mm_leak_search_chunk(hdr);
/* force trapping */
*(volatile void **)0 = 0;
}
if (!mdbg_check_magic_end(hdr)) {
printf("mm magic end err %p,%p", hdr->caller, caller);
mm_leak_search_chunk(hdr+1);
/* force trapping */
*(volatile void **)0 = 0;
}
mem = hdr;
hdr->magic = MAGIC_FREE;
mm_leak_del_chunk(hdr);
#endif
/* We need to hold the MM semaphore while we muck with the
* nodelist.
*/
mm_takesemaphore(heap);
/* Map the memory chunk into a free node */
node = (struct mm_freenode_s *)((uint32_t)mem - SIZEOF_MM_ALLOCNODE);
node->preceding &= ~MM_ALLOC_BIT;
/* Check if the following node is free and, if so, merge it */
next = (struct mm_freenode_s *)((uint32_t)node + node->size);
if ((next->preceding & MM_ALLOC_BIT) == 0)
{
struct mm_allocnode_s *andbeyond;
/* Get the node following the next node (which will
* become the new next node). We know that we can never
* index past the tail chunk because it is always allocated.
*/
andbeyond = (struct mm_allocnode_s *)((uint32_t)next + next->size);
/* Remove the next node. There must be a predecessor,
* but there may not be a successor node.
*/
//DEBUGASSERT(next->blink);
next->blink->flink = next->flink;
if (next->flink)
{
next->flink->blink = next->blink;
}
/* Then merge the two chunks */
node->size += next->size;
andbeyond->preceding = node->size | (andbeyond->preceding & MM_ALLOC_BIT);
next = (struct mm_freenode_s *)andbeyond;
}
/* Check if the preceding node is also free and, if so, merge
* it with this node
*/
prev = (struct mm_freenode_s *)((uint32_t)node - node->preceding);
if ((prev->preceding & MM_ALLOC_BIT) == 0)
{
/* Remove the node. There must be a predecessor, but there may
* not be a successor node.
*/
//DEBUGASSERT(prev->blink);
prev->blink->flink = prev->flink;
if (prev->flink)
{
prev->flink->blink = prev->blink;
}
/* Then merge the two chunks */
prev->size += node->size;
next->preceding = prev->size | (next->preceding & MM_ALLOC_BIT);
node = prev;
}
/* Add the merged node to the nodelist */
mm_addfreechunk(heap, node);
mm_givesemaphore(heap);
}