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:
parent
3cfd8a350b
commit
81d37d0320
@ -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 *newnode;
|
||||||
FAR struct mm_allocnode_s *next;
|
FAR struct mm_allocnode_s *next;
|
||||||
|
FAR struct mm_freenode_s *prev;
|
||||||
size_t precedingsize;
|
size_t precedingsize;
|
||||||
|
|
||||||
|
/* Mark node free */
|
||||||
|
|
||||||
|
node->preceding &= ~MM_MASK_BIT;
|
||||||
|
|
||||||
/* Get the node the next node after the allocation. */
|
/* Get the node the next node after the allocation. */
|
||||||
|
|
||||||
next = (FAR struct mm_allocnode_s *)((FAR char *)node + node->size);
|
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
|
/* Make sure that there is space to convert the preceding
|
||||||
* mm_allocnode_s into an mm_freenode_s. I think that this should
|
* 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;
|
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 */
|
/* Set up the size of the new node */
|
||||||
|
|
||||||
newnode->size = (uintptr_t)next - (uintptr_t)newnode;
|
newnode->size = (uintptr_t)next - (uintptr_t)newnode;
|
||||||
newnode->preceding = precedingsize | MM_ALLOC_BIT;
|
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 */
|
/* Fix the preceding size of the next node */
|
||||||
|
|
||||||
next->preceding = newnode->size | (next->preceding & MM_ALLOC_BIT);
|
next->preceding = newnode->size | (next->preceding & MM_ALLOC_BIT);
|
||||||
|
Loading…
Reference in New Issue
Block a user