From 7cd8db9425544bf10f742ce9798d4eec54c8e9a3 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 23 Aug 2014 12:43:21 -0600 Subject: [PATCH] gran_reserve(): Add a new function to reserve unallocatable regions in the granule heap --- configs/nucleo-f401re/nsh/setenv.sh | 3 +- include/nuttx/gran.h | 50 +++++++--- mm/Makefile | 3 +- mm/mm_gran.h | 21 +++- mm/mm_granalloc.c | 70 +------------- mm/mm_granmark.c | 132 +++++++++++++++++++++++++ mm/mm_granreserve.c | 144 ++++++++++++++++++++++++++++ 7 files changed, 340 insertions(+), 83 deletions(-) create mode 100644 mm/mm_granmark.c create mode 100644 mm/mm_granreserve.c diff --git a/configs/nucleo-f401re/nsh/setenv.sh b/configs/nucleo-f401re/nsh/setenv.sh index cd725c71ee..bd49bd23e9 100644 --- a/configs/nucleo-f401re/nsh/setenv.sh +++ b/configs/nucleo-f401re/nsh/setenv.sh @@ -52,12 +52,13 @@ fi # the CodeSourcery toolchain in any other location #export TOOLCHAIN_BIN="/cygdrive/c/Program Files (x86)/CodeSourcery/Sourcery G++ Lite/bin" export TOOLCHAIN_BIN="/cygdrive/c/Program Files (x86)/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_EABI/bin" +#export TOOLCHAIN_BIN="/cygdrive/c/Users/MyName/MentorGraphics/Sourcery_CodeBench_Lite_for_ARM_EABI/bin" # This the Cygwin path to the location where I build the buildroot # toolchain. #export TOOLCHAIN_BIN="${WD}/../misc/buildroot/build_arm_nofpu/staging_dir/bin" # Add the path to the toolchain to the PATH varialble -#export PATH="${TOOLCHAIN_BIN}:/sbin:/usr/sbin:${PATH_ORIG}" +export PATH="${TOOLCHAIN_BIN}:/sbin:/usr/sbin:${PATH_ORIG}" echo "PATH : ${PATH}" diff --git a/include/nuttx/gran.h b/include/nuttx/gran.h index 5e980dd9cf..4993c5b213 100644 --- a/include/nuttx/gran.h +++ b/include/nuttx/gran.h @@ -2,7 +2,7 @@ * include/nuttx/gran.h * General purpose granule memory allocator. * - * Copyright (C) 2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2012, 2014 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -134,16 +134,44 @@ extern "C" { * * Returned Value: * On success, a non-NULL handle is returned that may be used with other - * granual allocator interfaces. + * granule allocator interfaces. * ****************************************************************************/ #ifdef CONFIG_GRAN_SINGLE -EXTERN int gran_initialize(FAR void *heapstart, size_t heapsize, - uint8_t log2gran, uint8_t log2align); +int gran_initialize(FAR void *heapstart, size_t heapsize, uint8_t log2gran, + uint8_t log2align); #else -EXTERN GRAN_HANDLE gran_initialize(FAR void *heapstart, size_t heapsize, - uint8_t log2gran, uint8_t log2align); +GRAN_HANDLE gran_initialize(FAR void *heapstart, size_t heapsize, + uint8_t log2gran, uint8_t log2align); +#endif + +/**************************************************************************** + * Name: gran_reserve + * + * Description: + * Reserve memory in the granule heap. This will reserve the granules + * that contain the start and end addresses plus all of the granules + * in between. This should be done early in the initialization sequence + * before any other allocations are made. + * + * Reserved memory can never be allocated (it can be freed however which + * essentially unreserves the memory). + * + * Input Parameters: + * handle - The handle previously returned by gran_initialize + * start - The address of the beginning of the region to be reserved. + * size - The size of the region to be reserved + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_GRAN_SINGLE +void gran_reserve(uintptr_t start, size_t size); +#else +void gran_reserve(GRAN_HANDLE handle, uintptr_t start, size_t size); #endif /**************************************************************************** @@ -167,9 +195,9 @@ EXTERN GRAN_HANDLE gran_initialize(FAR void *heapstart, size_t heapsize, ****************************************************************************/ #ifdef CONFIG_GRAN_SINGLE -EXTERN FAR void *gran_alloc(size_t size); +FAR void *gran_alloc(size_t size); #else -EXTERN FAR void *gran_alloc(GRAN_HANDLE handle, size_t size); +FAR void *gran_alloc(GRAN_HANDLE handle, size_t size); #endif /**************************************************************************** @@ -180,7 +208,7 @@ EXTERN FAR void *gran_alloc(GRAN_HANDLE handle, size_t size); * * Input Parameters: * handle - The handle previously returned by gran_initialize - * memory - A pointer to memory previoiusly allocated by gran_alloc. + * memory - A pointer to memory previously allocated by gran_alloc. * * Returned Value: * None @@ -188,9 +216,9 @@ EXTERN FAR void *gran_alloc(GRAN_HANDLE handle, size_t size); ****************************************************************************/ #ifdef CONFIG_GRAN_SINGLE -EXTERN void gran_free(FAR void *memory, size_t size); +void gran_free(FAR void *memory, size_t size); #else -EXTERN void gran_free(GRAN_HANDLE handle, FAR void *memory, size_t size); +void gran_free(GRAN_HANDLE handle, FAR void *memory, size_t size); #endif #undef EXTERN diff --git a/mm/Makefile b/mm/Makefile index d1d0204a14..56b1157d27 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -67,7 +67,8 @@ endif # An optional granule allocator ifeq ($(CONFIG_GRAN),y) -CSRCS += mm_graninit.c mm_granalloc.c mm_granfree.c mm_grancritical.c +CSRCS += mm_graninit.c mm_granreserve.c mm_granalloc.c mm_granmark.c +CSRCS += mm_granfree.c mm_grancritical.c endif BINDIR ?= bin diff --git a/mm/mm_gran.h b/mm/mm_gran.h index 2dd1aef364..657aa68b60 100644 --- a/mm/mm_gran.h +++ b/mm/mm_gran.h @@ -83,7 +83,7 @@ * Public Types ****************************************************************************/ -/* This structure represents the state of on granual allocation */ +/* This structure represents the state of on granule allocation */ struct gran_s { @@ -129,4 +129,23 @@ extern FAR struct gran_s *g_graninfo; void gran_enter_critical(FAR struct gran_s *priv); void gran_leave_critical(FAR struct gran_s *priv); +/**************************************************************************** + * Name: gran_mark_allocated + * + * Description: + * Mark a range of granules as allocated. + * + * Input Parameters: + * priv - The granule heap state structure. + * alloc - The address of the allocation. + * ngranules - The number of granules allocated + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gran_mark_allocated(FAR struct gran_s *priv, uintptr_t alloc, + unsigned int ngranules); + #endif /* __MM_MM_GRAN_H */ diff --git a/mm/mm_granalloc.c b/mm/mm_granalloc.c index f92e44ef09..71647f954b 100644 --- a/mm/mm_granalloc.c +++ b/mm/mm_granalloc.c @@ -52,77 +52,9 @@ ****************************************************************************/ /**************************************************************************** - * Name: gran_common_alloc - * - * Description: - * Allocate memory from the granule heap. - * - * Input Parameters: - * priv - The granule heap state structure. - * alloc - The adress of the allocation. - * ngranules - The number of granules allocated - * - * Returned Value: - * None - * + * Private Functions ****************************************************************************/ -static inline void gran_mark_allocated(FAR struct gran_s *priv, - uintptr_t alloc, - unsigned int ngranules) -{ - unsigned int granno; - unsigned int gatidx; - unsigned int gatbit; - unsigned int avail; - uint32_t gatmask; - - /* Determine the granule number of the allocation */ - - granno = (alloc - priv->heapstart) >> priv->log2gran; - - /* Determine the GAT table index associated with the allocation */ - - gatidx = granno >> 5; - gatbit = granno & 31; - - /* Mark bits in the GAT entry or entries */ - - avail = 32 - gatbit; - if (ngranules > avail) - { - /* Mark bits in the first GAT entry */ - - gatmask =0xffffffff << gatbit; - DEBUGASSERT((priv->gat[gatidx] & gatmask) == 0); - - priv->gat[gatidx] |= gatmask; - ngranules -= avail; - - /* Mark bits in the second GAT entry */ - - gatmask = 0xffffffff >> (32 - ngranules); - DEBUGASSERT((priv->gat[gatidx+1] & gatmask) == 0); - - priv->gat[gatidx+1] |= gatmask; - } - - /* Handle the case where where all of the granules come from one entry */ - - else - { - /* Mark bits in a single GAT entry */ - - gatmask = 0xffffffff >> (32 - ngranules); - gatmask <<= gatbit; - DEBUGASSERT((priv->gat[gatidx] & gatmask) == 0); - - priv->gat[gatidx] |= gatmask; - return; - } - -} - /**************************************************************************** * Name: gran_common_alloc * diff --git a/mm/mm_granmark.c b/mm/mm_granmark.c new file mode 100644 index 0000000000..a2c9e9054e --- /dev/null +++ b/mm/mm_granmark.c @@ -0,0 +1,132 @@ +/**************************************************************************** + * mm/mm_granmark.c + * + * Copyright (C) 2012, 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include + +#include "mm_gran.h" + +#ifdef CONFIG_GRAN + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gran_mark_allocated + * + * Description: + * Mark a range of granules as allocated. + * + * Input Parameters: + * priv - The granule heap state structure. + * alloc - The address of the allocation. + * ngranules - The number of granules allocated + * + * Returned Value: + * None + * + ****************************************************************************/ + +void gran_mark_allocated(FAR struct gran_s *priv, uintptr_t alloc, + unsigned int ngranules) +{ + unsigned int granno; + unsigned int gatidx; + unsigned int gatbit; + unsigned int avail; + uint32_t gatmask; + + /* Determine the granule number of the allocation */ + + granno = (alloc - priv->heapstart) >> priv->log2gran; + + /* Determine the GAT table index associated with the allocation */ + + gatidx = granno >> 5; + gatbit = granno & 31; + + /* Mark bits in the GAT entry or entries */ + + avail = 32 - gatbit; + if (ngranules > avail) + { + /* Mark bits in the first GAT entry */ + + gatmask =0xffffffff << gatbit; + DEBUGASSERT((priv->gat[gatidx] & gatmask) == 0); + + priv->gat[gatidx] |= gatmask; + ngranules -= avail; + + /* Mark bits in the second GAT entry */ + + gatmask = 0xffffffff >> (32 - ngranules); + DEBUGASSERT((priv->gat[gatidx+1] & gatmask) == 0); + + priv->gat[gatidx+1] |= gatmask; + } + + /* Handle the case where where all of the granules come from one entry */ + + else + { + /* Mark bits in a single GAT entry */ + + gatmask = 0xffffffff >> (32 - ngranules); + gatmask <<= gatbit; + DEBUGASSERT((priv->gat[gatidx] & gatmask) == 0); + + priv->gat[gatidx] |= gatmask; + return; + } +} + +#endif /* CONFIG_GRAN */ diff --git a/mm/mm_granreserve.c b/mm/mm_granreserve.c new file mode 100644 index 0000000000..e336a228b2 --- /dev/null +++ b/mm/mm_granreserve.c @@ -0,0 +1,144 @@ +/**************************************************************************** + * mm/mm_granreserve.c + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include + +#include + +#include "mm_gran.h" + +#ifdef CONFIG_GRAN + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gran_common_reserve + * + * Description: + * Reserve memory in the granule heap. This will reserve the granules + * that contain the start and end addresses plus all of the granules + * in between. This should be done early in the initialization sequence + * before any other allocations are made. + * + * Reserved memory can never be allocated (it can be freed however which + * essentially unreserves the memory). + * + * Input Parameters: + * priv - The granule heap state structure. + * start - The address of the beginning of the region to be reserved. + * size - The size of the region to be reserved + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void gran_common_reserve(FAR struct gran_s *priv, + uintptr_t start, size_t size) +{ + if (size > 0) + { + uintptr_t mask = (1 << priv->log2gran) - 1; + uintptr_t end = start + size - 1; + unsigned int ngranules; + + /* Get the aligned (down) start address and the aligned (up) end + * address + */ + + start &= ~mask; + end = (end + mask) & ~mask; + + /* Calculate the new size in granuales */ + + ngranules = ((end - start) >> priv->log2gran) + 1; + + /* And reserve the granules */ + + gran_mark_allocated(priv, start, ngranules); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gran_reserve + * + * Description: + * Reserve memory in the granule heap. This will reserve the granules + * that contain the start and end addresses plus all of the granules + * in between. This should be done early in the initialization sequence + * before any other allocations are made. + * + * Reserved memory can never be allocated (it can be freed however which + * essentially unreserves the memory). + * + * Input Parameters: + * handle - The handle previously returned by gran_initialize + * start - The address of the beginning of the region to be reserved. + * size - The size of the region to be reserved + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_GRAN_SINGLE +void gran_reserve(uintptr_t start, size_t size) +{ + return gran_common_reserve(g_graninfo, start, size); +} +#else +void gran_reserve(GRAN_HANDLE handle, uintptr_t start, size_t size) +{ + return gran_common_reserve((FAR struct gran_s *)handle, start, size); +} +#endif + +#endif /* CONFIG_GRAN */