From a1480d01d1110f74f157d5caea0b5d619d859b91 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Fri, 18 Mar 2016 10:00:27 +0000 Subject: Added Guarded Memory Pools to RT and NIL. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9134 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/common/oslib/include/chmempools.h | 103 ++++++++++++++++++++++++-- os/common/oslib/src/chmempools.c | 139 ++++++++++++++++++++++++++++++++++- 2 files changed, 234 insertions(+), 8 deletions(-) (limited to 'os') diff --git a/os/common/oslib/include/chmempools.h b/os/common/oslib/include/chmempools.h index 2d582f48a..2dfe40e20 100644 --- a/os/common/oslib/include/chmempools.h +++ b/os/common/oslib/include/chmempools.h @@ -69,6 +69,17 @@ typedef struct { for this pool. */ } memory_pool_t; +#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__) +/** + * @brief Guarded memory pool descriptor. + */ +typedef struct { + semaphore_t sem; /**< @brief Counter semaphore quarding + the memory pool. */ + memory_pool_t pool; /**< @brief The memory pool itself. */ +} guarded_memory_pool_t; +#endif /* CH_CFG_USE_SEMAPHORES == TRUE */ + /*===========================================================================*/ /* Module macros. */ /*===========================================================================*/ @@ -86,18 +97,46 @@ typedef struct { {NULL, size, provider} /** - * @brief Static memory pool initializer in hungry mode. + * @brief Static memory pool initializer. * @details Statically initialized memory pools require no explicit * initialization using @p chPoolInit(). * - * @param[in] name the name of the memory pool variable - * @param[in] size size of the memory pool contained objects - * @param[in] provider memory provider function for the memory pool or @p NULL - * if the pool is not allowed to grow automatically + * @param[in] name the name of the memory pool variable + * @param[in] size size of the memory pool contained objects + * @param[in] provider memory provider function for the memory pool or @p NULL + * if the pool is not allowed to grow automatically */ #define MEMORYPOOL_DECL(name, size, provider) \ memory_pool_t name = _MEMORYPOOL_DATA(name, size, provider) +#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__) +/** + * @brief Data part of a static guarded memory pool initializer. + * @details This macro should be used when statically initializing a + * memory pool that is part of a bigger structure. + * + * @param[in] name the name of the memory pool variable + * @param[in] size size of the memory pool contained objects + */ +#define _GUARDEDMEMORYPOOL_DATA(name, size) { \ + _SEMAPHORE_DATA(name.sem, (cnt_t)0), \ + NULL, \ + size, \ + NULL \ +} + +/** + * @brief Static guarded memory pool initializer. + * @details Statically initialized guardedmemory pools require no explicit + * initialization using @p chGuardedPoolInit(). + * + * @param[in] name the name of the guarded memory pool variable + * @param[in] size size of the memory pool contained objects + */ +#define GUARDEDMEMORYPOOL_DECL(name, size) \ + memory_pool_t name = _MEMORYPOOL_DATA(name, size) +#endif /* CH_CFG_USE_SEMAPHORES == TRUE */ + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ @@ -111,6 +150,16 @@ extern "C" { void *chPoolAlloc(memory_pool_t *mp); void chPoolFreeI(memory_pool_t *mp, void *objp); void chPoolFree(memory_pool_t *mp, void *objp); +#if CH_CFG_USE_SEMAPHORES == TRUE + void chGuardedPoolObjectInit(guarded_memory_pool_t *gmp, size_t size); + void chGuardedPoolLoadArray(guarded_memory_pool_t *gmp, void *p, size_t n); + void *chGuardedPoolAllocTimeoutS(guarded_memory_pool_t *gmp, + systime_t timeout); + void *chGuardedPoolAllocTimeout(guarded_memory_pool_t *gmp, + systime_t timeout); + void chGuardedPoolFreeI(guarded_memory_pool_t *gmp, void *objp); + void chGuardedPoolFree(guarded_memory_pool_t *gmp, void *objp); +#endif #ifdef __cplusplus } #endif @@ -146,7 +195,7 @@ static inline void chPoolAdd(memory_pool_t *mp, void *objp) { * memory pool. * @pre The added object must be memory aligned to the size of * @p stkalign_t type. - * @note This function is just an alias for @p chPoolFree() and has been + * @note This function is just an alias for @p chPoolFreeI() and has been * added for clarity. * * @param[in] mp pointer to a @p memory_pool_t structure @@ -161,6 +210,48 @@ static inline void chPoolAddI(memory_pool_t *mp, void *objp) { chPoolFreeI(mp, objp); } +#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__) +/** + * @brief Adds an object to a guarded memory pool. + * @pre The guarded memory pool must be already been initialized. + * @pre The added object must be of the right size for the specified + * guarded memory pool. + * @pre The added object must be properly aligned. + * @note This function is just an alias for @p chGuardedPoolFree() and + * has been added for clarity. + * + * @param[in] gmp pointer to a @p guarded_memory_pool_t structure + * @param[in] objp the pointer to the object to be added + * + * @api + */ +static inline void chGuardedPoolAdd(guarded_memory_pool_t *gmp, void *objp) { + + chGuardedPoolFree(gmp, objp); +} + +/** + * @brief Adds an object to a guarded memory pool. + * @pre The guarded memory pool must be already been initialized. + * @pre The added object must be of the right size for the specified + * guarded memory pool. + * @pre The added object must be properly aligned. + * @note This function is just an alias for @p chGuardedPoolFreeI() and + * has been added for clarity. + * + * @param[in] gmp pointer to a @p guarded_memory_pool_t structure + * @param[in] objp the pointer to the object to be added + * + * @iclass + */ +static inline void chGuardedPoolAddI(guarded_memory_pool_t *gmp, void *objp) { + + chDbgCheckClassI(); + + chGuardedPoolFreeI(gmp, objp); +} +#endif /* CH_CFG_USE_SEMAPHORES == TRUE */ + #endif /* CH_CFG_USE_MEMPOOLS == TRUE */ #endif /* _CHMEMPOOLS_H_ */ diff --git a/os/common/oslib/src/chmempools.c b/os/common/oslib/src/chmempools.c index c29fde8f4..29ca2e0dc 100644 --- a/os/common/oslib/src/chmempools.c +++ b/os/common/oslib/src/chmempools.c @@ -162,7 +162,7 @@ void *chPoolAlloc(memory_pool_t *mp) { * @pre The memory pool must be already been initialized. * @pre The freed object must be of the right size for the specified * memory pool. - * @pre The object must be properly aligned to contain a pointer to void. + * @pre The added object must be properly aligned. * * @param[in] mp pointer to a @p memory_pool_t structure * @param[in] objp the pointer to the object to be released @@ -184,7 +184,7 @@ void chPoolFreeI(memory_pool_t *mp, void *objp) { * @pre The memory pool must be already been initialized. * @pre The freed object must be of the right size for the specified * memory pool. - * @pre The object must be properly aligned to contain a pointer to void. + * @pre The added object must be properly aligned. * * @param[in] mp pointer to a @p memory_pool_t structure * @param[in] objp the pointer to the object to be released @@ -198,6 +198,141 @@ void chPoolFree(memory_pool_t *mp, void *objp) { chSysUnlock(); } +#if CH_CFG_USE_SEMAPHORES == TRUE +/** + * @brief Initializes an empty guarded memory pool. + * + * @param[out] gmp pointer to a @p guarded_memory_pool_t structure + * @param[in] size the size of the objects contained in this guarded + * memory pool, the minimum accepted size is the size + * of a pointer to void. + * + * @init + */ +void chGuardedPoolObjectInit(guarded_memory_pool_t *gmp, size_t size) { + + chPoolObjectInit(&gmp->pool, size, NULL); + chSemObjectInit(&gmp->sem, (cnt_t)0); +} + +/** + * @brief Loads a guarded memory pool with an array of static objects. + * @pre The guarded memory pool must be already been initialized. + * @pre The array elements must be of the right size for the specified + * guarded memory pool. + * @post The guarded memory pool contains the elements of the input array. + * + * @param[in] gmp pointer to a @p guarded_memory_pool_t structure + * @param[in] p pointer to the array first element + * @param[in] n number of elements in the array + * + * @api + */ +void chGuardedPoolLoadArray(guarded_memory_pool_t *gmp, void *p, size_t n) { + + chDbgCheck((gmp != NULL) && (n != 0U)); + + while (n != 0U) { + chGuardedPoolAdd(gmp, p); + /*lint -save -e9087 [11.3] Safe cast.*/ + p = (void *)(((uint8_t *)p) + gmp->pool.object_size); + /*lint -restore*/ + n--; + } +} + +/** + * @brief Allocates an object from a guarded memory pool. + * @pre The guarded memory pool must be already been initialized. + * + * @param[in] gmp pointer to a @p guarded_memory_pool_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 the operation timed out. + * + * @sclass + */ +void *chGuardedPoolAllocTimeoutS(guarded_memory_pool_t *gmp, + systime_t timeout) { + msg_t msg; + + msg = chSemWaitTimeoutS(&gmp->sem, timeout); + if (msg != MSG_OK) { + return NULL; + } + + return chPoolAllocI(&gmp->pool); +} + +/** + * @brief Allocates an object from a guarded memory pool. + * @pre The guarded memory pool must be already been initialized. + * + * @param[in] gmp pointer to a @p guarded_memory_pool_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 the operation timed out. + * + * @api + */ +void *chGuardedPoolAllocTimeout(guarded_memory_pool_t *gmp, + systime_t timeout) { + void *p; + + chSysLock(); + p = chGuardedPoolAllocTimeoutS(gmp, timeout); + chSysUnlock(); + + return p; +} + +/** + * @brief Releases an object into a guarded memory pool. + * @pre The guarded memory pool must be already been initialized. + * @pre The freed object must be of the right size for the specified + * guarded memory pool. + * @pre The added object must be properly aligned. + * + * @param[in] gmp pointer to a @p guarded_memory_pool_t structure + * @param[in] objp the pointer to the object to be released + * + * @iclass + */ +void chGuardedPoolFreeI(guarded_memory_pool_t *gmp, void *objp) { + + chPoolFreeI(&gmp->pool, objp); + chSemSignalI(&gmp->sem); +} + +/** + * @brief Releases an object into a guarded memory pool. + * @pre The guarded memory pool must be already been initialized. + * @pre The freed object must be of the right size for the specified + * guarded memory pool. + * @pre The added object must be properly aligned. + * + * @param[in] gmp pointer to a @p guarded_memory_pool_t structure + * @param[in] objp the pointer to the object to be released + * + * @api + */ +void chGuardedPoolFree(guarded_memory_pool_t *gmp, void *objp) { + + chSysLock(); + chGuardedPoolFreeI(gmp, objp); + chSchRescheduleS(); + chSysUnlock(); +} +#endif + #endif /* CH_CFG_USE_MEMPOOLS == TRUE */ /** @} */ -- cgit v1.2.3