From b4438e44c532f226c8f5906ef089c2b951ac3d0c Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 2 Sep 2014 11:22:09 -0600 Subject: [PATCH] Restructuring of build to allow use of use-space allocators by kernel logic in the kernel build. --- arch/arm/src/common/up_allocateheap.c | 5 +- arch/arm/src/sama5/sam_allocateheap.c | 15 +++--- include/nuttx/arch.h | 11 +++- include/nuttx/kmalloc.h | 31 ++++++----- include/nuttx/mm.h | 75 ++++++++++++++++++--------- include/unistd.h | 3 +- mm/kmm_sbrk.c | 5 +- mm/mm_sbrk.c | 5 +- sched/init/os_start.c | 2 +- sched/sched/sched_free.c | 2 - 10 files changed, 94 insertions(+), 60 deletions(-) diff --git a/arch/arm/src/common/up_allocateheap.c b/arch/arm/src/common/up_allocateheap.c index e3443639a1..1c1dcb4630 100644 --- a/arch/arm/src/common/up_allocateheap.c +++ b/arch/arm/src/common/up_allocateheap.c @@ -67,8 +67,9 @@ * * The ARMv7 has no MPU but does have an MMU. With this MMU, it can support * the kernel build (CONFIG_BUILD_KERNEL=y). In this configuration, there - * is again only one heap but, retaining the terminology, this is the kernel - * heap. + * is one kernel heap but multiple user heaps: One per task group. However, + * in this case, we need only be concerned about initializing the single + * kernel heap here. */ /**************************************************************************** diff --git a/arch/arm/src/sama5/sam_allocateheap.c b/arch/arm/src/sama5/sam_allocateheap.c index 616b6f0fde..5cff278aa5 100644 --- a/arch/arm/src/sama5/sam_allocateheap.c +++ b/arch/arm/src/sama5/sam_allocateheap.c @@ -69,13 +69,12 @@ * * The ARMv7 has no MPU but does have an MMU. With this MMU, it can support * the kernel build (CONFIG_BUILD_KERNEL=y). In this configuration, there - * is again only one heap but, retaining the terminology, this is the kernel - * heap. + * is one kernel heap but multiple user heaps: One per task group. However, + * in this case, we need only be concerned about initializing the single + * kernel heap here. */ -#if defined(CONFIG_MM_USER_HEAP) && defined(CONFIG_MM_KERNEL_HEAP) -# error "Cannot support both user and kernel heaps" -#elif defined(CONFIG_MM_KERNEL_HEAP) +#if defined(CONFIG_BUILD_KERNEL) # define MM_ADDREGION kmm_addregion #else # define MM_ADDREGION umm_addregion @@ -247,10 +246,10 @@ * ****************************************************************************/ -#if defined(CONFIG_MM_USER_HEAP) -void up_allocate_heap(FAR void **heap_start, size_t *heap_size) -#elif defined(CONFIG_MM_KERNEL_HEAP) +#if defined(CONFIG_BUILD_KERNEL) void up_allocate_kheap(FAR void **heap_start, size_t *heap_size) +#else +void up_allocate_heap(FAR void **heap_start, size_t *heap_size) #endif { #if defined(CONFIG_BOOT_SDRAM_DATA) diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index aa70d81693..d9d8c3736d 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -760,7 +760,10 @@ uintptr_t pgalloc(uintptr_t brkaddr, unsigned int npages); * 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. + * 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. * addrenv - The location to return the representation of the task address * environment. * @@ -831,7 +834,11 @@ int up_addrenv_vtext(FAR group_addrenv_t *addrenv, FAR void **vtext); * in the same memory region (read/write/execute) and, in this case, * the virtual address of the data just lies at this offset into the * common region. - * vdata - The location to return the virtual address. + * vdata - The location to return the virtual address. NOTE that the + * beginning of the data region is reserved for use by the OS. The + * returned address will be at a offset from the actual allocated base + * address to account for the OS private region. The size of that + * offset is given by ARCH_DATA_RESERVE * * Returned Value: * Zero (OK) on success; a negated errno value on failure. diff --git a/include/nuttx/kmalloc.h b/include/nuttx/kmalloc.h index ffe0340dc1..68f8c7c7bf 100644 --- a/include/nuttx/kmalloc.h +++ b/include/nuttx/kmalloc.h @@ -89,8 +89,21 @@ extern "C" #define kumm_trysemaphore() umm_trysemaphore() #define kumm_givesemaphore() umm_givesemaphore() -#ifndef CONFIG_BUILD_PROTECTED -/* In the flat build, the following are declared in stdlib.h and are +#ifdef CONFIG_BUILD_PROTECTED +/* In the kernel-phase of the protected build, the these macros are defined + * in userspace.h. These macros version call into user-space via a header + * at the beginning of the user-space blob. + */ + +# define kumm_malloc(s) umm_malloc(s) +# define kumm_zalloc(s) umm_zalloc(s) +# define kumm_realloc(p,s) umm_realloc(p,s) +# define kumm_memalign(a,s) umm_memalign(a,s) +# define kumm_free(p) umm_free(p) + +#else +/* In the flat build (CONFIG_BUILD_FLAT) and in the kernel build + * (CONFIG_BUILD_KERNEL), the following are declared in stdlib.h and are * directly callable. */ @@ -100,18 +113,6 @@ extern "C" # define kumm_memalign(a,s) memalign(a,s) # define kumm_free(p) free(p) -#else -/* In the kernel-phase of the protected build, the these macros are defined - * in userspace.h. These macros versions call into user-space via a header - * at the beginning of the user-space blob. - */ - -# define kumm_malloc(s) umm_malloc(s) -# define kumm_zalloc(s) umm_zalloc(s) -# define kumm_realloc(p,s) umm_realloc(p,s) -# define kumm_memalign(a,s) umm_memalign(a,s) -# define kumm_free(p) umm_free(p) - #endif /* This family of allocators is used to manage kernel protected memory */ @@ -164,9 +165,7 @@ extern "C" * sched_garbagecollection(). */ -#ifdef CONFIG_MM_USER_HEAP void sched_ufree(FAR void *address); -#endif #if defined(CONFIG_MM_KERNEL_HEAP) && defined(__KERNEL__) void sched_kfree(FAR void *address); diff --git a/include/nuttx/mm.h b/include/nuttx/mm.h index d810ef6ff7..fb93c002cd 100644 --- a/include/nuttx/mm.h +++ b/include/nuttx/mm.h @@ -65,21 +65,40 @@ # define CONFIG_MM_SMALL 1 #endif -/* Decide if there is a user heap. CONFIG_MM_USER_HEAP=n does not not - * really that there is no user heap but, rather, that there is no - * user heap available from within the kernel. The user heap is - * Available if: +/* Terminology: * - * 1. The code is begin build for kernel space and this is a FLAT build - * (CONFIG_BUILD_FLAT=y), - * 2. The code is begin build for kernel space and this is a protected - * build (CONFIG_BUILD_PROTECTED=y), OR - * 3. The code is begin build for user space. + * - Flat Build: In the flat build (CONFIG_BUILD_FLAT=y), there is only a + * single heap access with the standard allocations (malloc/free). This + * heap is referred to as the user heap. The kernel logic must + * initialize this single heap at boot time. + * - Protected build: In the protected build (CONFIG_BUILD_PROTECTED=y) + * where an MPU is used to protect a region of otherwise flat memory, + * there will be two allocators: One that allocates protected (kernel) + * memory and one that allocates unprotected (user) memory. These are + * referred to as the kernel and user heaps, respectively. Both must be + * initialized by the kernel logic at boot time. + * - Kernel Build: If the architecture has an MMU, then it may support the + * kernel build (CONFIG_BUILD_KERNEL=y). In this configuration, there + * is one kernel heap but multiple user heaps: One per task group. + * However, in this case, the kernel need only be concerned about + * initializing the single kernel heap here. User heaps will be created + * as tasks are created. + * + * These special definitions are provided: + * + * MM_KERNEL_USRHEAP_INIT + * Special kernel interfaces to the kernel user-heap are required + * for heap initialization. + * CONFIG_MM_KERNEL_HEAP + * The configuration requires a kernel heap that must initialized + * at boot-up. */ -#undef CONFIG_MM_USER_HEAP -#if !defined(CONFIG_BUILD_KERNEL) || !defined(__KERNEL__) -# define CONFIG_MM_USER_HEAP 1 +#undef MM_KERNEL_USRHEAP_INIT +#if defined(CONFIG_BUILD_PROTECTED) && defined(__KERNEL__) +# define MM_KERNEL_USRHEAP_INIT 1 +#elif !defined(CONFIG_BUILD_KERNEL) +# define MM_KERNEL_USRHEAP_INIT 1 #endif /* The kernel heap is never accessible from user code */ @@ -243,8 +262,18 @@ extern "C" #define EXTERN extern #endif -#ifdef CONFIG_MM_USER_HEAP -/* This is the user heap */ +#if (!defined(CONFIG_ARCH_ADDRENV) || !defined(CONFIG_BUILD_KERNEL)) && \ + (defined(CONFIG_BUILD_KERNEL) && !defined(__KERNEL__)) +/* User heap structure: + * + * - Flat build: In the FLAT build, the user heap structure is a globally + * accessible variable. + * - Protected build: The user heap structure is directly available only + * in user space. + * - Kernel build: There are multiple heaps, one per process. The heap + * structure is associated with the address environment and there is + * no global user heap structure. + */ EXTERN struct mm_heap_s g_mmheap; #endif @@ -268,7 +297,7 @@ void mm_addregion(FAR struct mm_heap_s *heap, FAR void *heapstart, /* Functions contained in umm_initialize.c **********************************/ -#ifdef CONFIG_MM_USER_HEAP +#ifdef MM_KERNEL_USRHEAP_INIT void umm_initialize(FAR void *heap_start, size_t heap_size); #endif @@ -280,13 +309,13 @@ void kmm_initialize(FAR void *heap_start, size_t heap_size); /* Functions contained in umm_addregion.c ***********************************/ -#ifdef CONFIG_MM_USER_HEAP +#ifdef MM_KERNEL_USRHEAP_INIT void umm_addregion(FAR void *heapstart, size_t heapsize); #endif /* Functions contained in kmm_addregion.c ***********************************/ -#ifdef CONFIG_MM_USER_HEAP +#ifdef CONFIG_MM_KERNEL_HEAP void kmm_addregion(FAR void *heapstart, size_t heapsize); #endif @@ -299,7 +328,7 @@ void mm_givesemaphore(FAR struct mm_heap_s *heap); /* Functions contained in umm_sem.c ****************************************/ -#ifdef CONFIG_MM_USER_HEAP +#ifdef MM_KERNEL_USRHEAP_INIT int umm_trysemaphore(void); void umm_givesemaphore(void); #endif @@ -385,9 +414,7 @@ FAR void *mm_brkaddr(FAR struct mm_heap_s *heap, int region); /* Functions contained in umm_brkaddr.c *************************************/ -#ifdef CONFIG_MM_USER_HEAP FAR void *umm_brkaddr(int region); -#endif /* Functions contained in kmm_brkaddr.c *************************************/ @@ -397,14 +424,16 @@ FAR void *kmm_brkaddr(int region); /* Functions contained in mm_sbrk.c *****************************************/ -#ifdef CONFIG_ARCH_ADDRENV +#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_MM_PGALLOC) && \ + defined(CONFIG_ARCH_USE_MMU) FAR void *mm_sbrk(FAR struct mm_heap_s *heap, intptr_t incr, uintptr_t maxbreak); #endif /* Functions contained in kmm_sbrk.c ****************************************/ -#ifdef CONFIG_ARCH_ADDRENV +#if defined(CONFIG_MM_KERNEL_HEAP) && defined(CONFIG_ARCH_ADDRENV) && \ + defined(CONFIG_MM_PGALLOC) && defined(CONFIG_ARCH_USE_MMU) FAR void *kmm_sbrk(intptr_t incr); #endif @@ -415,9 +444,7 @@ void mm_extend(FAR struct mm_heap_s *heap, FAR void *mem, size_t size, /* Functions contained in umm_extend.c **************************************/ -#ifdef CONFIG_MM_USER_HEAP void umm_extend(FAR void *mem, size_t size, int region); -#endif /* Functions contained in kmm_extend.c **************************************/ diff --git a/include/unistd.h b/include/unistd.h index 641e2e4691..4dabdb35a3 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -149,7 +149,8 @@ ssize_t write(int fd, FAR const void *buf, size_t nbytes); /* Memory management */ -#ifdef CONFIG_ARCH_ADDRENV +#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_MM_PGALLOC) && \ + defined(CONFIG_ARCH_USE_MMU) FAR void *sbrk(intptr_t incr); #endif diff --git a/mm/kmm_sbrk.c b/mm/kmm_sbrk.c index 09da8d93dd..547dba0476 100755 --- a/mm/kmm_sbrk.c +++ b/mm/kmm_sbrk.c @@ -41,7 +41,8 @@ #include -#if defined(CONFIG_MM_KERNEL_HEAP) && defined(CONFIG_ARCH_ADDRENV) +#if defined(CONFIG_MM_KERNEL_HEAP) && defined(CONFIG_ARCH_ADDRENV) && \ + defined(CONFIG_MM_PGALLOC) && defined(CONFIG_ARCH_USE_MMU) /**************************************************************************** * Pre-processor Definitions @@ -88,4 +89,4 @@ FAR void *kmm_sbrk(intptr_t incr) return mm_sbrk(&g_kmmheap, incr, UINTPTR_MAX); } -#endif /* CONFIG_MM_USER_HEAP && CONFIG_ARCH_ADDRENV */ +#endif /* CONFIG_MM_KERNEL_HEAP && CONFIG_ARCH_ADDRENV && ... */ diff --git a/mm/mm_sbrk.c b/mm/mm_sbrk.c index f8c22b33a1..28689b3ca7 100644 --- a/mm/mm_sbrk.c +++ b/mm/mm_sbrk.c @@ -47,7 +47,8 @@ #include #include -#ifdef CONFIG_ARCH_ADDRENV +#if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_MM_PGALLOC) && \ + defined(CONFIG_ARCH_USE_MMU) /**************************************************************************** * Pre-processor Definitions @@ -163,4 +164,4 @@ errout: set_errno(err); return (FAR void *)-1; } -#endif /* CONFIG_ARCH_ADDRENV */ +#endif /* CONFIG_ARCH_ADDRENV && CONFIG_MM_PGALLOC && CONFIG_ARCH_USE_MMU */ diff --git a/sched/init/os_start.c b/sched/init/os_start.c index 8991cc6084..27ebd29c21 100644 --- a/sched/init/os_start.c +++ b/sched/init/os_start.c @@ -350,7 +350,7 @@ void os_start(void) FAR void *heap_start; size_t heap_size; -#ifdef CONFIG_MM_USER_HEAP +#ifdef MM_KERNEL_USRHEAP_INIT /* Get the user-mode heap from the platform specific code and configure * the user-mode memory allocator. */ diff --git a/sched/sched/sched_free.c b/sched/sched/sched_free.c index 268e6dc0af..43e305dbe5 100644 --- a/sched/sched/sched_free.c +++ b/sched/sched/sched_free.c @@ -82,7 +82,6 @@ * ************************************************************************/ -#ifdef CONFIG_MM_USER_HEAP void sched_ufree(FAR void *address) { irqstate_t flags; @@ -123,7 +122,6 @@ void sched_ufree(FAR void *address) kumm_givesemaphore(); } } -#endif #ifdef CONFIG_MM_KERNEL_HEAP void sched_kfree(FAR void *address)