From b16e783aaed6f30f1e276d68bcebc0cac7ed644a Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Sat, 17 Mar 2018 21:44:30 +0000 Subject: Typo. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11804 110e8d01-0319-4d1e-a829-52ad28d1bb01 --- os/hal/ports/simulator/posix/hal_lld.c | 2 +- os/hal/ports/simulator/win32/hal_lld.c | 2 +- os/lib/include/chfifo.h | 338 ---------------------------- os/lib/include/chheap.h | 178 --------------- os/lib/include/chlib.h | 4 +- os/lib/include/chmemheaps.h | 178 +++++++++++++++ os/lib/include/chobjfifos.h | 338 ++++++++++++++++++++++++++++ os/lib/lib.mk | 4 +- os/lib/src/chheap.c | 399 --------------------------------- os/lib/src/chmemheaps.c | 399 +++++++++++++++++++++++++++++++++ 10 files changed, 921 insertions(+), 921 deletions(-) delete mode 100644 os/lib/include/chfifo.h delete mode 100644 os/lib/include/chheap.h create mode 100644 os/lib/include/chmemheaps.h create mode 100644 os/lib/include/chobjfifos.h delete mode 100644 os/lib/src/chheap.c create mode 100644 os/lib/src/chmemheaps.c diff --git a/os/hal/ports/simulator/posix/hal_lld.c b/os/hal/ports/simulator/posix/hal_lld.c index 449fd8e98..0015f5b24 100755 --- a/os/hal/ports/simulator/posix/hal_lld.c +++ b/os/hal/ports/simulator/posix/hal_lld.c @@ -74,7 +74,7 @@ void _sim_check_for_interrupts(void) { #if HAL_USE_SERIAL if (sd_lld_interrupt_pending()) { - int_occured = true; + int_occurred = true; } #endif diff --git a/os/hal/ports/simulator/win32/hal_lld.c b/os/hal/ports/simulator/win32/hal_lld.c index e00aab428..6a0220b91 100644 --- a/os/hal/ports/simulator/win32/hal_lld.c +++ b/os/hal/ports/simulator/win32/hal_lld.c @@ -87,7 +87,7 @@ void _sim_check_for_interrupts(void) { /* Interrupt Timer simulation (10ms interval).*/ QueryPerformanceCounter(&n); if (n.QuadPart > nextcnt.QuadPart) { - int_occured = true; + int_occurred = true; nextcnt.QuadPart += slice.QuadPart; CH_IRQ_PROLOGUE(); diff --git a/os/lib/include/chfifo.h b/os/lib/include/chfifo.h deleted file mode 100644 index 066de53e6..000000000 --- a/os/lib/include/chfifo.h +++ /dev/null @@ -1,338 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file chfifo.h - * @brief Objects FIFO structures and macros. - * @details This module implements a generic FIFO queue of objects by - * coupling a Guarded Memory Pool (for objects storage) and - * a MailBox.
- * On the sender side free objects are taken from the pool, filled - * and then sent to the receiver, on the receiver side objects are - * fetched, used and then returned to the pool. - * Operations defined for object FIFOs: - * - Take: An object is taken from the pool of the free - * objects, can be blocking. - * - Return: An object is returned to the pool of the - * free objects, it is guaranteed to be non-blocking. - * - Send: An object is sent through the mailbox, it is - * guaranteed to be non-blocking - * - Receive: An object is received from the mailbox, - * can be blocking. - * . - * - * @addtogroup objects_fifo - * @{ - */ - -#ifndef CHFIFO_H -#define CHFIFO_H - -#if (CH_CFG_USE_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if CH_CFG_USE_MEMPOOLS == FALSE -#error "CH_CFG_USE_OBJ_FIFOS requires CH_CFG_USE_MEMPOOLS" -#endif - -#if CH_CFG_USE_SEMAPHORES == FALSE -#error "CH_CFG_USE_OBJ_FIFOS requires CH_CFG_USE_SEMAPHORES" -#endif - -#if CH_CFG_USE_MAILBOXES == FALSE -#error "CH_CFG_USE_OBJ_FIFOS requires CH_CFG_USE_MAILBOXES" -#endif - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of an objects FIFO. - */ -typedef struct ch_objects_fifo { - /** - * @brief Pool of the free objects. - */ - guarded_memory_pool_t free; - /** - * @brief Mailbox of the sent objects. - */ - mailbox_t mbx; -} objects_fifo_t; - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes a FIFO object. - * @pre The messages size must be a multiple of the alignment - * requirement. - * - * @param[out] ofp pointer to a @p objects_fifo_t structure - * @param[in] objsize size of objects - * @param[in] objn number of objects available - * @param[in] objalign required objects alignment - * @param[in] objbuf pointer to the buffer of objects, it must be able - * to hold @p objn objects of @p objsize size with - * @p objealign alignment - * @param[in] msgbuf pointer to the buffer of messages, it must be able - * to hold @p objn messages - * - * @init - */ -static inline void chFifoObjectInit(objects_fifo_t *ofp, size_t objsize, - size_t objn, unsigned objalign, - void *objbuf, msg_t *msgbuf) { - - chGuardedPoolObjectInitAligned(&ofp->free, objsize, objalign); - chGuardedPoolLoadArray(&ofp->free, objbuf, objn); - chMBObjectInit(&ofp->mbx, msgbuf, objn); -} - -/** - * @brief Allocates a free object. - * - * @param[in] ofp pointer to a @p objects_fifo_t structure - * @return The pointer to the allocated object. - * @retval NULL if an object is not immediately available. - * - * @iclass - */ -static inline void *chFifoTakeObjectI(objects_fifo_t *ofp) { - - return chGuardedPoolAllocI(&ofp->free); -} - -/** - * @brief Allocates a free object. - * - * @param[in] ofp pointer to a @p objects_fifo_t structure - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. - * - @a TIME_INFINITE no timeout. - * . - * @return The pointer to the allocated object. - * @retval NULL if an object is not available within the specified - * timeout. - * - * @sclass - */ -static inline void *chFifoTakeObjectTimeoutS(objects_fifo_t *ofp, - sysinterval_t timeout) { - - return chGuardedPoolAllocTimeoutS(&ofp->free, timeout); -} - -/** - * @brief Allocates a free object. - * - * @param[in] ofp pointer to a @p objects_fifo_t structure - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. - * - @a TIME_INFINITE no timeout. - * . - * @return The pointer to the allocated object. - * @retval NULL if an object is not available within the specified - * timeout. - * - * @api - */ -static inline void *chFifoTakeObjectTimeout(objects_fifo_t *ofp, - sysinterval_t timeout) { - - return chGuardedPoolAllocTimeout(&ofp->free, timeout); -} - -/** - * @brief Releases a fetched object. - * - * @param[in] ofp pointer to a @p objects_fifo_t structure - * @param[in] objp pointer to the object to be released - * - * @iclass - */ -static inline void chFifoReturnObjectI(objects_fifo_t *ofp, - void *objp) { - - chGuardedPoolFreeI(&ofp->free, objp); -} - -/** - * @brief Releases a fetched object. - * - * @param[in] ofp pointer to a @p objects_fifo_t structure - * @param[in] objp pointer to the object to be released - * - * @api - */ -static inline void chFifoReturnObject(objects_fifo_t *ofp, - void *objp) { - - chGuardedPoolFree(&ofp->free, objp); -} - -/** - * @brief Posts an object. - * @note By design the object can be always immediately posted. - * - * @param[in] ofp pointer to a @p objects_fifo_t structure - * @param[in] objp pointer to the object to be posted - * - * @iclass - */ -static inline void chFifoSendObjectI(objects_fifo_t *ofp, - void *objp) { - msg_t msg; - - msg = chMBPostI(&ofp->mbx, (msg_t)objp); - chDbgAssert(msg == MSG_OK, "post failed"); -} - -/** - * @brief Posts an object. - * @note By design the object can be always immediately posted. - * - * @param[in] ofp pointer to a @p objects_fifo_t structure - * @param[in] objp pointer to the object to be posted - * - * @sclass - */ -static inline void chFifoSendObjectS(objects_fifo_t *ofp, - void *objp) { - msg_t msg; - - msg = chMBPostTimeoutS(&ofp->mbx, (msg_t)objp, TIME_IMMEDIATE); - chDbgAssert(msg == MSG_OK, "post failed"); -} - -/** - * @brief Posts an object. - * @note By design the object can be always immediately posted. - * - * @param[in] ofp pointer to a @p objects_fifo_t structure - * @param[in] objp pointer to the object to be released - * - * @api - */ -static inline void chFifoSendObject(objects_fifo_t *ofp, void *objp) { - - msg_t msg; - - msg = chMBPostTimeout(&ofp->mbx, (msg_t)objp, TIME_IMMEDIATE); - chDbgAssert(msg == MSG_OK, "post failed"); -} - -/** - * @brief Fetches an object. - * - * @param[in] ofp pointer to a @p objects_fifo_t structure - * @param[in] objpp pointer to the fetched object reference - * @return The operation status. - * @retval MSG_OK if an object has been correctly fetched. - * @retval MSG_TIMEOUT if the FIFO is empty and a message cannot be fetched. - * - * @iclass - */ -static inline msg_t chFifoReceiveObjectI(objects_fifo_t *ofp, - void **objpp) { - - return chMBFetchI(&ofp->mbx, (msg_t *)objpp); -} - -/** - * @brief Fetches an object. - * - * @param[in] ofp pointer to a @p objects_fifo_t structure - * @param[in] objpp pointer to the fetched object reference - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval MSG_OK if an object has been correctly fetched. - * @retval MSG_TIMEOUT if the operation has timed out. - * - * @sclass - */ -static inline msg_t chFifoReceiveObjectTimeoutS(objects_fifo_t *ofp, - void **objpp, - sysinterval_t timeout) { - - return chMBFetchTimeoutS(&ofp->mbx, (msg_t *)objpp, timeout); -} - -/** - * @brief Fetches an object. - * - * @param[in] ofp pointer to a @p objects_fifo_t structure - * @param[in] objpp pointer to the fetched object reference - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval MSG_OK if an object has been correctly fetched. - * @retval MSG_TIMEOUT if the operation has timed out. - * - * @api - */ -static inline msg_t chFifoReceiveObjectTimeout(objects_fifo_t *ofp, - void **objpp, - sysinterval_t timeout) { - - return chMBFetchTimeout(&ofp->mbx, (msg_t *)objpp, timeout); -} -#endif /* CH_CFG_USE_OBJ_FIFOS == TRUE */ - -#endif /* CHFIFO_H */ - -/** @} */ diff --git a/os/lib/include/chheap.h b/os/lib/include/chheap.h deleted file mode 100644 index 24e8e4761..000000000 --- a/os/lib/include/chheap.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file chheap.h - * @brief Heaps macros and structures. - * - * @addtogroup heaps - * @{ - */ - -#ifndef CHHEAP_H -#define CHHEAP_H - -#if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/** - * @brief Minimum alignment used for heap. - * @note Cannot use the sizeof operator in this macro. - */ -#if (SIZEOF_PTR == 4) || defined(__DOXYGEN__) -#define CH_HEAP_ALIGNMENT 8U -#elif (SIZEOF_PTR == 2) -#define CH_HEAP_ALIGNMENT 4U -#else -#error "unsupported pointer size" -#endif - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if CH_CFG_USE_MEMCORE == FALSE -#error "CH_CFG_USE_HEAP requires CH_CFG_USE_MEMCORE" -#endif - -#if (CH_CFG_USE_MUTEXES == FALSE) && (CH_CFG_USE_SEMAPHORES == FALSE) -#error "CH_CFG_USE_HEAP requires CH_CFG_USE_MUTEXES and/or CH_CFG_USE_SEMAPHORES" -#endif - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a memory heap. - */ -typedef struct memory_heap memory_heap_t; - -/** - * @brief Type of a memory heap header. - */ -typedef union heap_header heap_header_t; - -/** - * @brief Memory heap block header. - */ -union heap_header { - struct { - heap_header_t *next; /**< @brief Next block in free list. */ - size_t pages; /**< @brief Size of the area in pages. */ - } free; - struct { - memory_heap_t *heap; /**< @brief Block owner heap. */ - size_t size; /**< @brief Size of the area in bytes. */ - } used; -}; - -/** - * @brief Structure describing a memory heap. - */ -struct memory_heap { - memgetfunc2_t provider; /**< @brief Memory blocks provider for - this heap. */ - heap_header_t header; /**< @brief Free blocks list header. */ -#if CH_CFG_USE_MUTEXES == TRUE - mutex_t mtx; /**< @brief Heap access mutex. */ -#else - semaphore_t sem; /**< @brief Heap access semaphore. */ -#endif -}; - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/** - * @brief Allocation of an aligned static heap buffer. - */ -#define CH_HEAP_AREA(name, size) \ - ALIGNED_VAR(CH_HEAP_ALIGNMENT) \ - uint8_t name[MEM_ALIGN_NEXT((size), CH_HEAP_ALIGNMENT)] - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void _heap_init(void); - void chHeapObjectInit(memory_heap_t *heapp, void *buf, size_t size); - void *chHeapAllocAligned(memory_heap_t *heapp, size_t size, unsigned align); - void chHeapFree(void *p); - size_t chHeapStatus(memory_heap_t *heapp, size_t *totalp, size_t *largestp); -#ifdef __cplusplus -} -#endif - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/** - * @brief Allocates a block of memory from the heap by using the first-fit - * algorithm. - * @details The allocated block is guaranteed to be properly aligned for a - * pointer data type. - * - * @param[in] heapp pointer to a heap descriptor or @p NULL in order to - * access the default heap. - * @param[in] size the size of the block to be allocated. Note that the - * allocated block may be a bit bigger than the requested - * size for alignment and fragmentation reasons. - * @return A pointer to the allocated block. - * @retval NULL if the block cannot be allocated. - * - * @api - */ -static inline void *chHeapAlloc(memory_heap_t *heapp, size_t size) { - - return chHeapAllocAligned(heapp, size, CH_HEAP_ALIGNMENT); -} - -/** - * @brief Returns the size of an allocated block. - * @note The returned value is the requested size, the real size is the - * same value aligned to the next @p CH_HEAP_ALIGNMENT multiple. - * - * @param[in] p pointer to the memory block - * @return Size of the block. - * - * @api - */ -static inline size_t chHeapGetSize(const void *p) { - - return ((heap_header_t *)p - 1U)->used.size; -} - -#endif /* CH_CFG_USE_HEAP == TRUE */ - -#endif /* CHHEAP_H */ - -/** @} */ diff --git a/os/lib/include/chlib.h b/os/lib/include/chlib.h index 6a1944e53..674561cb8 100644 --- a/os/lib/include/chlib.h +++ b/os/lib/include/chlib.h @@ -210,9 +210,9 @@ #include "chbsem.h" #include "chmboxes.h" #include "chmemcore.h" -#include "chheap.h" +#include "chmemheaps.h" #include "chmempools.h" -#include "chfifo.h" +#include "chobjfifos.h" //#include "chpipes.h" #include "chfactory.h" diff --git a/os/lib/include/chmemheaps.h b/os/lib/include/chmemheaps.h new file mode 100644 index 000000000..59248a89e --- /dev/null +++ b/os/lib/include/chmemheaps.h @@ -0,0 +1,178 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chmemheaps.h + * @brief Memory heaps macros and structures. + * + * @addtogroup heaps + * @{ + */ + +#ifndef CHMEMHEAPS_H +#define CHMEMHEAPS_H + +#if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @brief Minimum alignment used for heap. + * @note Cannot use the sizeof operator in this macro. + */ +#if (SIZEOF_PTR == 4) || defined(__DOXYGEN__) +#define CH_HEAP_ALIGNMENT 8U +#elif (SIZEOF_PTR == 2) +#define CH_HEAP_ALIGNMENT 4U +#else +#error "unsupported pointer size" +#endif + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if CH_CFG_USE_MEMCORE == FALSE +#error "CH_CFG_USE_HEAP requires CH_CFG_USE_MEMCORE" +#endif + +#if (CH_CFG_USE_MUTEXES == FALSE) && (CH_CFG_USE_SEMAPHORES == FALSE) +#error "CH_CFG_USE_HEAP requires CH_CFG_USE_MUTEXES and/or CH_CFG_USE_SEMAPHORES" +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a memory heap. + */ +typedef struct memory_heap memory_heap_t; + +/** + * @brief Type of a memory heap header. + */ +typedef union heap_header heap_header_t; + +/** + * @brief Memory heap block header. + */ +union heap_header { + struct { + heap_header_t *next; /**< @brief Next block in free list. */ + size_t pages; /**< @brief Size of the area in pages. */ + } free; + struct { + memory_heap_t *heap; /**< @brief Block owner heap. */ + size_t size; /**< @brief Size of the area in bytes. */ + } used; +}; + +/** + * @brief Structure describing a memory heap. + */ +struct memory_heap { + memgetfunc2_t provider; /**< @brief Memory blocks provider for + this heap. */ + heap_header_t header; /**< @brief Free blocks list header. */ +#if CH_CFG_USE_MUTEXES == TRUE + mutex_t mtx; /**< @brief Heap access mutex. */ +#else + semaphore_t sem; /**< @brief Heap access semaphore. */ +#endif +}; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Allocation of an aligned static heap buffer. + */ +#define CH_HEAP_AREA(name, size) \ + ALIGNED_VAR(CH_HEAP_ALIGNMENT) \ + uint8_t name[MEM_ALIGN_NEXT((size), CH_HEAP_ALIGNMENT)] + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void _heap_init(void); + void chHeapObjectInit(memory_heap_t *heapp, void *buf, size_t size); + void *chHeapAllocAligned(memory_heap_t *heapp, size_t size, unsigned align); + void chHeapFree(void *p); + size_t chHeapStatus(memory_heap_t *heapp, size_t *totalp, size_t *largestp); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Allocates a block of memory from the heap by using the first-fit + * algorithm. + * @details The allocated block is guaranteed to be properly aligned for a + * pointer data type. + * + * @param[in] heapp pointer to a heap descriptor or @p NULL in order to + * access the default heap. + * @param[in] size the size of the block to be allocated. Note that the + * allocated block may be a bit bigger than the requested + * size for alignment and fragmentation reasons. + * @return A pointer to the allocated block. + * @retval NULL if the block cannot be allocated. + * + * @api + */ +static inline void *chHeapAlloc(memory_heap_t *heapp, size_t size) { + + return chHeapAllocAligned(heapp, size, CH_HEAP_ALIGNMENT); +} + +/** + * @brief Returns the size of an allocated block. + * @note The returned value is the requested size, the real size is the + * same value aligned to the next @p CH_HEAP_ALIGNMENT multiple. + * + * @param[in] p pointer to the memory block + * @return Size of the block. + * + * @api + */ +static inline size_t chHeapGetSize(const void *p) { + + return ((heap_header_t *)p - 1U)->used.size; +} + +#endif /* CH_CFG_USE_HEAP == TRUE */ + +#endif /* CHMEMHEAPS_H */ + +/** @} */ diff --git a/os/lib/include/chobjfifos.h b/os/lib/include/chobjfifos.h new file mode 100644 index 000000000..51e7bf0a8 --- /dev/null +++ b/os/lib/include/chobjfifos.h @@ -0,0 +1,338 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chobjfifos.h + * @brief Objects FIFO structures and macros. + * @details This module implements a generic FIFO queue of objects by + * coupling a Guarded Memory Pool (for objects storage) and + * a MailBox.
+ * On the sender side free objects are taken from the pool, filled + * and then sent to the receiver, on the receiver side objects are + * fetched, used and then returned to the pool. + * Operations defined for object FIFOs: + * - Take: An object is taken from the pool of the free + * objects, can be blocking. + * - Return: An object is returned to the pool of the + * free objects, it is guaranteed to be non-blocking. + * - Send: An object is sent through the mailbox, it is + * guaranteed to be non-blocking + * - Receive: An object is received from the mailbox, + * can be blocking. + * . + * + * @addtogroup objects_fifo + * @{ + */ + +#ifndef CHOBJFIFOS_H +#define CHOBJFIFOS_H + +#if (CH_CFG_USE_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if CH_CFG_USE_MEMPOOLS == FALSE +#error "CH_CFG_USE_OBJ_FIFOS requires CH_CFG_USE_MEMPOOLS" +#endif + +#if CH_CFG_USE_SEMAPHORES == FALSE +#error "CH_CFG_USE_OBJ_FIFOS requires CH_CFG_USE_SEMAPHORES" +#endif + +#if CH_CFG_USE_MAILBOXES == FALSE +#error "CH_CFG_USE_OBJ_FIFOS requires CH_CFG_USE_MAILBOXES" +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of an objects FIFO. + */ +typedef struct ch_objects_fifo { + /** + * @brief Pool of the free objects. + */ + guarded_memory_pool_t free; + /** + * @brief Mailbox of the sent objects. + */ + mailbox_t mbx; +} objects_fifo_t; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes a FIFO object. + * @pre The messages size must be a multiple of the alignment + * requirement. + * + * @param[out] ofp pointer to a @p objects_fifo_t structure + * @param[in] objsize size of objects + * @param[in] objn number of objects available + * @param[in] objalign required objects alignment + * @param[in] objbuf pointer to the buffer of objects, it must be able + * to hold @p objn objects of @p objsize size with + * @p objealign alignment + * @param[in] msgbuf pointer to the buffer of messages, it must be able + * to hold @p objn messages + * + * @init + */ +static inline void chFifoObjectInit(objects_fifo_t *ofp, size_t objsize, + size_t objn, unsigned objalign, + void *objbuf, msg_t *msgbuf) { + + chGuardedPoolObjectInitAligned(&ofp->free, objsize, objalign); + chGuardedPoolLoadArray(&ofp->free, objbuf, objn); + chMBObjectInit(&ofp->mbx, msgbuf, objn); +} + +/** + * @brief Allocates a free object. + * + * @param[in] ofp pointer to a @p objects_fifo_t structure + * @return The pointer to the allocated object. + * @retval NULL if an object is not immediately available. + * + * @iclass + */ +static inline void *chFifoTakeObjectI(objects_fifo_t *ofp) { + + return chGuardedPoolAllocI(&ofp->free); +} + +/** + * @brief Allocates a free object. + * + * @param[in] ofp pointer to a @p objects_fifo_t structure + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The pointer to the allocated object. + * @retval NULL if an object is not available within the specified + * timeout. + * + * @sclass + */ +static inline void *chFifoTakeObjectTimeoutS(objects_fifo_t *ofp, + sysinterval_t timeout) { + + return chGuardedPoolAllocTimeoutS(&ofp->free, timeout); +} + +/** + * @brief Allocates a free object. + * + * @param[in] ofp pointer to a @p objects_fifo_t structure + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The pointer to the allocated object. + * @retval NULL if an object is not available within the specified + * timeout. + * + * @api + */ +static inline void *chFifoTakeObjectTimeout(objects_fifo_t *ofp, + sysinterval_t timeout) { + + return chGuardedPoolAllocTimeout(&ofp->free, timeout); +} + +/** + * @brief Releases a fetched object. + * + * @param[in] ofp pointer to a @p objects_fifo_t structure + * @param[in] objp pointer to the object to be released + * + * @iclass + */ +static inline void chFifoReturnObjectI(objects_fifo_t *ofp, + void *objp) { + + chGuardedPoolFreeI(&ofp->free, objp); +} + +/** + * @brief Releases a fetched object. + * + * @param[in] ofp pointer to a @p objects_fifo_t structure + * @param[in] objp pointer to the object to be released + * + * @api + */ +static inline void chFifoReturnObject(objects_fifo_t *ofp, + void *objp) { + + chGuardedPoolFree(&ofp->free, objp); +} + +/** + * @brief Posts an object. + * @note By design the object can be always immediately posted. + * + * @param[in] ofp pointer to a @p objects_fifo_t structure + * @param[in] objp pointer to the object to be posted + * + * @iclass + */ +static inline void chFifoSendObjectI(objects_fifo_t *ofp, + void *objp) { + msg_t msg; + + msg = chMBPostI(&ofp->mbx, (msg_t)objp); + chDbgAssert(msg == MSG_OK, "post failed"); +} + +/** + * @brief Posts an object. + * @note By design the object can be always immediately posted. + * + * @param[in] ofp pointer to a @p objects_fifo_t structure + * @param[in] objp pointer to the object to be posted + * + * @sclass + */ +static inline void chFifoSendObjectS(objects_fifo_t *ofp, + void *objp) { + msg_t msg; + + msg = chMBPostTimeoutS(&ofp->mbx, (msg_t)objp, TIME_IMMEDIATE); + chDbgAssert(msg == MSG_OK, "post failed"); +} + +/** + * @brief Posts an object. + * @note By design the object can be always immediately posted. + * + * @param[in] ofp pointer to a @p objects_fifo_t structure + * @param[in] objp pointer to the object to be released + * + * @api + */ +static inline void chFifoSendObject(objects_fifo_t *ofp, void *objp) { + + msg_t msg; + + msg = chMBPostTimeout(&ofp->mbx, (msg_t)objp, TIME_IMMEDIATE); + chDbgAssert(msg == MSG_OK, "post failed"); +} + +/** + * @brief Fetches an object. + * + * @param[in] ofp pointer to a @p objects_fifo_t structure + * @param[in] objpp pointer to the fetched object reference + * @return The operation status. + * @retval MSG_OK if an object has been correctly fetched. + * @retval MSG_TIMEOUT if the FIFO is empty and a message cannot be fetched. + * + * @iclass + */ +static inline msg_t chFifoReceiveObjectI(objects_fifo_t *ofp, + void **objpp) { + + return chMBFetchI(&ofp->mbx, (msg_t *)objpp); +} + +/** + * @brief Fetches an object. + * + * @param[in] ofp pointer to a @p objects_fifo_t structure + * @param[in] objpp pointer to the fetched object reference + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if an object has been correctly fetched. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @sclass + */ +static inline msg_t chFifoReceiveObjectTimeoutS(objects_fifo_t *ofp, + void **objpp, + sysinterval_t timeout) { + + return chMBFetchTimeoutS(&ofp->mbx, (msg_t *)objpp, timeout); +} + +/** + * @brief Fetches an object. + * + * @param[in] ofp pointer to a @p objects_fifo_t structure + * @param[in] objpp pointer to the fetched object reference + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if an object has been correctly fetched. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @api + */ +static inline msg_t chFifoReceiveObjectTimeout(objects_fifo_t *ofp, + void **objpp, + sysinterval_t timeout) { + + return chMBFetchTimeout(&ofp->mbx, (msg_t *)objpp, timeout); +} +#endif /* CH_CFG_USE_OBJ_FIFOS == TRUE */ + +#endif /* CHOBJFIFOS_H */ + +/** @} */ diff --git a/os/lib/lib.mk b/os/lib/lib.mk index f515b0315..c84dd322f 100644 --- a/os/lib/lib.mk +++ b/os/lib/lib.mk @@ -17,7 +17,7 @@ ifneq ($(findstring CH_CFG_USE_MEMCORE TRUE,$(CHLIBCONF)),) LIBSRC += $(CHIBIOS)/os/lib/src/chmemcore.c endif ifneq ($(findstring CH_CFG_USE_HEAP TRUE,$(CHLIBCONF)),) -LIBSRC += $(CHIBIOS)/os/lib/src/chheap.c +LIBSRC += $(CHIBIOS)/os/lib/src/chmemheaps.c endif ifneq ($(findstring CH_CFG_USE_MEMPOOLS TRUE,$(CHLIBCONF)),) LIBSRC += $(CHIBIOS)/os/lib/src/chmempools.c @@ -28,7 +28,7 @@ endif else LIBSRC := $(CHIBIOS)/os/lib/src/chmboxes.c \ $(CHIBIOS)/os/lib/src/chmemcore.c \ - $(CHIBIOS)/os/lib/src/chheap.c \ + $(CHIBIOS)/os/lib/src/chmemheaps.c \ $(CHIBIOS)/os/lib/src/chmempools.c \ $(CHIBIOS)/os/lib/src/chfactory.c endif diff --git a/os/lib/src/chheap.c b/os/lib/src/chheap.c deleted file mode 100644 index d3d25458f..000000000 --- a/os/lib/src/chheap.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file chheap.c - * @brief Heaps code. - * - * @addtogroup heaps - * @details Heap Allocator related APIs. - *

Operation mode

- * The heap allocator implements a first-fit strategy and its APIs - * are functionally equivalent to the usual @p malloc() and @p free() - * library functions. The main difference is that the OS heap APIs - * are guaranteed to be thread safe and there is the ability to - * return memory blocks aligned to arbitrary powers of two.
- * @pre In order to use the heap APIs the @p CH_CFG_USE_HEAP option must - * be enabled in @p chconf.h. - * @note Compatible with RT and NIL. - * @{ - */ - -#include "ch.h" - -#if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Module local definitions. */ -/*===========================================================================*/ - -/* - * Defaults on the best synchronization mechanism available. - */ -#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) -#define H_LOCK(h) chMtxLock(&(h)->mtx) -#define H_UNLOCK(h) chMtxUnlock(&(h)->mtx) -#else -#define H_LOCK(h) (void) chSemWait(&(h)->sem) -#define H_UNLOCK(h) chSemSignal(&(h)->sem) -#endif - -#define H_BLOCK(hp) ((hp) + 1U) - -#define H_LIMIT(hp) (H_BLOCK(hp) + H_PAGES(hp)) - -#define H_NEXT(hp) ((hp)->free.next) - -#define H_PAGES(hp) ((hp)->free.pages) - -#define H_HEAP(hp) ((hp)->used.heap) - -#define H_SIZE(hp) ((hp)->used.size) - -/* - * Number of pages between two pointers in a MISRA-compatible way. - */ -#define NPAGES(p1, p2) \ - /*lint -save -e9033 [10.8] The cast is safe.*/ \ - ((size_t)((p1) - (p2))) \ - /*lint -restore*/ - -/*===========================================================================*/ -/* Module exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local variables. */ -/*===========================================================================*/ - -/** - * @brief Default heap descriptor. - */ -static memory_heap_t default_heap; - -/*===========================================================================*/ -/* Module local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the default heap. - * - * @notapi - */ -void _heap_init(void) { - - default_heap.provider = chCoreAllocAlignedWithOffset; - H_NEXT(&default_heap.header) = NULL; - H_PAGES(&default_heap.header) = 0; -#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) - chMtxObjectInit(&default_heap.mtx); -#else - chSemObjectInit(&default_heap.sem, (cnt_t)1); -#endif -} - -/** - * @brief Initializes a memory heap from a static memory area. - * @note The heap buffer base and size are adjusted if the passed buffer - * is not aligned to @p CH_HEAP_ALIGNMENT. This mean that the - * effective heap size can be less than @p size. - * - * @param[out] heapp pointer to the memory heap descriptor to be initialized - * @param[in] buf heap buffer base - * @param[in] size heap size - * - * @init - */ -void chHeapObjectInit(memory_heap_t *heapp, void *buf, size_t size) { - heap_header_t *hp = (heap_header_t *)MEM_ALIGN_NEXT(buf, CH_HEAP_ALIGNMENT); - - chDbgCheck((heapp != NULL) && (size > 0U)); - - /* Adjusting the size in case the initial block was not correctly - aligned.*/ - /*lint -save -e9033 [10.8] Required cast operations.*/ - size -= (size_t)((uint8_t *)hp - (uint8_t *)buf); - /*lint restore*/ - - /* Initializing the heap header.*/ - heapp->provider = NULL; - H_NEXT(&heapp->header) = hp; - H_PAGES(&heapp->header) = 0; - H_NEXT(hp) = NULL; - H_PAGES(hp) = (size - sizeof (heap_header_t)) / CH_HEAP_ALIGNMENT; -#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) - chMtxObjectInit(&heapp->mtx); -#else - chSemObjectInit(&heapp->sem, (cnt_t)1); -#endif -} - -/** - * @brief Allocates a block of memory from the heap by using the first-fit - * algorithm. - * @details The allocated block is guaranteed to be properly aligned to the - * specified alignment. - * - * @param[in] heapp pointer to a heap descriptor or @p NULL in order to - * access the default heap. - * @param[in] size the size of the block to be allocated. Note that the - * allocated block may be a bit bigger than the requested - * size for alignment and fragmentation reasons. - * @param[in] align desired memory alignment - * @return A pointer to the aligned allocated block. - * @retval NULL if the block cannot be allocated. - * - * @api - */ -void *chHeapAllocAligned(memory_heap_t *heapp, size_t size, unsigned align) { - heap_header_t *qp, *hp, *ahp; - size_t pages; - - chDbgCheck((size > 0U) && MEM_IS_VALID_ALIGNMENT(align)); - - /* If an heap is not specified then the default system header is used.*/ - if (heapp == NULL) { - heapp = &default_heap; - } - - /* Minimum alignment is constrained by the heap header structure size.*/ - if (align < CH_HEAP_ALIGNMENT) { - align = CH_HEAP_ALIGNMENT; - } - - /* Size is converted in number of elementary allocation units.*/ - pages = MEM_ALIGN_NEXT(size, CH_HEAP_ALIGNMENT) / CH_HEAP_ALIGNMENT; - - /* Taking heap mutex/semaphore.*/ - H_LOCK(heapp); - - /* Start of the free blocks list.*/ - qp = &heapp->header; - while (H_NEXT(qp) != NULL) { - - /* Next free block.*/ - hp = H_NEXT(qp); - - /* Pointer aligned to the requested alignment.*/ - ahp = (heap_header_t *)MEM_ALIGN_NEXT(H_BLOCK(hp), align) - 1U; - - if ((ahp < H_LIMIT(hp)) && (pages <= NPAGES(H_LIMIT(hp), ahp + 1U))) { - /* The block is large enough to contain a correctly aligned area - of sufficient size.*/ - - if (ahp > hp) { - /* The block is not properly aligned, must split it.*/ - size_t bpages; - - bpages = NPAGES(H_LIMIT(hp), H_BLOCK(ahp)); - H_PAGES(hp) = NPAGES(ahp, H_BLOCK(hp)); - if (bpages > pages) { - /* The block is bigger than required, must split the excess.*/ - heap_header_t *fp; - - /* Creating the excess block.*/ - fp = H_BLOCK(ahp) + pages; - H_PAGES(fp) = (bpages - pages) - 1U; - - /* Linking the excess block.*/ - H_NEXT(fp) = H_NEXT(hp); - H_NEXT(hp) = fp; - } - - hp = ahp; - } - else { - /* The block is already properly aligned.*/ - - if (H_PAGES(hp) == pages) { - /* Exact size, getting the whole block.*/ - H_NEXT(qp) = H_NEXT(hp); - } - else { - /* The block is bigger than required, must split the excess.*/ - heap_header_t *fp; - - fp = H_BLOCK(hp) + pages; - H_NEXT(fp) = H_NEXT(hp); - H_PAGES(fp) = NPAGES(H_LIMIT(hp), H_BLOCK(fp)); - H_NEXT(qp) = fp; - } - } - - /* Setting in the block owner heap and size.*/ - H_SIZE(hp) = size; - H_HEAP(hp) = heapp; - - /* Releasing heap mutex/semaphore.*/ - H_UNLOCK(heapp); - - /*lint -save -e9087 [11.3] Safe cast.*/ - return (void *)H_BLOCK(hp); - /*lint -restore*/ - } - - /* Next in the free blocks list.*/ - qp = hp; - } - - /* Releasing heap mutex/semaphore.*/ - H_UNLOCK(heapp); - - /* More memory is required, tries to get it from the associated provider - else fails.*/ - if (heapp->provider != NULL) { - ahp = heapp->provider((pages + 1U) * CH_HEAP_ALIGNMENT, - align, - sizeof (heap_header_t)); - if (ahp != NULL) { - hp = ahp - 1U; - H_HEAP(hp) = heapp; - H_SIZE(hp) = size; - - /*lint -save -e9087 [11.3] Safe cast.*/ - return (void *)ahp; - /*lint -restore*/ - } - } - - return NULL; -} - -/** - * @brief Frees a previously allocated memory block. - * - * @param[in] p pointer to the memory block to be freed - * - * @api - */ -void chHeapFree(void *p) { - heap_header_t *qp, *hp; - memory_heap_t *heapp; - - chDbgCheck((p != NULL) && MEM_IS_ALIGNED(p, CH_HEAP_ALIGNMENT)); - - /*lint -save -e9087 [11.3] Safe cast.*/ - hp = (heap_header_t *)p - 1U; - /*lint -restore*/ - heapp = H_HEAP(hp); - qp = &heapp->header; - - /* Size is converted in number of elementary allocation units.*/ - H_PAGES(hp) = MEM_ALIGN_NEXT(H_SIZE(hp), - CH_HEAP_ALIGNMENT) / CH_HEAP_ALIGNMENT; - - /* Taking heap mutex/semaphore.*/ - H_LOCK(heapp); - - while (true) { - chDbgAssert((hp < qp) || (hp >= H_LIMIT(qp)), "within free block"); - - if (((qp == &heapp->header) || (hp > qp)) && - ((H_NEXT(qp) == NULL) || (hp < H_NEXT(qp)))) { - /* Insertion after qp.*/ - H_NEXT(hp) = H_NEXT(qp); - H_NEXT(qp) = hp; - /* Verifies if the newly inserted block should be merged.*/ - if (H_LIMIT(hp) == H_NEXT(hp)) { - /* Merge with the next block.*/ - H_PAGES(hp) += H_PAGES(H_NEXT(hp)) + 1U; - H_NEXT(hp) = H_NEXT(H_NEXT(hp)); - } - if ((H_LIMIT(qp) == hp)) { - /* Merge with the previous block.*/ - H_PAGES(qp) += H_PAGES(hp) + 1U; - H_NEXT(qp) = H_NEXT(hp); - } - break; - } - qp = H_NEXT(qp); - } - - /* Releasing heap mutex/semaphore.*/ - H_UNLOCK(heapp); - - return; -} - -/** - * @brief Reports the heap status. - * @note This function is meant to be used in the test suite, it should - * not be really useful for the application code. - * - * @param[in] heapp pointer to a heap descriptor or @p NULL in order to - * access the default heap. - * @param[in] totalp pointer to a variable that will receive the total - * fragmented free space or @ NULL - * @param[in] largestp pointer to a variable that will receive the largest - * free free block found space or @ NULL - * @return The number of fragments in the heap. - * - * @api - */ -size_t chHeapStatus(memory_heap_t *heapp, size_t *totalp, size_t *largestp) { - heap_header_t *qp; - size_t n, tpages, lpages; - - if (heapp == NULL) { - heapp = &default_heap; - } - - H_LOCK(heapp); - tpages = 0U; - lpages = 0U; - n = 0U; - qp = &heapp->header; - while (H_NEXT(qp) != NULL) { - size_t pages = H_PAGES(H_NEXT(qp)); - - /* Updating counters.*/ - n++; - tpages += pages; - if (pages > lpages) { - lpages = pages; - } - - qp = H_NEXT(qp); - } - - /* Writing out fragmented free memory.*/ - if (totalp != NULL) { - *totalp = tpages * CH_HEAP_ALIGNMENT; - } - - /* Writing out unfragmented free memory.*/ - if (largestp != NULL) { - *largestp = lpages * CH_HEAP_ALIGNMENT; - } - H_UNLOCK(heapp); - - return n; -} - -#endif /* CH_CFG_USE_HEAP == TRUE */ - -/** @} */ diff --git a/os/lib/src/chmemheaps.c b/os/lib/src/chmemheaps.c new file mode 100644 index 000000000..ebbd46bad --- /dev/null +++ b/os/lib/src/chmemheaps.c @@ -0,0 +1,399 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chmemheaps.c + * @brief Memory heaps code. + * + * @addtogroup memheaps + * @details Heap Allocator related APIs. + *

Operation mode

+ * The heap allocator implements a first-fit strategy and its APIs + * are functionally equivalent to the usual @p malloc() and @p free() + * library functions. The main difference is that the OS heap APIs + * are guaranteed to be thread safe and there is the ability to + * return memory blocks aligned to arbitrary powers of two.
+ * @pre In order to use the heap APIs the @p CH_CFG_USE_HEAP option must + * be enabled in @p chconf.h. + * @note Compatible with RT and NIL. + * @{ + */ + +#include "ch.h" + +#if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/* + * Defaults on the best synchronization mechanism available. + */ +#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) +#define H_LOCK(h) chMtxLock(&(h)->mtx) +#define H_UNLOCK(h) chMtxUnlock(&(h)->mtx) +#else +#define H_LOCK(h) (void) chSemWait(&(h)->sem) +#define H_UNLOCK(h) chSemSignal(&(h)->sem) +#endif + +#define H_BLOCK(hp) ((hp) + 1U) + +#define H_LIMIT(hp) (H_BLOCK(hp) + H_PAGES(hp)) + +#define H_NEXT(hp) ((hp)->free.next) + +#define H_PAGES(hp) ((hp)->free.pages) + +#define H_HEAP(hp) ((hp)->used.heap) + +#define H_SIZE(hp) ((hp)->used.size) + +/* + * Number of pages between two pointers in a MISRA-compatible way. + */ +#define NPAGES(p1, p2) \ + /*lint -save -e9033 [10.8] The cast is safe.*/ \ + ((size_t)((p1) - (p2))) \ + /*lint -restore*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/** + * @brief Default heap descriptor. + */ +static memory_heap_t default_heap; + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the default heap. + * + * @notapi + */ +void _heap_init(void) { + + default_heap.provider = chCoreAllocAlignedWithOffset; + H_NEXT(&default_heap.header) = NULL; + H_PAGES(&default_heap.header) = 0; +#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) + chMtxObjectInit(&default_heap.mtx); +#else + chSemObjectInit(&default_heap.sem, (cnt_t)1); +#endif +} + +/** + * @brief Initializes a memory heap from a static memory area. + * @note The heap buffer base and size are adjusted if the passed buffer + * is not aligned to @p CH_HEAP_ALIGNMENT. This mean that the + * effective heap size can be less than @p size. + * + * @param[out] heapp pointer to the memory heap descriptor to be initialized + * @param[in] buf heap buffer base + * @param[in] size heap size + * + * @init + */ +void chHeapObjectInit(memory_heap_t *heapp, void *buf, size_t size) { + heap_header_t *hp = (heap_header_t *)MEM_ALIGN_NEXT(buf, CH_HEAP_ALIGNMENT); + + chDbgCheck((heapp != NULL) && (size > 0U)); + + /* Adjusting the size in case the initial block was not correctly + aligned.*/ + /*lint -save -e9033 [10.8] Required cast operations.*/ + size -= (size_t)((uint8_t *)hp - (uint8_t *)buf); + /*lint restore*/ + + /* Initializing the heap header.*/ + heapp->provider = NULL; + H_NEXT(&heapp->header) = hp; + H_PAGES(&heapp->header) = 0; + H_NEXT(hp) = NULL; + H_PAGES(hp) = (size - sizeof (heap_header_t)) / CH_HEAP_ALIGNMENT; +#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) + chMtxObjectInit(&heapp->mtx); +#else + chSemObjectInit(&heapp->sem, (cnt_t)1); +#endif +} + +/** + * @brief Allocates a block of memory from the heap by using the first-fit + * algorithm. + * @details The allocated block is guaranteed to be properly aligned to the + * specified alignment. + * + * @param[in] heapp pointer to a heap descriptor or @p NULL in order to + * access the default heap. + * @param[in] size the size of the block to be allocated. Note that the + * allocated block may be a bit bigger than the requested + * size for alignment and fragmentation reasons. + * @param[in] align desired memory alignment + * @return A pointer to the aligned allocated block. + * @retval NULL if the block cannot be allocated. + * + * @api + */ +void *chHeapAllocAligned(memory_heap_t *heapp, size_t size, unsigned align) { + heap_header_t *qp, *hp, *ahp; + size_t pages; + + chDbgCheck((size > 0U) && MEM_IS_VALID_ALIGNMENT(align)); + + /* If an heap is not specified then the default system header is used.*/ + if (heapp == NULL) { + heapp = &default_heap; + } + + /* Minimum alignment is constrained by the heap header structure size.*/ + if (align < CH_HEAP_ALIGNMENT) { + align = CH_HEAP_ALIGNMENT; + } + + /* Size is converted in number of elementary allocation units.*/ + pages = MEM_ALIGN_NEXT(size, CH_HEAP_ALIGNMENT) / CH_HEAP_ALIGNMENT; + + /* Taking heap mutex/semaphore.*/ + H_LOCK(heapp); + + /* Start of the free blocks list.*/ + qp = &heapp->header; + while (H_NEXT(qp) != NULL) { + + /* Next free block.*/ + hp = H_NEXT(qp); + + /* Pointer aligned to the requested alignment.*/ + ahp = (heap_header_t *)MEM_ALIGN_NEXT(H_BLOCK(hp), align) - 1U; + + if ((ahp < H_LIMIT(hp)) && (pages <= NPAGES(H_LIMIT(hp), ahp + 1U))) { + /* The block is large enough to contain a correctly aligned area + of sufficient size.*/ + + if (ahp > hp) { + /* The block is not properly aligned, must split it.*/ + size_t bpages; + + bpages = NPAGES(H_LIMIT(hp), H_BLOCK(ahp)); + H_PAGES(hp) = NPAGES(ahp, H_BLOCK(hp)); + if (bpages > pages) { + /* The block is bigger than required, must split the excess.*/ + heap_header_t *fp; + + /* Creating the excess block.*/ + fp = H_BLOCK(ahp) + pages; + H_PAGES(fp) = (bpages - pages) - 1U; + + /* Linking the excess block.*/ + H_NEXT(fp) = H_NEXT(hp); + H_NEXT(hp) = fp; + } + + hp = ahp; + } + else { + /* The block is already properly aligned.*/ + + if (H_PAGES(hp) == pages) { + /* Exact size, getting the whole block.*/ + H_NEXT(qp) = H_NEXT(hp); + } + else { + /* The block is bigger than required, must split the excess.*/ + heap_header_t *fp; + + fp = H_BLOCK(hp) + pages; + H_NEXT(fp) = H_NEXT(hp); + H_PAGES(fp) = NPAGES(H_LIMIT(hp), H_BLOCK(fp)); + H_NEXT(qp) = fp; + } + } + + /* Setting in the block owner heap and size.*/ + H_SIZE(hp) = size; + H_HEAP(hp) = heapp; + + /* Releasing heap mutex/semaphore.*/ + H_UNLOCK(heapp); + + /*lint -save -e9087 [11.3] Safe cast.*/ + return (void *)H_BLOCK(hp); + /*lint -restore*/ + } + + /* Next in the free blocks list.*/ + qp = hp; + } + + /* Releasing heap mutex/semaphore.*/ + H_UNLOCK(heapp); + + /* More memory is required, tries to get it from the associated provider + else fails.*/ + if (heapp->provider != NULL) { + ahp = heapp->provider((pages + 1U) * CH_HEAP_ALIGNMENT, + align, + sizeof (heap_header_t)); + if (ahp != NULL) { + hp = ahp - 1U; + H_HEAP(hp) = heapp; + H_SIZE(hp) = size; + + /*lint -save -e9087 [11.3] Safe cast.*/ + return (void *)ahp; + /*lint -restore*/ + } + } + + return NULL; +} + +/** + * @brief Frees a previously allocated memory block. + * + * @param[in] p pointer to the memory block to be freed + * + * @api + */ +void chHeapFree(void *p) { + heap_header_t *qp, *hp; + memory_heap_t *heapp; + + chDbgCheck((p != NULL) && MEM_IS_ALIGNED(p, CH_HEAP_ALIGNMENT)); + + /*lint -save -e9087 [11.3] Safe cast.*/ + hp = (heap_header_t *)p - 1U; + /*lint -restore*/ + heapp = H_HEAP(hp); + qp = &heapp->header; + + /* Size is converted in number of elementary allocation units.*/ + H_PAGES(hp) = MEM_ALIGN_NEXT(H_SIZE(hp), + CH_HEAP_ALIGNMENT) / CH_HEAP_ALIGNMENT; + + /* Taking heap mutex/semaphore.*/ + H_LOCK(heapp); + + while (true) { + chDbgAssert((hp < qp) || (hp >= H_LIMIT(qp)), "within free block"); + + if (((qp == &heapp->header) || (hp > qp)) && + ((H_NEXT(qp) == NULL) || (hp < H_NEXT(qp)))) { + /* Insertion after qp.*/ + H_NEXT(hp) = H_NEXT(qp); + H_NEXT(qp) = hp; + /* Verifies if the newly inserted block should be merged.*/ + if (H_LIMIT(hp) == H_NEXT(hp)) { + /* Merge with the next block.*/ + H_PAGES(hp) += H_PAGES(H_NEXT(hp)) + 1U; + H_NEXT(hp) = H_NEXT(H_NEXT(hp)); + } + if ((H_LIMIT(qp) == hp)) { + /* Merge with the previous block.*/ + H_PAGES(qp) += H_PAGES(hp) + 1U; + H_NEXT(qp) = H_NEXT(hp); + } + break; + } + qp = H_NEXT(qp); + } + + /* Releasing heap mutex/semaphore.*/ + H_UNLOCK(heapp); + + return; +} + +/** + * @brief Reports the heap status. + * @note This function is meant to be used in the test suite, it should + * not be really useful for the application code. + * + * @param[in] heapp pointer to a heap descriptor or @p NULL in order to + * access the default heap. + * @param[in] totalp pointer to a variable that will receive the total + * fragmented free space or @ NULL + * @param[in] largestp pointer to a variable that will receive the largest + * free free block found space or @ NULL + * @return The number of fragments in the heap. + * + * @api + */ +size_t chHeapStatus(memory_heap_t *heapp, size_t *totalp, size_t *largestp) { + heap_header_t *qp; + size_t n, tpages, lpages; + + if (heapp == NULL) { + heapp = &default_heap; + } + + H_LOCK(heapp); + tpages = 0U; + lpages = 0U; + n = 0U; + qp = &heapp->header; + while (H_NEXT(qp) != NULL) { + size_t pages = H_PAGES(H_NEXT(qp)); + + /* Updating counters.*/ + n++; + tpages += pages; + if (pages > lpages) { + lpages = pages; + } + + qp = H_NEXT(qp); + } + + /* Writing out fragmented free memory.*/ + if (totalp != NULL) { + *totalp = tpages * CH_HEAP_ALIGNMENT; + } + + /* Writing out unfragmented free memory.*/ + if (largestp != NULL) { + *largestp = lpages * CH_HEAP_ALIGNMENT; + } + H_UNLOCK(heapp); + + return n; +} + +#endif /* CH_CFG_USE_HEAP == TRUE */ + +/** @} */ -- cgit v1.2.3