From 08c11b47be8f255682246e4aeffe85f56991c73e Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Mon, 4 Feb 2019 12:55:59 +0000 Subject: [PATCH] Core allocator enhancements. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12637 110e8d01-0319-4d1e-a829-52ad28d1bb01 --- os/oslib/include/chmemcore.h | 41 +++++++---- os/oslib/src/chmemcore.c | 88 +++++++++++++++++++----- os/various/syscalls.c | 127 +++++++++++++++++------------------ readme.txt | 8 +++ 4 files changed, 165 insertions(+), 99 deletions(-) diff --git a/os/oslib/include/chmemcore.h b/os/oslib/include/chmemcore.h index b9b728389..3c81a50bd 100644 --- a/os/oslib/include/chmemcore.h +++ b/os/oslib/include/chmemcore.h @@ -82,17 +82,33 @@ typedef struct { /** * @brief Next free address. */ - uint8_t *nextmem; + uint8_t *basemem; /** * @brief Final address. */ - uint8_t *endmem; + uint8_t *topmem; } memcore_t; /*===========================================================================*/ /* Module macros. */ /*===========================================================================*/ +/** + * @brief Allocates a memory block. + * @note This is a generic form with unspecified allocation position. + * + * @iclass + */ +#define chCoreAllocAlignedWithOffsetI chCoreAllocFromTopI + +/** + * @brief Allocates a memory block. + * @note This is a generic form with unspecified allocation position. + * + * @api + */ +#define chCoreAllocAlignedWithOffset chCoreAllocFromTop + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ @@ -105,12 +121,10 @@ extern memcore_t ch_memcore; extern "C" { #endif void _core_init(void); - void *chCoreAllocAlignedWithOffsetI(size_t size, - unsigned align, - size_t offset); - void *chCoreAllocAlignedWithOffset(size_t size, - unsigned align, - size_t offset); + void *chCoreAllocFromBaseI(size_t size, unsigned align, size_t offset); + void *chCoreAllocFromTopI(size_t size, unsigned align, size_t offset); + void *chCoreAllocFromBase(size_t size, unsigned align, size_t offset); + void *chCoreAllocFromTop(size_t size, unsigned align, size_t offset); size_t chCoreGetStatusX(void); #ifdef __cplusplus } @@ -124,6 +138,7 @@ extern "C" { * @brief Allocates a memory block. * @details The allocated block is guaranteed to be properly aligned to the * specified alignment. + * @note This is a generic form with unspecified allocation position. * * @param[in] size the size of the block to be allocated. * @param[in] align desired memory alignment @@ -141,6 +156,7 @@ static inline void *chCoreAllocAlignedI(size_t size, unsigned align) { * @brief Allocates a memory block. * @details The allocated block is guaranteed to be properly aligned to the * specified alignment. + * @note This is a generic form with unspecified allocation position. * * @param[in] size the size of the block to be allocated * @param[in] align desired memory alignment @@ -150,19 +166,15 @@ static inline void *chCoreAllocAlignedI(size_t size, unsigned align) { * @api */ static inline void *chCoreAllocAligned(size_t size, unsigned align) { - void *p; - chSysLock(); - p = chCoreAllocAlignedWithOffsetI(size, align, 0U); - chSysUnlock(); - - return p; + return chCoreAllocAlignedWithOffset(size, align, 0U); } /** * @brief Allocates a memory block. * @details The allocated block is guaranteed to be properly aligned for a * pointer data type. + * @note This is a generic form with unspecified allocation position. * * @param[in] size the size of the block to be allocated. * @return A pointer to the allocated memory block. @@ -179,6 +191,7 @@ static inline void *chCoreAllocI(size_t size) { * @brief Allocates a memory block. * @details The allocated block is guaranteed to be properly aligned for a * pointer data type. + * @note This is a generic form with unspecified allocation position. * * @param[in] size the size of the block to be allocated. * @return A pointer to the allocated memory block. diff --git a/os/oslib/src/chmemcore.c b/os/oslib/src/chmemcore.c index 5dc3ce446..73e2b0c89 100644 --- a/os/oslib/src/chmemcore.c +++ b/os/oslib/src/chmemcore.c @@ -84,19 +84,19 @@ void _core_init(void) { extern uint8_t __heap_end__[]; /*lint -save -e9033 [10.8] Required cast operations.*/ - ch_memcore.nextmem = __heap_base__; - ch_memcore.endmem = __heap_end__; + ch_memcore.basemem = __heap_base__; + ch_memcore.topmem = __heap_end__; /*lint restore*/ #else static uint8_t static_heap[CH_CFG_MEMCORE_SIZE]; - ch_memcore.nextmem = &static_heap[0]; - ch_memcore.endmem = &static_heap[CH_CFG_MEMCORE_SIZE]; + ch_memcore.basemem = &static_heap[0]; + ch_memcore.topmem = &static_heap[CH_CFG_MEMCORE_SIZE]; #endif } /** - * @brief Allocates a memory block. + * @brief Allocates a memory block starting from the lowest address upward. * @details This function allocates a block of @p offset + @p size bytes. The * returned pointer has @p offset bytes before its address and * @p size bytes after. @@ -109,30 +109,60 @@ void _core_init(void) { * * @iclass */ -void *chCoreAllocAlignedWithOffsetI(size_t size, - unsigned align, - size_t offset) { +void *chCoreAllocFromBaseI(size_t size, unsigned align, size_t offset) { uint8_t *p, *next; chDbgCheckClassI(); chDbgCheck(MEM_IS_VALID_ALIGNMENT(align)); - size = MEM_ALIGN_NEXT(size, align); - p = (uint8_t *)MEM_ALIGN_NEXT(ch_memcore.nextmem + offset, align); + p = (uint8_t *)MEM_ALIGN_NEXT(ch_memcore.basemem + offset, align); next = p + size; /* Considering also the case where there is numeric overflow.*/ - if ((next > ch_memcore.endmem) || (next < ch_memcore.nextmem)) { + if ((next > ch_memcore.topmem) || (next < ch_memcore.basemem)) { return NULL; } - ch_memcore.nextmem = next; + ch_memcore.basemem = next; return p; } /** - * @brief Allocates a memory block. + * @brief Allocates a memory block starting from the top address downward. + * @details This function allocates a block of @p offset + @p size bytes. The + * returned pointer has @p offset bytes before its address and + * @p size bytes after. + * + * @param[in] size the size of the block to be allocated. + * @param[in] align desired memory alignment + * @param[in] offset aligned pointer offset + * @return A pointer to the allocated memory block. + * @retval NULL allocation failed, core memory exhausted. + * + * @iclass + */ +void *chCoreAllocFromTopI(size_t size, unsigned align, size_t offset) { + uint8_t *p, *prev; + + chDbgCheckClassI(); + chDbgCheck(MEM_IS_VALID_ALIGNMENT(align)); + + p = (uint8_t *)MEM_ALIGN_PREV(ch_memcore.topmem - size, align); + prev = p - offset; + + /* Considering also the case where there is numeric overflow.*/ + if ((prev < ch_memcore.basemem) || (prev > ch_memcore.topmem)) { + return NULL; + } + + ch_memcore.topmem = prev; + + return p; +} + +/** + * @brief Allocates a memory block starting from the lowest address upward. * @details This function allocates a block of @p offset + @p size bytes. The * returned pointer has @p offset bytes before its address and * @p size bytes after. @@ -145,13 +175,35 @@ void *chCoreAllocAlignedWithOffsetI(size_t size, * * @api */ -void *chCoreAllocAlignedWithOffset(size_t size, - unsigned align, - size_t offset) { +void *chCoreAllocFromBase(size_t size, unsigned align, size_t offset) { void *p; chSysLock(); - p = chCoreAllocAlignedWithOffsetI(size, align, offset); + p = chCoreAllocFromBaseI(size, align, offset); + chSysUnlock(); + + return p; +} + +/** + * @brief Allocates a memory block starting from the top address downward. + * @details This function allocates a block of @p offset + @p size bytes. The + * returned pointer has @p offset bytes before its address and + * @p size bytes after. + * + * @param[in] size the size of the block to be allocated. + * @param[in] align desired memory alignment + * @param[in] offset aligned pointer offset + * @return A pointer to the allocated memory block. + * @retval NULL allocation failed, core memory exhausted. + * + * @api + */ +void *chCoreAllocFromTop(size_t size, unsigned align, size_t offset) { + void *p; + + chSysLock(); + p = chCoreAllocFromTopI(size, align, offset); chSysUnlock(); return p; @@ -167,7 +219,7 @@ void *chCoreAllocAlignedWithOffset(size_t size, size_t chCoreGetStatusX(void) { /*lint -save -e9033 [10.8] The cast is safe.*/ - return (size_t)(ch_memcore.endmem - ch_memcore.nextmem); + return (size_t)(ch_memcore.topmem - ch_memcore.basemem); /*lint -restore*/ } #endif /* CH_CFG_USE_MEMCORE == TRUE */ diff --git a/os/various/syscalls.c b/os/various/syscalls.c index 72e28a830..8da8f755a 100644 --- a/os/various/syscalls.c +++ b/os/various/syscalls.c @@ -1,58 +1,58 @@ /* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ /* -* **** This file incorporates work covered by the following copyright and **** -* **** permission notice: **** -* -* Copyright (c) 2009 by Michael Fischer. All rights reserved. -* -* 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 of the author 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. -* -**************************************************************************** -* History: -* -* 28.03.09 mifi First Version, based on the original syscall.c from -* newlib version 1.17.0 -* 17.08.09 gdisirio Modified the file for use under ChibiOS/RT -* 15.11.09 gdisirio Added read and write handling -****************************************************************************/ + * **** This file incorporates work covered by the following copyright and **** + * **** permission notice: **** + * + * Copyright (c) 2009 by Michael Fischer. All rights reserved. + * + * 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 of the author 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. + * + **************************************************************************** + * History: + * + * 28.03.09 mifi First Version, based on the original syscall.c from + * newlib version 1.17.0 + * 17.08.09 gdisirio Modified the file for use under ChibiOS/RT + * 15.11.09 gdisirio Added read and write handling + ****************************************************************************/ #include #include @@ -68,8 +68,7 @@ /***************************************************************************/ __attribute__((used)) -int _read_r(struct _reent *r, int file, char * ptr, int len) -{ +int _read_r(struct _reent *r, int file, char * ptr, int len) { (void)r; #if defined(STDIN_SD) if (!len || (file != 0)) { @@ -82,7 +81,7 @@ int _read_r(struct _reent *r, int file, char * ptr, int len) (void)file; (void)ptr; (void)len; - __errno_r(r) = EINVAL; + __errno_r(r) = EINVAL; return -1; #endif } @@ -90,8 +89,7 @@ int _read_r(struct _reent *r, int file, char * ptr, int len) /***************************************************************************/ __attribute__((used)) -int _lseek_r(struct _reent *r, int file, int ptr, int dir) -{ +int _lseek_r(struct _reent *r, int file, int ptr, int dir) { (void)r; (void)file; (void)ptr; @@ -103,8 +101,7 @@ int _lseek_r(struct _reent *r, int file, int ptr, int dir) /***************************************************************************/ __attribute__((used)) -int _write_r(struct _reent *r, int file, char * ptr, int len) -{ +int _write_r(struct _reent *r, int file, char * ptr, int len) { (void)r; (void)file; (void)ptr; @@ -121,8 +118,7 @@ int _write_r(struct _reent *r, int file, char * ptr, int len) /***************************************************************************/ __attribute__((used)) -int _close_r(struct _reent *r, int file) -{ +int _close_r(struct _reent *r, int file) { (void)r; (void)file; @@ -132,16 +128,15 @@ int _close_r(struct _reent *r, int file) /***************************************************************************/ __attribute__((used)) -caddr_t _sbrk_r(struct _reent *r, int incr) -{ +caddr_t _sbrk_r(struct _reent *r, int incr) { #if CH_CFG_USE_MEMCORE void *p; chDbgCheck(incr >= 0); - p = chCoreAlloc((size_t)incr); + p = chCoreAllocFromBase((size_t)incr, 1U, 0U); if (p == NULL) { - __errno_r(r) = ENOMEM; + __errno_r(r) = ENOMEM; return (caddr_t)-1; } return (caddr_t)p; @@ -155,8 +150,7 @@ caddr_t _sbrk_r(struct _reent *r, int incr) /***************************************************************************/ __attribute__((used)) -int _fstat_r(struct _reent *r, int file, struct stat * st) -{ +int _fstat_r(struct _reent *r, int file, struct stat * st) { (void)r; (void)file; @@ -168,8 +162,7 @@ int _fstat_r(struct _reent *r, int file, struct stat * st) /***************************************************************************/ __attribute__((used)) -int _isatty_r(struct _reent *r, int fd) -{ +int _isatty_r(struct _reent *r, int fd) { (void)r; (void)fd; diff --git a/readme.txt b/readme.txt index 9fa5b19dc..46b38f9ae 100644 --- a/readme.txt +++ b/readme.txt @@ -74,6 +74,14 @@ ***************************************************************************** *** Next *** +- VAR: Modified syscalls.c to allocate memory from bottom upward, ChibiOS + allocators take memory from top downward. This way the memory taken + using _sbrk_r() does not contain "holes" caused by other allocators. +- LIB: Modified core allocator to be able to get blocks starting from bottom + or top of the available memory range. + Removed alignment enforcements for requested block size. Alignment is + only ensured on the returned pointer, this should reduce memory usage + is some cases. - HAL: Added mcuconf.h updater tool for STM32F407 (backported to 19.1.1). - NIL: Integrated NIL 4.0. - FIX: Fixed wrong mcuconf.h in some testex demos related to STM32F407