mirror of
https://github.com/apache/nuttx.git
synced 2026-09-20 21:06:58 +08:00
sbrk() need to initialized the memory manager on the first call
This commit is contained in:
@@ -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 */
|
||||
|
||||
+16
-1
@@ -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
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
+28
-8
@@ -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.
|
||||
*/
|
||||
|
||||
mm_extend(heap, (FAR void *)brkaddr, pgincr << MM_PGSHIFT, 0);
|
||||
bytesize = pgincr << MM_PGSHIFT;
|
||||
if (brkaddr != 0)
|
||||
{
|
||||
/* No... then initialize it now */
|
||||
|
||||
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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user