mm_memalign: avoid two adjacent free nodes situation.

Original code assumes the previous node in physical must be
ALLOCED, but other thread may free the previous node between
mm_malloc() and mm_lock(), and the original code didn't condsider
this, which will cause two adjacent free nodes situation and this
should not be happened.

This commit will merge the previous node and node if the previous
node is free to avoid the situation discribed above.

Signed-off-by: wangbowen6 <wangbowen6@xiaomi.com>
This commit is contained in:
wangbowen6 2023-01-28 18:34:30 +08:00 committed by Xiang Xiao
parent 3cfd8a350b
commit 81d37d0320
1 changed files with 30 additions and 5 deletions

View File

@ -146,11 +146,18 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment,
{
FAR struct mm_allocnode_s *newnode;
FAR struct mm_allocnode_s *next;
FAR struct mm_freenode_s *prev;
size_t precedingsize;
/* Mark node free */
node->preceding &= ~MM_MASK_BIT;
/* Get the node the next node after the allocation. */
next = (FAR struct mm_allocnode_s *)((FAR char *)node + node->size);
prev = (FAR struct mm_freenode_s *)
((FAR char *)node - node->preceding);
/* Make sure that there is space to convert the preceding
* mm_allocnode_s into an mm_freenode_s. I think that this should
@ -184,16 +191,34 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment,
precedingsize = (uintptr_t)newnode - (uintptr_t)node;
}
/* If the previous node is free, merge node and previous node, then
* set up the node size.
*/
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;
}
precedingsize += prev->size;
node = (FAR struct mm_allocnode_s *)prev;
}
node->size = precedingsize;
/* Set up the size of the new node */
newnode->size = (uintptr_t)next - (uintptr_t)newnode;
newnode->preceding = precedingsize | MM_ALLOC_BIT;
/* Reduce the size of the original chunk and mark it not allocated, */
node->size = precedingsize;
node->preceding &= ~MM_MASK_BIT;
/* Fix the preceding size of the next node */
next->preceding = newnode->size | (next->preceding & MM_ALLOC_BIT);