summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nuttx/arch/arm/src/armv7-a/arm_pgalloc.c39
-rw-r--r--nuttx/include/nuttx/arch.h17
-rw-r--r--nuttx/mm/mm_sbrk.c36
-rw-r--r--nuttx/sched/init/os_start.c4
4 files changed, 73 insertions, 23 deletions
diff --git a/nuttx/arch/arm/src/armv7-a/arm_pgalloc.c b/nuttx/arch/arm/src/armv7-a/arm_pgalloc.c
index e55e92c25..e58c20cd0 100644
--- a/nuttx/arch/arm/src/armv7-a/arm_pgalloc.c
+++ b/nuttx/arch/arm/src/armv7-a/arm_pgalloc.c
@@ -186,9 +186,24 @@ static int get_pgtable(FAR group_addrenv_t *addrenv, uintptr_t vaddr)
* Therefore, it is a system interface and follows a different naming
* convention.
*
+ * Input Parameters:
+ * brkaddr - The heap break address. The next page will be allocated and
+ * mapped to this address. Must be page aligned. If the memory manager
+ * has not yet been initialized and this is the first block requested for
+ * the heap, then brkaddr should be zero. pgalloc will then assigned the
+ * well-known virtual address of the beginning of the heap.
+ * npages - The number of pages to allocate and map. Mapping of pages
+ * will be contiguous beginning beginning at 'brkaddr'
+ *
+ * Returned Value:
+ * The (virtual) base address of the mapped page will returned on success.
+ * Normally this will be the same as the 'brkaddr' input. However, if
+ * the 'brkaddr' input was zero, this will be the virtual address of the
+ * beginning of the heap. Zero is returned on any failure.
+ *
****************************************************************************/
-int pgalloc(uintptr_t vaddr, unsigned int npages)
+uintptr_t pgalloc(uintptr_t brkaddr, unsigned int npages)
{
FAR struct tcb_s *tcb = sched_self();
FAR struct task_group_s *group;
@@ -209,24 +224,24 @@ int pgalloc(uintptr_t vaddr, unsigned int npages)
DEBUGASSERT((group->flags & GROUP_FLAG_ADDRENV) != 0);
- /* vaddr = 0 means that no heap has yet been allocated */
+ /* brkaddr = 0 means that no heap has yet been allocated */
- if (vaddr == 0)
+ if (brkaddr == 0)
{
- vaddr = CONFIG_ARCH_HEAP_VBASE;
+ brkaddr = CONFIG_ARCH_HEAP_VBASE;
}
- DEBUGASSERT(vadddr >= CONFIG_ARCH_HEAP_VBASE && vaddr < ARCH_HEAP_VEND);
- DEBUGASSERT(MM_ISALIGNED(vaddr));
+ DEBUGASSERT(vadddr >= CONFIG_ARCH_HEAP_VBASE && brkaddr < ARCH_HEAP_VEND);
+ DEBUGASSERT(MM_ISALIGNED(brkaddr));
for (; npages > 0; npages--)
{
/* Get the physical address of the level 2 page table */
- paddr = get_pgtable(&group->addrenv, vaddr);
+ paddr = get_pgtable(&group->addrenv, brkaddr);
if (paddr == 0)
{
- return -ENOMEM; /* ENOMEM might have correct meaning for sbrk? */
+ return 0;
}
/* Temporarily map the level 2 page table into the "scratch" virtual
@@ -245,7 +260,7 @@ int pgalloc(uintptr_t vaddr, unsigned int npages)
{
mmu_l1_restore(ARCH_SCRATCH_VBASE, l1save);
irqrestore(flags);
- return -EAGAIN; /* ENOMEM has different meaning for sbrk */
+ return 0;
}
/* The table divides a 1Mb address space up into 256 entries, each
@@ -253,13 +268,13 @@ int pgalloc(uintptr_t vaddr, unsigned int npages)
* related to the offset from the beginning of 1Mb region.
*/
- index = (vaddr & 0x000ff000) >> 12;
+ index = (brkaddr & 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;
+ brkaddr += MM_PGSIZE;
/* Make sure that the modified L2 table is flushed to physical
* memory.
@@ -274,7 +289,7 @@ int pgalloc(uintptr_t vaddr, unsigned int npages)
irqrestore(flags);
}
- return OK;
+ return brkaddr;
}
#endif /* CONFIG_MM_PGALLOC && CONFIG_ARCH_USE_MMU */
diff --git a/nuttx/include/nuttx/arch.h b/nuttx/include/nuttx/arch.h
index f60ec6d8d..2a27bf6d8 100644
--- a/nuttx/include/nuttx/arch.h
+++ b/nuttx/include/nuttx/arch.h
@@ -678,10 +678,25 @@ void up_allocate_pgheap(FAR void **heap_start, size_t *heap_size);
* Therefore, it is a system interface and follows a different naming
* convention.
*
+ * Input Parameters:
+ * brkaddr - The heap break address. The next page will be allocated and
+ * mapped to this address. Must be page aligned. If the memory manager
+ * has not yet been initialized and this is the first block requested for
+ * the heap, then brkaddr should be zero. pgalloc will then assigned the
+ * well-known virtual address of the beginning of the heap.
+ * npages - The number of pages to allocate and map. Mapping of pages
+ * will be contiguous beginning beginning at 'brkaddr'
+ *
+ * Returned Value:
+ * The (virtual) base address of the mapped page will returned on success.
+ * Normally this will be the same as the 'brkaddr' input. However, if
+ * the 'brkaddr' input was zero, this will be the virtual address of the
+ * beginning of the heap. Zero is returned on any failure.
+ *
****************************************************************************/
#ifdef CONFIG_ARCH_ADDRENV
-int pgalloc(uintptr_t vaddr, unsigned int npages);
+uintptr_t pgalloc(uintptr_t brkaddr, unsigned int npages);
#endif
/****************************************************************************
diff --git a/nuttx/mm/mm_sbrk.c b/nuttx/mm/mm_sbrk.c
index c0c640735..f8c22b33a 100644
--- a/nuttx/mm/mm_sbrk.c
+++ b/nuttx/mm/mm_sbrk.c
@@ -93,9 +93,10 @@ FAR void *mm_sbrk(FAR struct mm_heap_s *heap, intptr_t incr,
uintptr_t maxbreak)
{
uintptr_t brkaddr;
+ uintptr_t allocbase;
unsigned int pgincr;
+ size_t bytesize;
int err;
- int ret;
DEBUGASSERT(incr >= 0);
if (incr < 0)
@@ -104,7 +105,10 @@ FAR void *mm_sbrk(FAR struct mm_heap_s *heap, intptr_t incr,
goto errout;
}
- /* Get the current break address (NOTE: assumes region 0) */
+ /* Get the current break address (NOTE: assumes region 0). If
+ * the memory manager is uninitialized, mm_brkaddr() will return
+ * zero.
+ */
brkaddr = (uintptr_t)mm_brkaddr(heap, 0);
if (incr > 0)
@@ -122,19 +126,35 @@ FAR void *mm_sbrk(FAR struct mm_heap_s *heap, intptr_t incr,
}
/* Allocate the requested number of pages and map them to the
- * break address.
+ * break address. If we provide a zero brkaddr to pgalloc(), it
+ * will create the first block in the correct virtual address
+ * space and return the start address of that block.
*/
- ret = pgalloc(brkaddr, pgincr);
- if (ret < 0)
+ allocbase = pgalloc(brkaddr, pgincr);
+ if (allocbase == 0)
{
- err = -ret;
+ err = EAGAIN;
goto errout;
}
- /* Extend the heap (region 0) */
+ /* Has the been been initialized? brkaddr will be zero if the
+ * memory manager has not yet been initialized.
+ */
+
+ bytesize = pgincr << MM_PGSHIFT;
+ if (brkaddr != 0)
+ {
+ /* No... then initialize it now */
- mm_extend(heap, (FAR void *)brkaddr, pgincr << MM_PGSHIFT, 0);
+ mm_initialize(heap, (FAR void *)allocbase, bytesize);
+ }
+ else
+ {
+ /* Extend the heap (region 0) */
+
+ mm_extend(heap, (FAR void *)allocbase, bytesize, 0);
+ }
}
return (FAR void *)brkaddr;
diff --git a/nuttx/sched/init/os_start.c b/nuttx/sched/init/os_start.c
index 7879eaeec..8991cc608 100644
--- a/nuttx/sched/init/os_start.c
+++ b/nuttx/sched/init/os_start.c
@@ -220,7 +220,7 @@ static FAR const char g_idlename[] = "Idle Task";
/* This the IDLE idle threads argument list. */
-static char *g_idleargv[2];
+static FAR char *g_idleargv[2];
/****************************************************************************
* Private Function Prototypes
@@ -321,7 +321,7 @@ void os_start(void)
g_idleargv[0] = (FAR char *)g_idlename;
#endif /* CONFIG_TASK_NAME_SIZE */
g_idleargv[1] = NULL;
- g_idletcb.argv = &g_idleargv;
+ g_idletcb.argv = g_idleargv;
/* Then add the idle task's TCB to the head of the ready to run list */