summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-09-01 10:46:51 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-09-01 10:46:51 -0600
commitf23b744ac0c3750a0a1742b8ff7e18c63e45253c (patch)
treea9231d215cdb9bdb6cbb2932f877297f7c5f8874
parent83c30d32a3c84c9c7e992c8d1b29bf03e9fa8a3a (diff)
downloadnuttx-f23b744ac0c3750a0a1742b8ff7e18c63e45253c.tar.gz
nuttx-f23b744ac0c3750a0a1742b8ff7e18c63e45253c.tar.bz2
nuttx-f23b744ac0c3750a0a1742b8ff7e18c63e45253c.zip
Completes the implementation of sbrk() (untested)
-rw-r--r--nuttx/arch/arm/include/arch.h2
-rw-r--r--nuttx/arch/arm/src/a1x/Make.defs2
-rw-r--r--nuttx/arch/arm/src/armv7-a/arm_addrenv.c6
-rw-r--r--nuttx/arch/arm/src/armv7-a/arm_pgalloc.c280
-rw-r--r--nuttx/arch/arm/src/sama5/Make.defs2
-rw-r--r--nuttx/include/nuttx/addrenv.h20
-rw-r--r--nuttx/include/nuttx/arch.h2
-rw-r--r--nuttx/include/nuttx/mm.h4
-rw-r--r--nuttx/include/unistd.h4
-rw-r--r--nuttx/mm/Makefile12
-rwxr-xr-xnuttx/mm/kmm_sbrk.c5
-rw-r--r--nuttx/mm/mm_brkaddr.c5
-rw-r--r--nuttx/mm/mm_sbrk.c6
-rw-r--r--nuttx/mm/umm_malloc.c33
-rw-r--r--nuttx/mm/umm_sbrk.c5
-rw-r--r--nuttx/mm/umm_zalloc.c16
16 files changed, 364 insertions, 40 deletions
diff --git a/nuttx/arch/arm/include/arch.h b/nuttx/arch/arm/include/arch.h
index 1d1661c0d..2f1991622 100644
--- a/nuttx/arch/arm/include/arch.h
+++ b/nuttx/arch/arm/include/arch.h
@@ -135,9 +135,7 @@ struct group_addrenv_s
{
FAR uintptr_t *text[ARCH_TEXT_NSECTS];
FAR uintptr_t *data[ARCH_DATA_NSECTS];
-#if 0 /* Not yet implemented */
FAR uintptr_t *heap[ARCH_HEAP_NSECTS];
-#endif
};
typedef struct group_addrenv_s group_addrenv_t;
diff --git a/nuttx/arch/arm/src/a1x/Make.defs b/nuttx/arch/arm/src/a1x/Make.defs
index 92825cc12..6c53ce0e8 100644
--- a/nuttx/arch/arm/src/a1x/Make.defs
+++ b/nuttx/arch/arm/src/a1x/Make.defs
@@ -87,7 +87,7 @@ CMN_CSRCS += up_task_start.c up_pthread_start.c up_stackframe.c
endif
ifeq ($(CONFIG_ARCH_ADDRENV),y)
-CMN_CSRCS += arm_addrenv.c
+CMN_CSRCS += arm_addrenv.c arm_pgalloc.c
endif
ifeq ($(CONFIG_ELF),y)
diff --git a/nuttx/arch/arm/src/armv7-a/arm_addrenv.c b/nuttx/arch/arm/src/armv7-a/arm_addrenv.c
index de5df1473..fe765a182 100644
--- a/nuttx/arch/arm/src/armv7-a/arm_addrenv.c
+++ b/nuttx/arch/arm/src/armv7-a/arm_addrenv.c
@@ -199,7 +199,7 @@ static int up_addrenv_create_region(FAR uintptr_t **list,
}
DEBUGASSERT(MM_ISALIGNED(paddr));
- list[i] = (FAR uint32_t *)paddr;
+ list[i] = (FAR uintptr_t *)paddr;
/* Temporarily map the page into the virtual address space */
@@ -241,7 +241,7 @@ static int up_addrenv_create_region(FAR uintptr_t **list,
(uintptr_t)l2table +
ENTRIES_PER_L2TABLE * sizeof(uint32_t));
- /* Restore the original L1 page table entry */
+ /* Restore the scratch section L1 page table entry */
mmu_l1_restore(ARCH_SCRATCH_VBASE, l1save);
irqrestore(flags);
@@ -300,7 +300,7 @@ static void up_addrenv_destroy_region(FAR uintptr_t **list,
}
}
- /* Restore the original L1 page table entry */
+ /* Restore the scratch section L1 page table entry */
mmu_l1_restore(ARCH_SCRATCH_VBASE, l1save);
irqrestore(flags);
diff --git a/nuttx/arch/arm/src/armv7-a/arm_pgalloc.c b/nuttx/arch/arm/src/armv7-a/arm_pgalloc.c
new file mode 100644
index 000000000..e55e92c25
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-a/arm_pgalloc.c
@@ -0,0 +1,280 @@
+/****************************************************************************
+ * arch/arm/src/armv7/arm_pgalloc.c
+ *
+ * Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/sched.h>
+#include <nuttx/arch.h>
+#include <nuttx/addrenv.h>
+
+#include "cache.h"
+#include "mmu.h"
+
+#if defined(CONFIG_MM_PGALLOC) && defined(CONFIG_ARCH_USE_MMU)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: alloc_pgtable
+ *
+ * Description:
+ * Add one page table to a memory region.
+ *
+ ****************************************************************************/
+
+static uintptr_t alloc_pgtable(void)
+{
+ irqstate_t flags;
+ uintptr_t paddr;
+ FAR uint32_t *l2table;
+ uint32_t l1save;
+
+ /* Allocate one physical page for the L2 page table */
+
+ paddr = mm_pgalloc(1);
+ if (paddr)
+ {
+ DEBUGASSERT(MM_ISALIGNED(paddr));
+
+ /* Temporarily map the page into the virtual address space */
+
+ flags = irqsave();
+ l1save = mmu_l1_getentry(ARCH_SCRATCH_VBASE);
+ mmu_l1_setentry(paddr & ~SECTION_MASK, ARCH_SCRATCH_VBASE, MMU_MEMFLAGS);
+ l2table = (FAR uint32_t *)(ARCH_SCRATCH_VBASE | (paddr & SECTION_MASK));
+
+ /* Initialize the page table */
+
+ memset(l2table, 0, MM_PGSIZE);
+
+ /* Make sure that the initialized L2 table is flushed to physical
+ * memory.
+ */
+
+ arch_flush_dcache((uintptr_t)l2table,
+ (uintptr_t)l2table + MM_PGSIZE);
+
+ /* Restore the scratch section page table entry */
+
+ mmu_l1_restore(ARCH_SCRATCH_VBASE, l1save);
+ irqrestore(flags);
+ }
+
+ return paddr;
+}
+
+/****************************************************************************
+ * Name: get_pgtable
+ *
+ * Description:
+ * Return the physical address of the L2 page table corresponding to
+ * 'vaddr'
+ *
+ ****************************************************************************/
+
+static int get_pgtable(FAR group_addrenv_t *addrenv, uintptr_t vaddr)
+{
+ uint32_t l1entry;
+ uintptr_t paddr;
+ unsigned int hpoffset;
+ unsigned int hpndx;
+
+ /* The current implementation only supports extending the user heap
+ * region as part of the implementation of user sbrk().
+ */
+
+ DEBUGASSERT(vadddr >= CONFIG_ARCH_HEAP_VBASE && vaddr < ARCH_HEAP_VEND);
+
+ /* Get the current level 1 entry corresponding to this vaddr */
+
+ hpoffset = vaddr - CONFIG_ARCH_HEAP_VBASE;
+ if (hpoffset >= ARCH_HEAP_SIZE)
+ {
+ return 0;
+ }
+
+ hpndx = hpoffset >> 20;
+ l1entry = (uintptr_t)addrenv->heap[hpndx];
+ if (l1entry == 0)
+ {
+ /* No page table has been allocated... allocate one now */
+
+ paddr = alloc_pgtable();
+ if (paddr != 0)
+ {
+ /* Set the new level 1 page table entry in the address environment. */
+
+ l1entry = paddr | MMU_L1_PGTABFLAGS;
+ addrenv->heap[hpndx] = (FAR uintptr_t *)l1entry;
+
+ /* And instantiate the modified environment */
+
+ (void)up_addrenv_select(addrenv, NULL);
+ }
+ }
+
+ return l1entry & ~SECTION_MASK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pgalloc
+ *
+ * Description:
+ * If there is a page allocator in the configuration and if and MMU is
+ * available to map physical addresses to virtual address, then function
+ * must be provided by the platform-specific code. This is part of the
+ * implementation of sbrk(). This function will allocate the requested
+ * number of pages using the page allocator and map them into consecutive
+ * virtual addresses beginning with 'brkaddr'
+ *
+ * NOTE: This function does not use the up_ naming standard because it
+ * is indirectly callable from user-space code via a system trap.
+ * Therefore, it is a system interface and follows a different naming
+ * convention.
+ *
+ ****************************************************************************/
+
+int pgalloc(uintptr_t vaddr, unsigned int npages)
+{
+ FAR struct tcb_s *tcb = sched_self();
+ FAR struct task_group_s *group;
+ FAR uint32_t *l2table;
+ irqstate_t flags;
+ uintptr_t paddr;
+ uint32_t l1save;
+ unsigned int index;
+
+ DEBUGASSERT(tcb && tcb->group);
+ group = tcb->group;
+
+ /* The current implementation only supports extending the user heap
+ * region as part of the implementation of user sbrk(). This function
+ * needs to be expanded to also handle (1) extending the user stack
+ * space and (2) extending the kernel memory regions as well.
+ */
+
+ DEBUGASSERT((group->flags & GROUP_FLAG_ADDRENV) != 0);
+
+ /* vaddr = 0 means that no heap has yet been allocated */
+
+ if (vaddr == 0)
+ {
+ vaddr = CONFIG_ARCH_HEAP_VBASE;
+ }
+
+ DEBUGASSERT(vadddr >= CONFIG_ARCH_HEAP_VBASE && vaddr < ARCH_HEAP_VEND);
+ DEBUGASSERT(MM_ISALIGNED(vaddr));
+
+ for (; npages > 0; npages--)
+ {
+ /* Get the physical address of the level 2 page table */
+
+ paddr = get_pgtable(&group->addrenv, vaddr);
+ if (paddr == 0)
+ {
+ return -ENOMEM; /* ENOMEM might have correct meaning for sbrk? */
+ }
+
+ /* Temporarily map the level 2 page table into the "scratch" virtual
+ * address space
+ */
+
+ flags = irqsave();
+ l1save = mmu_l1_getentry(ARCH_SCRATCH_VBASE);
+ mmu_l1_setentry(paddr & ~SECTION_MASK, ARCH_SCRATCH_VBASE, MMU_MEMFLAGS);
+ l2table = (FAR uint32_t *)(ARCH_SCRATCH_VBASE | (paddr & SECTION_MASK));
+
+ /* Back up L2 entry with physical memory */
+
+ paddr = mm_pgalloc(1);
+ if (paddr == 0)
+ {
+ mmu_l1_restore(ARCH_SCRATCH_VBASE, l1save);
+ irqrestore(flags);
+ return -EAGAIN; /* ENOMEM has different meaning for sbrk */
+ }
+
+ /* The table divides a 1Mb address space up into 256 entries, each
+ * corresponding to 4Kb of address space. The page table index is
+ * related to the offset from the beginning of 1Mb region.
+ */
+
+ index = (vaddr & 0x000ff000) >> 12;
+
+ /* Map the .text region virtual address to this physical address */
+
+ DEBUGASSERT(l2table[index] == 0);
+ l2table[index] = paddr | MMU_L2_UDATAFLAGS;
+ vaddr += MM_PGSIZE;
+
+ /* Make sure that the modified L2 table is flushed to physical
+ * memory.
+ */
+
+ arch_flush_dcache((uintptr_t)&l2table[index],
+ (uintptr_t)&l2table[index] + sizeof(uint32_t));
+
+ /* Restore the scratch L1 page table entry */
+
+ mmu_l1_restore(ARCH_SCRATCH_VBASE, l1save);
+ irqrestore(flags);
+ }
+
+ return OK;
+}
+
+#endif /* CONFIG_MM_PGALLOC && CONFIG_ARCH_USE_MMU */
diff --git a/nuttx/arch/arm/src/sama5/Make.defs b/nuttx/arch/arm/src/sama5/Make.defs
index e2ecb9716..6daa81b5e 100644
--- a/nuttx/arch/arm/src/sama5/Make.defs
+++ b/nuttx/arch/arm/src/sama5/Make.defs
@@ -89,7 +89,7 @@ CMN_CSRCS += up_task_start.c up_pthread_start.c up_stackframe.c
endif
ifeq ($(CONFIG_ARCH_ADDRENV),y)
-CMN_CSRCS += arm_addrenv.c
+CMN_CSRCS += arm_addrenv.c arm_pgalloc.c
endif
ifeq ($(CONFIG_ELF),y)
diff --git a/nuttx/include/nuttx/addrenv.h b/nuttx/include/nuttx/addrenv.h
index 51bd79491..1825a0170 100644
--- a/nuttx/include/nuttx/addrenv.h
+++ b/nuttx/include/nuttx/addrenv.h
@@ -74,13 +74,14 @@
# define CONFIG_ARCH_TEXT_NPAGES 1
#endif
-#define CONFIG_ARCH_TEXT_SIZE (CONFIG_ARCH_TEXT_NPAGES * CONFIG_MM_PGSIZE)
+#define ARCH_TEXT_SIZE (CONFIG_ARCH_TEXT_NPAGES * CONFIG_MM_PGSIZE)
+#define ARCH_TEXT_VEND (CONFIG_ARCH_TEXT_VBASE + ARCH_TEXT_SIZE)
/* .bss/.data region */
#ifndef CONFIG_ARCH_DATA_VBASE
# error CONFIG_ARCH_DATA_VBASE not defined
-# define CONFIG_ARCH_DATA_VBASE (CONFIG_ARCH_TEXT_VBASE + CONFIG_ARCH_TEXT_SIZE)
+# define CONFIG_ARCH_DATA_VBASE (CONFIG_ARCH_TEXT_VBASE + ARCH_TEXT_SIZE)
#endif
#if (CONFIG_ARCH_DATA_VBASE & CONFIG_MM_MASK) != 0
@@ -92,13 +93,14 @@
# define CONFIG_ARCH_DATA_NPAGES 1
#endif
-#define CONFIG_ARCH_DATA_SIZE (CONFIG_ARCH_DATA_NPAGES * CONFIG_MM_PGSIZE)
+#define ARCH_DATA_SIZE (CONFIG_ARCH_DATA_NPAGES * CONFIG_MM_PGSIZE)
+#define ARCH_DATA_VEND (CONFIG_ARCH_DATA_VBASE + ARCH_DATA_SIZE)
/* Heap region */
#ifndef CONFIG_ARCH_HEAP_VBASE
# error CONFIG_ARCH_HEAP_VBASE not defined
-# define CONFIG_ARCH_HEAP_VBASE (CONFIG_ARCH_DATA_VBASE + CONFIG_ARCH_DATA_SIZE)
+# define CONFIG_ARCH_HEAP_VBASE (CONFIG_ARCH_DATA_VBASE + ARCH_DATA_SIZE)
#endif
#if (CONFIG_ARCH_HEAP_VBASE & CONFIG_MM_MASK) != 0
@@ -110,13 +112,14 @@
# define CONFIG_ARCH_HEAP_NPAGES 1
#endif
-#define CONFIG_ARCH_HEAP_SIZE (CONFIG_ARCH_HEAP_NPAGES * CONFIG_MM_PGSIZE)
+#define ARCH_HEAP_SIZE (CONFIG_ARCH_HEAP_NPAGES * CONFIG_MM_PGSIZE)
+#define ARCH_HEAP_VEND (CONFIG_ARCH_HEAP_VBASE + ARCH_HEAP_SIZE)
/* Stack region */
#ifndef CONFIG_ARCH_STACK_VBASE
# error CONFIG_ARCH_STACK_VBASE not defined
-# define CONFIG_ARCH_STACK_VBASE (CONFIG_ARCH_HEAP_VBASE + CONFIG_ARCH_HEAP_SIZE)
+# define CONFIG_ARCH_STACK_VBASE (CONFIG_ARCH_HEAP_VBASE + ARCH_HEAP_SIZE)
#endif
#if (CONFIG_ARCH_STACK_VBASE & CONFIG_MM_MASK) != 0
@@ -128,11 +131,12 @@
# define CONFIG_ARCH_STACK_NPAGES 1
#endif
-#define CONFIG_ARCH_STACK_SIZE (CONFIG_ARCH_STACK_NPAGES * CONFIG_MM_PGSIZE)
+#define ARCH_STACK_SIZE (CONFIG_ARCH_STACK_NPAGES * CONFIG_MM_PGSIZE)
+#define ARCH_STACK_VEND (CONFIG_ARCH_STACK_VBASE + ARCH_STACK_SIZE)
/* A single page scratch region used for temporary mappings */
-#define ARCH_SCRATCH_VBASE (CONFIG_ARCH_STACK_VBASE + CONFIG_ARCH_STACK_SIZE)
+#define ARCH_SCRATCH_VBASE (CONFIG_ARCH_STACK_VBASE + ARCH_STACK_SIZE)
/****************************************************************************
* Private Data
diff --git a/nuttx/include/nuttx/arch.h b/nuttx/include/nuttx/arch.h
index bb876ed85..cd4915411 100644
--- a/nuttx/include/nuttx/arch.h
+++ b/nuttx/include/nuttx/arch.h
@@ -689,7 +689,7 @@ void up_allocate_pgheap(FAR void **heap_start, size_t *heap_size);
*
****************************************************************************/
-#if defined(CONFIG_MM_PGALLOC) && defined(CONFIG_ARCH_USE_MMU)
+#ifdef CONFIG_ARCH_ADDRENV
int pgalloc(uintptr_t vaddr, unsigned int npages);
#endif
diff --git a/nuttx/include/nuttx/mm.h b/nuttx/include/nuttx/mm.h
index 6b5ec14c6..d810ef6ff 100644
--- a/nuttx/include/nuttx/mm.h
+++ b/nuttx/include/nuttx/mm.h
@@ -397,14 +397,14 @@ FAR void *kmm_brkaddr(int region);
/* Functions contained in mm_sbrk.c *****************************************/
-#if defined(CONFIG_MM_PGALLOC) && defined(CONFIG_ARCH_USE_MMU)
+#ifdef CONFIG_ARCH_ADDRENV
FAR void *mm_sbrk(FAR struct mm_heap_s *heap, intptr_t incr,
uintptr_t maxbreak);
#endif
/* Functions contained in kmm_sbrk.c ****************************************/
-#if defined(CONFIG_MM_PGALLOC) && defined(CONFIG_ARCH_USE_MMU)
+#ifdef CONFIG_ARCH_ADDRENV
FAR void *kmm_sbrk(intptr_t incr);
#endif
diff --git a/nuttx/include/unistd.h b/nuttx/include/unistd.h
index 51f4b24b6..641e2e469 100644
--- a/nuttx/include/unistd.h
+++ b/nuttx/include/unistd.h
@@ -47,7 +47,7 @@
* Pre-processor Definitions
****************************************************************************/
-/* The number of functions that may be registerd to be called
+/* The number of functions that may be registered to be called
* at program exit.
*/
@@ -149,7 +149,7 @@ ssize_t write(int fd, FAR const void *buf, size_t nbytes);
/* Memory management */
-#if defined(CONFIG_MM_PGALLOC) && defined(CONFIG_ARCH_USE_MMU)
+#ifdef CONFIG_ARCH_ADDRENV
FAR void *sbrk(intptr_t incr);
#endif
diff --git a/nuttx/mm/Makefile b/nuttx/mm/Makefile
index a62a1de93..4c5fe0e19 100644
--- a/nuttx/mm/Makefile
+++ b/nuttx/mm/Makefile
@@ -56,11 +56,9 @@ CSRCS += mm_shrinkchunk.c
CSRCS += mm_brkaddr.c mm_calloc.c mm_extend.c mm_free.c mm_mallinfo.c
CSRCS += mm_malloc.c mm_memalign.c mm_realloc.c mm_zalloc.c
-ifeq ($(CONFIG_MM_PGALLOC),y)
-ifeq ($(CONFIG_ARCH_USE_MMU),y)
+ifeq ($(CONFIG_ARCH_ADDRENV),y)
CSRCS += mm_sbrk.c
endif
-endif
# User allocator
@@ -68,11 +66,9 @@ CSRCS += umm_initialize.c umm_addregion.c umm_sem.c
CSRCS += umm_brkaddr.c umm_calloc.c umm_extend.c umm_free.c umm_mallinfo.c
CSRCS += umm_malloc.c umm_memalign.c umm_realloc.c umm_zalloc.c
-ifeq ($(CONFIG_MM_PGALLOC),y)
-ifeq ($(CONFIG_ARCH_USE_MMU),y)
+ifeq ($(CONFIG_ARCH_ADDRENV),y)
CSRCS += umm_sbrk.c
endif
-endif
# Kernel allocator
@@ -81,11 +77,9 @@ CSRCS += kmm_initialize.c kmm_addregion.c kmm_sem.c
CSRCS += kmm_brkaddr.c kmm_calloc.c kmm_extend.c kmm_free.c kmm_mallinfo.c
CSRCS += kmm_malloc.c kmm_memalign.c kmm_realloc.c kmm_zalloc.c
-ifeq ($(CONFIG_MM_PGALLOC),y)
-ifeq ($(CONFIG_ARCH_USE_MMU),y)
+ifeq ($(CONFIG_ARCH_ADDRENV),y)
CSRCS += kmm_sbrk.c
endif
-endif
ifeq ($(CONFIG_DEBUG),y)
CSRCS += kmm_heapmember.c
diff --git a/nuttx/mm/kmm_sbrk.c b/nuttx/mm/kmm_sbrk.c
index 89e6129c3..09da8d93d 100755
--- a/nuttx/mm/kmm_sbrk.c
+++ b/nuttx/mm/kmm_sbrk.c
@@ -41,8 +41,7 @@
#include <nuttx/mm.h>
-#if defined(CONFIG_MM_KERNEL_HEAP) && defined(CONFIG_MM_PGALLOC) && \
- defined(CONFIG_ARCH_USE_MMU)
+#if defined(CONFIG_MM_KERNEL_HEAP) && defined(CONFIG_ARCH_ADDRENV)
/****************************************************************************
* Pre-processor Definitions
@@ -89,4 +88,4 @@ FAR void *kmm_sbrk(intptr_t incr)
return mm_sbrk(&g_kmmheap, incr, UINTPTR_MAX);
}
-#endif /* CONFIG_MM_USER_HEAP && CONFIG_MM_PGALLOC && CONFIG_ARCH_USE_MMU */
+#endif /* CONFIG_MM_USER_HEAP && CONFIG_ARCH_ADDRENV */
diff --git a/nuttx/mm/mm_brkaddr.c b/nuttx/mm/mm_brkaddr.c
index a75bcd68b..693b81086 100644
--- a/nuttx/mm/mm_brkaddr.c
+++ b/nuttx/mm/mm_brkaddr.c
@@ -55,7 +55,8 @@
* Name: mm_brkaddr
*
* Description:
- * Return the break address of a heap region
+ * Return the break address of a heap region. Zero is returned if the
+ * memory region is not initialized.
*
****************************************************************************/
@@ -65,5 +66,5 @@ FAR void *mm_brkaddr(FAR struct mm_heap_s *heap, int region)
DEBUGASSERT(heap && region < heap->mm_nregions);
brkaddr = (uintptr_t)heap->mm_heapend[region];
- return (FAR void *)(brkaddr + SIZEOF_MM_ALLOCNODE);
+ return brkaddr ? (FAR void *)(brkaddr + SIZEOF_MM_ALLOCNODE) : 0;
}
diff --git a/nuttx/mm/mm_sbrk.c b/nuttx/mm/mm_sbrk.c
index 02fbab38d..c0c640735 100644
--- a/nuttx/mm/mm_sbrk.c
+++ b/nuttx/mm/mm_sbrk.c
@@ -47,7 +47,7 @@
#include <nuttx/mm.h>
#include <nuttx/pgalloc.h>
-#if defined(CONFIG_MM_PGALLOC) && defined(CONFIG_ARCH_USE_MMU)
+#ifdef CONFIG_ARCH_ADDRENV
/****************************************************************************
* Pre-processor Definitions
@@ -115,7 +115,7 @@ FAR void *mm_sbrk(FAR struct mm_heap_s *heap, intptr_t incr,
/* Check if this increment would exceed the maximum break value */
- if ((maxbreak - brkaddr) < (pgincr << MM_PGSHIFT))
+ if ((brkaddr > 0) && ((maxbreak - brkaddr) < (pgincr << MM_PGSHIFT)))
{
err = ENOMEM;
goto errout;
@@ -143,4 +143,4 @@ errout:
set_errno(err);
return (FAR void *)-1;
}
-#endif /* CONFIG_MM_PGALLOC && CONFIG_ARCH_USE_MMU */
+#endif /* CONFIG_ARCH_ADDRENV */
diff --git a/nuttx/mm/umm_malloc.c b/nuttx/mm/umm_malloc.c
index 6d08fbc29..a2f68eca3 100644
--- a/nuttx/mm/umm_malloc.c
+++ b/nuttx/mm/umm_malloc.c
@@ -40,6 +40,7 @@
#include <nuttx/config.h>
#include <stdlib.h>
+#include <unistd.h>
#include <nuttx/mm.h>
@@ -85,7 +86,39 @@
FAR void *malloc(size_t size)
{
+#ifdef CONFIG_ARCH_ADDRENV
+ FAR void *brkaddr;
+ FAR void *mem;
+
+ /* Loop until we successfully allocate the memory or until an error
+ * occurs. If we fail to allocate memory on the first pass, then call
+ * sbrk to extend the heap by one page. This may require several
+ * passes if more the size of the allocation is more than one page.
+ *
+ * An alternative would be to increase the size of the heap by the
+ * full requested allocation in sbrk(). Then the loop should never
+ * execute more than twice (but more memory than we need may be
+ * allocated).
+ */
+
+ do
+ {
+ mem = mm_malloc(&g_mmheap, size);
+ if (!mem)
+ {
+ brkaddr = sbrk(size);
+ if (brkaddr == (FAR void *)-1)
+ {
+ return NULL;
+ }
+ }
+ }
+ while (mem == NULL);
+
+ return mem;
+#else
return mm_malloc(&g_mmheap, size);
+#endif
}
#endif /* CONFIG_MM_USER_HEAP */
diff --git a/nuttx/mm/umm_sbrk.c b/nuttx/mm/umm_sbrk.c
index c03b69840..b404b020c 100644
--- a/nuttx/mm/umm_sbrk.c
+++ b/nuttx/mm/umm_sbrk.c
@@ -44,8 +44,7 @@
#include <nuttx/mm.h>
#include <nuttx/pgalloc.h>
-#if defined(CONFIG_MM_USER_HEAP) && defined(CONFIG_MM_PGALLOC) && \
- defined(CONFIG_ARCH_USE_MMU)
+#if defined(CONFIG_MM_USER_HEAP) && defined(CONFIG_ARCH_ADDRENV)
/****************************************************************************
* Pre-processor Definitions
@@ -92,4 +91,4 @@ FAR void *sbrk(intptr_t incr)
return mm_sbrk(&g_mmheap, incr, CONFIG_ARCH_STACK_NPAGES << MM_PGSHIFT);
}
-#endif /* CONFIG_MM_USER_HEAP && CONFIG_MM_PGALLOC && CONFIG_ARCH_USE_MMU */
+#endif /* CONFIG_MM_USER_HEAP && CONFIG_ARCH_ADDRENV */
diff --git a/nuttx/mm/umm_zalloc.c b/nuttx/mm/umm_zalloc.c
index d4d5bf5fd..835841a75 100644
--- a/nuttx/mm/umm_zalloc.c
+++ b/nuttx/mm/umm_zalloc.c
@@ -40,6 +40,7 @@
#include <nuttx/config.h>
#include <stdlib.h>
+#include <string.h>
#include <nuttx/mm.h>
@@ -69,7 +70,22 @@
FAR void *zalloc(size_t size)
{
+#ifdef CONFIG_ARCH_ADDRENV
+ /* Use malloc() because it implements the sbrk() logic */
+
+ FAR void *alloc = malloc(size);
+ if (alloc)
+ {
+ memset(alloc, 0, size);
+ }
+
+ return alloc;
+
+#else
+ /* Use mm_zalloc() becuase it implements the clear */
+
return mm_zalloc(&g_mmheap, size);
+#endif
}
#endif /* CONFIG_MM_USER_HEAP */