From 006cf7d745d143ea61a73831e294d6fc8448b230 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 10 Sep 2014 15:55:36 -0600 Subject: [PATCH] Add logic to initialize the per-process user heap when each user process is started --- arch/arm/include/arch.h | 12 +++- arch/arm/include/armv7-a/irq.h | 4 +- arch/arm/src/armv7-a/arm_addrenv.c | 90 +++++++++++++++++++++--------- arch/z80/src/z180/z180_mmu.c | 64 +++++++++++++++------ 4 files changed, 124 insertions(+), 46 deletions(-) diff --git a/arch/arm/include/arch.h b/arch/arm/include/arch.h index 2f19916223..02e66aaf49 100644 --- a/arch/arm/include/arch.h +++ b/arch/arm/include/arch.h @@ -133,9 +133,19 @@ do { \ struct group_addrenv_s { + /* Level 1 page table entries for each group section */ + FAR uintptr_t *text[ARCH_TEXT_NSECTS]; FAR uintptr_t *data[ARCH_DATA_NSECTS]; FAR uintptr_t *heap[ARCH_HEAP_NSECTS]; + + /* Initial heap allocation (in bytes). This exists only provide an + * indirect path for passing the size of the initial heap to the heap + * initialization logic. These operations are separated in time and + * architecture. REVISIT: I would like a better way to do this. + */ + + size_t heapsize; }; typedef struct group_addrenv_s group_addrenv_t; @@ -153,9 +163,7 @@ struct save_addrenv_s { FAR uint32_t text[ARCH_TEXT_NSECTS]; FAR uint32_t data[ARCH_DATA_NSECTS]; -#if 0 /* Not yet implemented */ FAR uint32_t heap[ARCH_HEAP_NSECTS]; -#endif }; typedef struct save_addrenv_s save_addrenv_t; diff --git a/arch/arm/include/armv7-a/irq.h b/arch/arm/include/armv7-a/irq.h index 00e7244ae2..f9d5225b3a 100755 --- a/arch/arm/include/armv7-a/irq.h +++ b/arch/arm/include/armv7-a/irq.h @@ -274,17 +274,15 @@ struct xcptcontext struct xcpt_syscall_s syscall[CONFIG_SYS_NNEST]; #endif -#ifdef CONFIG_ARCH_ADDRENV +#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_ARCH_STACK_DYNAMIC) /* This table holds the physical address of the level 2 page table used * to map the thread's stack memory. This array will be initially of * zeroed and would be back-up up with pages during page fault exception * handling to support dynamically sized stacks for each thread. */ -#if 0 /* Not yet implemented */ FAR uintptr_t *stack[ARCH_STACK_NSECTS]; #endif -#endif }; #endif diff --git a/arch/arm/src/armv7-a/arm_addrenv.c b/arch/arm/src/armv7-a/arm_addrenv.c index 4d68fd655f..aa28efbdbc 100644 --- a/arch/arm/src/armv7-a/arm_addrenv.c +++ b/arch/arm/src/armv7-a/arm_addrenv.c @@ -40,27 +40,28 @@ * is an abstract representation of a task group's address environment and * must be defined in arch/arch.h if CONFIG_ARCH_ADDRENV is defined. * - * up_addrenv_create - Create an address environment - * up_addrenv_destroy - Destroy an address environment. - * up_addrenv_vtext - Returns the virtual base address of the .text - * address environment - * up_addrenv_vdata - Returns the virtual base address of the .bss/.data - * address environment - * up_addrenv_select - Instantiate an address environment - * up_addrenv_restore - Restore an address environment - * up_addrenv_clone - Copy an address environment from one location to - * another. + * up_addrenv_create - Create an address environment + * up_addrenv_destroy - Destroy an address environment. + * up_addrenv_vtext - Returns the virtual base address of the .text + * address environment + * up_addrenv_vdata - Returns the virtual base address of the .bss/.data + * address environment + * up_addrenv_heapsize - Returns the size of the initial heap allocation. + * up_addrenv_select - Instantiate an address environment + * up_addrenv_restore - Restore an address environment + * up_addrenv_clone - Copy an address environment from one location to + * another. * * Higher-level interfaces used by the tasking logic. These interfaces are * used by the functions in sched/ and all operate on the thread which whose * group been assigned an address environment by up_addrenv_clone(). * - * up_addrenv_attach - Clone the address environment assigned to one TCB - * to another. This operation is done when a pthread - * is created that share's the same address - * environment. - * up_addrenv_detach - Release the threads reference to an address - * environment when a task/thread exits. + * up_addrenv_attach - Clone the address environment assigned to one TCB + * to another. This operation is done when a pthread + * is created that share's the same address + * environment. + * up_addrenv_detach - Release the threads reference to an address + * environment when a task/thread exits. * ****************************************************************************/ @@ -153,6 +154,10 @@ static void set_l2_entry(FAR uint32_t *l2table, uintptr_t paddr, * Description: * Create one memory region. * + * Returned Value: + * On success, the number of pages allocated is returned. Otherwise, a + * negated errno value is returned. + * ****************************************************************************/ static int up_addrenv_create_region(FAR uintptr_t **list, @@ -264,7 +269,7 @@ static int up_addrenv_create_region(FAR uintptr_t **list, irqrestore(flags); } - return OK; + return npages; } /**************************************************************************** @@ -437,6 +442,8 @@ static void up_addrenv_destroy_region(FAR uintptr_t **list, * actual size of the data region that is allocated will include a * OS private reserved region at the beginning. The size of the * private, reserved region is give by ARCH_DATA_RESERVE_SIZE. + * heapsize - The initial size (in bytes) of the heap address environment + * needed by the task. This region may be read/write only. * addrenv - The location to return the representation of the task address * environment. * @@ -445,7 +452,7 @@ static void up_addrenv_destroy_region(FAR uintptr_t **list, * ****************************************************************************/ -int up_addrenv_create(size_t textsize, size_t datasize, +int up_addrenv_create(size_t textsize, size_t datasize, size_t heapsize, FAR group_addrenv_t *addrenv) { int ret; @@ -503,8 +510,22 @@ int up_addrenv_create(size_t textsize, size_t datasize, } #endif - /* Notice that no pages are yet allocated for the heap */ + /* Allocate heap space pages */ + ret = up_addrenv_create_region(addrenv->heap, ARCH_HEAP_NSECTS, + CONFIG_ARCH_HEAP_VBASE, heapsize, + MMU_L2_UDATAFLAGS); + if (ret < 0) + { + bdbg("ERROR: Failed to create heap region: %d\n", ret); + goto errout; + } + + /* Save the initial heap size allocated. This will be needed when + * the heap data structures are initialized. + */ + + addrenv->heapsize = (size_t)ret << MM_PGSHIFT; return OK; errout: @@ -543,12 +564,10 @@ int up_addrenv_destroy(FAR group_addrenv_t *addrenv) up_addrenv_destroy_region(addrenv->data, ARCH_DATA_NSECTS, CONFIG_ARCH_DATA_VBASE); -#if 0 /* Not yet implemented */ /* Destroy the heap region */ up_addrenv_destroy_region(addrenv->heap, ARCH_HEAP_NSECTS, CONFIG_ARCH_HEAP_VBASE); -#endif memset(addrenv, 0, sizeof(group_addrenv_t)); return OK; @@ -616,6 +635,31 @@ int up_addrenv_vdata(FAR group_addrenv_t *addrenv, uintptr_t textsize, return OK; } +/**************************************************************************** + * Name: up_addrenv_heapsize + * + * Description: + * Return the initial heap allocation size. That is the amount of memory + * allocated by up_addrenv_create() when the heap memory region was first + * created. This may or may not differ from the heapsize parameter that + * was passed to up_addrenv_create() + * + * Input Parameters: + * addrenv - The representation of the task address environment previously + * returned by up_addrenv_create. + * + * Returned Value: + * The initial heap size allocated is returned on success; a negated + * errno value on failure. + * + ****************************************************************************/ + +ssize_t up_addrenv_heapsize(FAR const group_addrenv_t *addrenv) +{ + DEBUGASSERT(addrenv); + return (ssize_t)addrenv->heapsize; +} + /**************************************************************************** * Name: up_addrenv_select * @@ -698,7 +742,6 @@ int up_addrenv_select(FAR const group_addrenv_t *addrenv, } } -#if 0 /* Not yet implemented */ for (vaddr = CONFIG_ARCH_HEAP_VBASE, i = 0; i < ARCH_HEAP_NSECTS; vaddr += SECTION_SIZE, i++) @@ -722,7 +765,6 @@ int up_addrenv_select(FAR const group_addrenv_t *addrenv, mmu_l1_clrentry(vaddr); } } -#endif return OK; } @@ -770,7 +812,6 @@ int up_addrenv_restore(FAR const save_addrenv_t *oldenv) mmu_l1_restore(vaddr, oldenv->data[i]); } -#if 0 /* Not yet implemented */ for (vaddr = CONFIG_ARCH_HEAP_VBASE, i = 0; i < ARCH_HEAP_NSECTS; vaddr += SECTION_SIZE, i++) @@ -779,7 +820,6 @@ int up_addrenv_restore(FAR const save_addrenv_t *oldenv) mmu_l1_restore(vaddr, oldenv->heap[i]); } -#endif return OK; } diff --git a/arch/z80/src/z180/z180_mmu.c b/arch/z80/src/z180/z180_mmu.c index e1373851db..e63e184032 100644 --- a/arch/z80/src/z180/z180_mmu.c +++ b/arch/z80/src/z180/z180_mmu.c @@ -184,15 +184,16 @@ return g_physhandle ? OK : -ENOMEM; * is an abstract representation of a task group's address environment and * must be defined in arch/arch.h if CONFIG_ARCH_ADDRENV is defined. * - * up_addrenv_create - Create an address environment - * up_addrenv_destroy - Destroy an address environment. - * up_addrenv_vtext - Returns the virtual base address of the .text - * address environment - * up_addrenv_vdata - Returns the virtual base address of the .bss/.data - * address environment - * up_addrenv_select - Instantiate an address environment - * up_addrenv_restore - Restore an address environment - * up_addrenv_clone - Copy an address environment from one location to + * up_addrenv_create - Create an address environment + * up_addrenv_destroy - Destroy an address environment. + * up_addrenv_vtext - Returns the virtual base address of the .text + * address environment + * up_addrenv_vdata - Returns the virtual base address of the .bss/.data + * address environment + * up_addrenv_heapsize - Returns the size of the initial heap allocation. + * up_addrenv_select - Instantiate an address environment + * up_addrenv_restore - Restore an address environment + * up_addrenv_clone - Copy an address environment from one location to * another. * * Higher-level interfaces used by the tasking logic. These interfaces are @@ -200,11 +201,11 @@ return g_physhandle ? OK : -ENOMEM; * group been assigned an address environment by up_addrenv_clone(). * * up_addrenv_attach - Clone the address environment assigned to one TCB - * to another. This operation is done when a pthread - * is created that share's the same address - * environment. - * up_addrenv_detach - Release the threads reference to an address - * environment when a task/thread exits. + * to another. This operation is done when a pthread + * is created that share's the same address + * environment. + * up_addrenv_detach - Release the threads reference to an address + * environment when a task/thread exits. * ****************************************************************************/ /**************************************************************************** @@ -220,6 +221,11 @@ return g_physhandle ? OK : -ENOMEM; * textsize - The size (in bytes) of the .text address environment needed * by the task. This region may be read/execute only. * datasize - The size (in bytes) of the .data/.bss address environment + * needed by the task. This region may be read/write only. NOTE: The + * actual size of the data region that is allocated will include a + * OS private reserved region at the beginning. The size of the + * private, reserved region is give by ARCH_DATA_RESERVE_SIZE. + * heapsize - The initial size (in bytes) of the heap address environment * needed by the task. This region may be read/write only. * addrenv - The location to return the representation of the task address * environment. @@ -229,7 +235,7 @@ return g_physhandle ? OK : -ENOMEM; * ****************************************************************************/ -int up_addrenv_create(size_t textsize, size_t datasize, +int up_addrenv_create(size_t textsize, size_t datasize, size_t heapsize, FAR group_addrenv_t *addrenv) { FAR struct z180_cbr_s *cbr; @@ -241,7 +247,7 @@ int up_addrenv_create(size_t textsize, size_t datasize, /* Convert the size from bytes to numbers of pages */ - envsize = textsize + datasize; + envsize = textsize + datasize + heapsize; npages = PHYS_ALIGNUP(envsize); if (npages < 1) { @@ -389,6 +395,32 @@ int up_addrenv_vdata(FAR group_addrenv_t *addrenv, uintptr_t textsize, return CONFIG_Z180_COMMON1AREA_VIRTBASE + textsize; } +/**************************************************************************** + * Name: up_addrenv_heapsize + * + * Description: + * Return the initial heap allocation size. That is the amount of memory + * allocated by up_addrenv_create() when the heap memory region was first + * created. This may or may not differ from the heapsize parameter that + * was passed to up_addrenv_create() + * + * Input Parameters: + * addrenv - The representation of the task address environment previously + * returned by up_addrenv_create. + * + * Returned Value: + * The initial heap size allocated is returned on success; a negated + * errno value on failure. + * + ****************************************************************************/ + +ssize_t up_addrenv_heapsize(FAR const group_addrenv_t *addrenv) +{ + /* Not implemented */ + + return (ssize_t)-ENOSYS; +} + /**************************************************************************** * Name: up_addrenv_select *