mm/mm_heap: add mm_delaylist to mm_heap_s struct

Change-Id: I2ffaec5557bf2dd2021baa6cda84bb5318425caa
Signed-off-by: ligd <liguiding@fishsemi.com>
This commit is contained in:
ligd 2020-04-07 22:21:42 +08:00 committed by patacongo
parent 78eb9f73dd
commit 1d2396353e
4 changed files with 118 additions and 4 deletions

View File

@ -224,6 +224,13 @@ struct mm_freenode_s
FAR struct mm_freenode_s *blink;
};
#ifdef __KERNEL__
struct mm_delaynode_s
{
struct mm_delaynode_s *flink;
};
#endif
/* What is the size of the freenode? */
#define MM_PTR_SIZE sizeof(FAR struct mm_freenode_s *)
@ -263,6 +270,12 @@ struct mm_heap_s
*/
struct mm_freenode_s mm_nodelist[MM_NNODES];
#ifdef __KERNEL__
/* Free delay list, for some situation can't do free immdiately */
struct mm_delaynode_s mm_delaylist;
#endif
};
/****************************************************************************

View File

@ -42,8 +42,31 @@
#include <assert.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/mm/mm.h>
/****************************************************************************
* Private Functions
****************************************************************************/
#ifdef __KERNEL__
static void mm_add_delaylist(FAR struct mm_heap_s *heap, FAR void *mem)
{
FAR struct mm_delaynode_s *new = mem;
irqstate_t flags;
/* Delay the deallocation until a more appropriate time. */
flags = enter_critical_section();
new->flink = heap->mm_delaylist.flink;
heap->mm_delaylist.flink = new;
leave_critical_section(flags);
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -72,11 +95,37 @@ void mm_free(FAR struct mm_heap_s *heap, FAR void *mem)
return;
}
/* We need to hold the MM semaphore while we muck with the
* nodelist.
*/
#ifdef __KERNEL__
/* Check current environment */
if (up_interrupt_context())
{
/* We are in ISR, add to mm_delaylist */
mm_add_delaylist(heap, mem);
return;
}
else if (mm_trysemaphore(heap) == 0)
{
/* Got the sem, do free immediately */
}
else if (sched_idletask())
{
/* We are in IDLE task & can't get sem, add to mm_delaylist */
mm_add_delaylist(heap, mem);
return;
}
else
#endif
{
/* We need to hold the MM semaphore while we muck with the
* nodelist.
*/
mm_takesemaphore(heap);
}
mm_takesemaphore(heap);
DEBUGASSERT(mm_heapmember(heap, mem));
/* Map the memory chunk into a free node */

View File

@ -175,6 +175,12 @@ void mm_initialize(FAR struct mm_heap_s *heap, FAR void *heapstart,
heap->mm_nregions = 0;
#endif
#ifdef __KERNEL__
/* Initialize mm_delaylist */
heap->mm_delaylist.flink = NULL;
#endif
/* Initialize the node array */
memset(heap->mm_nodelist, 0, sizeof(struct mm_freenode_s) * MM_NNODES);

View File

@ -44,6 +44,7 @@
#include <debug.h>
#include <string.h>
#include <nuttx/arch.h>
#include <nuttx/mm/mm.h>
/****************************************************************************
@ -54,6 +55,45 @@
# define NULL ((void *)0)
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
#ifdef __KERNEL__
static void mm_free_delaylist(FAR struct mm_heap_s *heap)
{
FAR struct mm_delaynode_s *tmp;
irqstate_t flags;
/* Move the delay list to local */
flags = enter_critical_section();
tmp = heap->mm_delaylist.flink;
heap->mm_delaylist.flink = NULL;
leave_critical_section(flags);
/* Test if the delayed is empty */
while (tmp)
{
FAR void *address;
/* Get the first delayed deallocation */
address = tmp;
tmp = tmp->flink;
/* The address should always be non-NULL since that was checked in the
* 'while' condition above.
*/
mm_free(heap, address);
}
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -76,6 +116,12 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size)
void *ret = NULL;
int ndx;
#ifdef __KERNEL__
/* Firstly, free mm_delaylist */
mm_free_delaylist(heap);
#endif
/* Ignore zero-length allocations */
if (size < 1)