From 5397ae347acc6d302b68bbdc10ec2d9e70892513 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Sun, 20 Jan 2019 15:20:43 +0000 Subject: Renames for consistency. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12564 110e8d01-0319-4d1e-a829-52ad28d1bb01 --- doc/nil/Doxyfile_chm | 6 +- doc/nil/Doxyfile_html | 6 +- doc/rt/Doxyfile_chm | 6 +- doc/rt/Doxyfile_html | 6 +- os/lib/dox/lib.dox | 85 ----- os/lib/include/chbsem.h | 311 ---------------- os/lib/include/chfactory.h | 553 ---------------------------- os/lib/include/chlib.h | 217 ----------- os/lib/include/chmboxes.h | 209 ----------- os/lib/include/chmemcore.h | 198 ----------- os/lib/include/chmemheaps.h | 178 ---------- os/lib/include/chmempools.h | 371 ------------------- os/lib/include/chobjfifos.h | 430 ---------------------- os/lib/include/chpipes.h | 208 ----------- os/lib/lib.mk | 49 --- os/lib/readme.txt | 2 - os/lib/src/chfactory.c | 810 ------------------------------------------ os/lib/src/chmboxes.c | 522 --------------------------- os/lib/src/chmemcore.c | 175 --------- os/lib/src/chmemheaps.c | 399 --------------------- os/lib/src/chmempools.c | 336 ------------------ os/lib/src/chpipes.c | 388 -------------------- os/nil/nil.mk | 2 +- os/oslib/dox/lib.dox | 85 +++++ os/oslib/include/chbsem.h | 311 ++++++++++++++++ os/oslib/include/chfactory.h | 553 ++++++++++++++++++++++++++++ os/oslib/include/chlib.h | 217 +++++++++++ os/oslib/include/chmboxes.h | 209 +++++++++++ os/oslib/include/chmemcore.h | 198 +++++++++++ os/oslib/include/chmemheaps.h | 178 ++++++++++ os/oslib/include/chmempools.h | 371 +++++++++++++++++++ os/oslib/include/chobjfifos.h | 430 ++++++++++++++++++++++ os/oslib/include/chpipes.h | 208 +++++++++++ os/oslib/oslib.mk | 49 +++ os/oslib/readme.txt | 2 + os/oslib/src/chfactory.c | 810 ++++++++++++++++++++++++++++++++++++++++++ os/oslib/src/chmboxes.c | 522 +++++++++++++++++++++++++++ os/oslib/src/chmemcore.c | 175 +++++++++ os/oslib/src/chmemheaps.c | 399 +++++++++++++++++++++ os/oslib/src/chmempools.c | 336 ++++++++++++++++++ os/oslib/src/chpipes.c | 388 ++++++++++++++++++++ os/rt/rt.mk | 2 +- 42 files changed, 5455 insertions(+), 5455 deletions(-) delete mode 100644 os/lib/dox/lib.dox delete mode 100644 os/lib/include/chbsem.h delete mode 100644 os/lib/include/chfactory.h delete mode 100644 os/lib/include/chlib.h delete mode 100644 os/lib/include/chmboxes.h delete mode 100644 os/lib/include/chmemcore.h delete mode 100644 os/lib/include/chmemheaps.h delete mode 100644 os/lib/include/chmempools.h delete mode 100644 os/lib/include/chobjfifos.h delete mode 100644 os/lib/include/chpipes.h delete mode 100644 os/lib/lib.mk delete mode 100644 os/lib/readme.txt delete mode 100644 os/lib/src/chfactory.c delete mode 100644 os/lib/src/chmboxes.c delete mode 100644 os/lib/src/chmemcore.c delete mode 100644 os/lib/src/chmemheaps.c delete mode 100644 os/lib/src/chmempools.c delete mode 100644 os/lib/src/chpipes.c create mode 100644 os/oslib/dox/lib.dox create mode 100644 os/oslib/include/chbsem.h create mode 100644 os/oslib/include/chfactory.h create mode 100644 os/oslib/include/chlib.h create mode 100644 os/oslib/include/chmboxes.h create mode 100644 os/oslib/include/chmemcore.h create mode 100644 os/oslib/include/chmemheaps.h create mode 100644 os/oslib/include/chmempools.h create mode 100644 os/oslib/include/chobjfifos.h create mode 100644 os/oslib/include/chpipes.h create mode 100644 os/oslib/oslib.mk create mode 100644 os/oslib/readme.txt create mode 100644 os/oslib/src/chfactory.c create mode 100644 os/oslib/src/chmboxes.c create mode 100644 os/oslib/src/chmemcore.c create mode 100644 os/oslib/src/chmemheaps.c create mode 100644 os/oslib/src/chmempools.c create mode 100644 os/oslib/src/chpipes.c diff --git a/doc/nil/Doxyfile_chm b/doc/nil/Doxyfile_chm index 4375bea26..a0faca17d 100644 --- a/doc/nil/Doxyfile_chm +++ b/doc/nil/Doxyfile_chm @@ -791,9 +791,9 @@ INPUT = ./src \ ../../os/nil/src \ ../../os/nil/include \ ../../os/nil/templates \ - ../../os/lib/dox \ - ../../os/lib/src \ - ../../os/lib/include + ../../os/oslib/dox \ + ../../os/oslib/src \ + ../../os/oslib/include # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/doc/nil/Doxyfile_html b/doc/nil/Doxyfile_html index 4b7d0144a..c80e46339 100644 --- a/doc/nil/Doxyfile_html +++ b/doc/nil/Doxyfile_html @@ -791,9 +791,9 @@ INPUT = ./src \ ../../os/nil/src \ ../../os/nil/include \ ../../os/nil/templates \ - ../../os/lib/dox \ - ../../os/lib/src \ - ../../os/lib/include + ../../os/oslib/dox \ + ../../os/oslib/src \ + ../../os/oslib/include # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/doc/rt/Doxyfile_chm b/doc/rt/Doxyfile_chm index 413f3b19e..066a5a19a 100644 --- a/doc/rt/Doxyfile_chm +++ b/doc/rt/Doxyfile_chm @@ -792,9 +792,9 @@ INPUT = ./src \ ../../os/rt/src \ ../../os/rt/include \ ../../os/rt/templates \ - ../../os/lib/dox \ - ../../os/lib/src \ - ../../os/lib/include + ../../os/oslib/dox \ + ../../os/oslib/src \ + ../../os/oslib/include # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/doc/rt/Doxyfile_html b/doc/rt/Doxyfile_html index 409c03be0..d746085fb 100644 --- a/doc/rt/Doxyfile_html +++ b/doc/rt/Doxyfile_html @@ -792,9 +792,9 @@ INPUT = ./src \ ../../os/rt/src \ ../../os/rt/include \ ../../os/rt/templates \ - ../../os/lib/dox \ - ../../os/lib/src \ - ../../os/lib/include + ../../os/oslib/dox \ + ../../os/oslib/src \ + ../../os/oslib/include # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/os/lib/dox/lib.dox b/os/lib/dox/lib.dox deleted file mode 100644 index 4dfcdce58..000000000 --- a/os/lib/dox/lib.dox +++ /dev/null @@ -1,85 +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 . -*/ -/** - * @defgroup oslib OS Library - * @details The OS Library is a set of RTOS extensions compatible with both - * the RT and NIL RTOSes. - */ - -/** - * @defgroup oslib_info Version Numbers and Identification - * @ingroup oslib - */ - -/** - * @defgroup oslib_synchronization Synchronization - * @details Synchronization services. - * @ingroup oslib - */ - -/** - * @defgroup oslib_binary_semaphores Binary Semaphores - * @ingroup oslib_synchronization - */ - -/** - * @defgroup oslib_mailboxes Mailboxes - * @ingroup oslib_synchronization - */ - -/** - * @defgroup oslib_pipes Pipes - * @ingroup oslib_synchronization - */ - -/** - * @defgroup oslib_memory Memory Management - * @details Memory Management services. - * @ingroup oslib - */ - -/** - * @defgroup oslib_memcore Core Memory Manager - * @ingroup oslib_memory - */ - -/** - * @defgroup oslib_memheaps Memory Heaps - * @ingroup oslib_memory - */ - -/** - * @defgroup oslib_mempools Memory Pools - * @ingroup oslib_memory - */ - -/** - * @defgroup oslib_complex Complex Services - * @ingroup oslib - */ - -/** - * @defgroup oslib_objects_fifos Objects FIFOs - * @ingroup oslib_complex - */ - -/** - * @defgroup oslib_objects_factory Dynamic Objects Factory - * @ingroup oslib_complex - */ diff --git a/os/lib/include/chbsem.h b/os/lib/include/chbsem.h deleted file mode 100644 index 192aec86a..000000000 --- a/os/lib/include/chbsem.h +++ /dev/null @@ -1,311 +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 chbsem.h - * @brief Binary semaphores structures and macros. - * @details Binary semaphores related APIs and services. - *

Operation mode

- * Binary semaphores are implemented as a set of inline functions - * that use the existing counting semaphores primitives. The - * difference between counting and binary semaphores is that the - * counter of binary semaphores is not allowed to grow above the - * value 1. Repeated signal operation are ignored. A binary - * semaphore can thus have only two defined states: - * - Taken, when its counter has a value of zero or lower - * than zero. A negative number represent the number of threads - * queued on the binary semaphore. - * - Not taken, when its counter has a value of one. - * . - * Binary semaphores are different from mutexes because there is no - * concept of ownership, a binary semaphore can be taken by a - * thread and signaled by another thread or an interrupt handler, - * mutexes can only be taken and released by the same thread. Another - * difference is that binary semaphores, unlike mutexes, do not - * implement the priority inheritance protocol.
- * In order to use the binary semaphores APIs the - * @p CH_CFG_USE_SEMAPHORES option must be enabled in @p chconf.h. - * - * @addtogroup oslib_binary_semaphores - * @{ - */ - -#ifndef CHBSEM_H -#define CHBSEM_H - -#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/** - * @extends semaphore_t - * - * @brief Binary semaphore type. - */ -typedef struct ch_binary_semaphore { - semaphore_t sem; -} binary_semaphore_t; - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/** - * @brief Data part of a static semaphore initializer. - * @details This macro should be used when statically initializing a semaphore - * that is part of a bigger structure. - * - * @param[in] name the name of the semaphore variable - * @param[in] taken the semaphore initial state - */ -#define _BSEMAPHORE_DATA(name, taken) \ - {_SEMAPHORE_DATA(name.sem, ((taken) ? 0 : 1))} - -/** - * @brief Static semaphore initializer. - * @details Statically initialized semaphores require no explicit - * initialization using @p chBSemInit(). - * - * @param[in] name the name of the semaphore variable - * @param[in] taken the semaphore initial state - */ -#define BSEMAPHORE_DECL(name, taken) \ - binary_semaphore_t name = _BSEMAPHORE_DATA(name, taken) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes a binary semaphore. - * - * @param[out] bsp pointer to a @p binary_semaphore_t structure - * @param[in] taken initial state of the binary semaphore: - * - @a false, the initial state is not taken. - * - @a true, the initial state is taken. - * . - * - * @init - */ -static inline void chBSemObjectInit(binary_semaphore_t *bsp, bool taken) { - - chSemObjectInit(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1); -} - -/** - * @brief Wait operation on the binary semaphore. - * - * @param[in] bsp pointer to a @p binary_semaphore_t structure - * @return A message specifying how the invoking thread has been - * released from the semaphore. - * @retval MSG_OK if the binary semaphore has been successfully taken. - * @retval MSG_RESET if the binary semaphore has been reset using - * @p bsemReset(). - * - * @api - */ -static inline msg_t chBSemWait(binary_semaphore_t *bsp) { - - return chSemWait(&bsp->sem); -} - -/** - * @brief Wait operation on the binary semaphore. - * - * @param[in] bsp pointer to a @p binary_semaphore_t structure - * @return A message specifying how the invoking thread has been - * released from the semaphore. - * @retval MSG_OK if the binary semaphore has been successfully taken. - * @retval MSG_RESET if the binary semaphore has been reset using - * @p bsemReset(). - * - * @sclass - */ -static inline msg_t chBSemWaitS(binary_semaphore_t *bsp) { - - chDbgCheckClassS(); - - return chSemWaitS(&bsp->sem); -} - -/** - * @brief Wait operation on the binary semaphore. - * - * @param[in] bsp pointer to a @p binary_semaphore_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 A message specifying how the invoking thread has been - * released from the semaphore. - * @retval MSG_OK if the binary semaphore has been successfully taken. - * @retval MSG_RESET if the binary semaphore has been reset using - * @p bsemReset(). - * @retval MSG_TIMEOUT if the binary semaphore has not been signaled or reset - * within the specified timeout. - * - * @sclass - */ -static inline msg_t chBSemWaitTimeoutS(binary_semaphore_t *bsp, - sysinterval_t timeout) { - - chDbgCheckClassS(); - - return chSemWaitTimeoutS(&bsp->sem, timeout); -} - -/** - * @brief Wait operation on the binary semaphore. - * - * @param[in] bsp pointer to a @p binary_semaphore_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 A message specifying how the invoking thread has been - * released from the semaphore. - * @retval MSG_OK if the binary semaphore has been successfully taken. - * @retval MSG_RESET if the binary semaphore has been reset using - * @p bsemReset(). - * @retval MSG_TIMEOUT if the binary semaphore has not been signaled or reset - * within the specified timeout. - * - * @api - */ -static inline msg_t chBSemWaitTimeout(binary_semaphore_t *bsp, - sysinterval_t timeout) { - - return chSemWaitTimeout(&bsp->sem, timeout); -} - -/** - * @brief Reset operation on the binary semaphore. - * @note The released threads can recognize they were waked up by a reset - * rather than a signal because the @p bsemWait() will return - * @p MSG_RESET instead of @p MSG_OK. - * @note This function does not reschedule. - * - * @param[in] bsp pointer to a @p binary_semaphore_t structure - * @param[in] taken new state of the binary semaphore - * - @a false, the new state is not taken. - * - @a true, the new state is taken. - * . - * - * @iclass - */ -static inline void chBSemResetI(binary_semaphore_t *bsp, bool taken) { - - chDbgCheckClassI(); - - chSemResetI(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1); -} - -/** - * @brief Reset operation on the binary semaphore. - * @note The released threads can recognize they were waked up by a reset - * rather than a signal because the @p bsemWait() will return - * @p MSG_RESET instead of @p MSG_OK. - * - * @param[in] bsp pointer to a @p binary_semaphore_t structure - * @param[in] taken new state of the binary semaphore - * - @a false, the new state is not taken. - * - @a true, the new state is taken. - * . - * - * @api - */ -static inline void chBSemReset(binary_semaphore_t *bsp, bool taken) { - - chSemReset(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1); -} - -/** - * @brief Performs a signal operation on a binary semaphore. - * @note This function does not reschedule. - * - * @param[in] bsp pointer to a @p binary_semaphore_t structure - * - * @iclass - */ -static inline void chBSemSignalI(binary_semaphore_t *bsp) { - - chDbgCheckClassI(); - - if (bsp->sem.cnt < (cnt_t)1) { - chSemSignalI(&bsp->sem); - } -} - -/** - * @brief Performs a signal operation on a binary semaphore. - * - * @param[in] bsp pointer to a @p binary_semaphore_t structure - * - * @api - */ -static inline void chBSemSignal(binary_semaphore_t *bsp) { - - chSysLock(); - chBSemSignalI(bsp); - chSchRescheduleS(); - chSysUnlock(); -} - -/** - * @brief Returns the binary semaphore current state. - * - * @param[in] bsp pointer to a @p binary_semaphore_t structure - * @return The binary semaphore current state. - * @retval false if the binary semaphore is not taken. - * @retval true if the binary semaphore is taken. - * - * @iclass - */ -static inline bool chBSemGetStateI(const binary_semaphore_t *bsp) { - - chDbgCheckClassI(); - - return (bsp->sem.cnt > (cnt_t)0) ? false : true; -} - -#endif /* CH_CFG_USE_SEMAPHORES == TRUE */ - -#endif /* CHBSEM_H */ - -/** @} */ diff --git a/os/lib/include/chfactory.h b/os/lib/include/chfactory.h deleted file mode 100644 index aaaa5d2c2..000000000 --- a/os/lib/include/chfactory.h +++ /dev/null @@ -1,553 +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 chfactory.h - * @brief ChibiOS objects factory structures and macros. - * - * @addtogroup oslib_objects_factory - * @{ - */ - -#ifndef CHFACTORY_H -#define CHFACTORY_H - -#if (CH_CFG_USE_FACTORY == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief Maximum length for object names. - * @details If the specified length is zero then the name is stored by - * pointer but this could have unintended side effects. - */ -#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) || defined(__DOXYGEN__) -#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 -#endif - -/** - * @brief Enables the registry of generic objects. - */ -#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) || defined(__DOXYGEN__) -#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE -#endif - -/** - * @brief Enables factory for generic buffers. - */ -#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) || defined(__DOXYGEN__) -#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE -#endif - -/** - * @brief Enables factory for semaphores. - */ -#if !defined(CH_CFG_FACTORY_SEMAPHORES) || defined(__DOXYGEN__) -#define CH_CFG_FACTORY_SEMAPHORES TRUE -#endif - -/** - * @brief Enables factory for mailboxes. - */ -#if !defined(CH_CFG_FACTORY_MAILBOXES) || defined(__DOXYGEN__) -#define CH_CFG_FACTORY_MAILBOXES TRUE -#endif - -/** - * @brief Enables factory for objects FIFOs. - */ -#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) || defined(__DOXYGEN__) -#define CH_CFG_FACTORY_OBJ_FIFOS TRUE -#endif - -/** - * @brief Enables factory for objects FIFOs. - */ -#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) || defined(__DOXYGEN__) -#define CH_CFG_FACTORY_OBJ_FIFOS TRUE -#endif - -/** - * @brief Enables factory for Pipes. - */ -#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) -#define CH_CFG_FACTORY_PIPES TRUE -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) && (CH_CFG_USE_SEMAPHORES == FALSE) -/*lint -save -e767 [20.5] Valid because the #undef.*/ -#undef CH_CFG_FACTORY_SEMAPHORES -#define CH_CFG_FACTORY_SEMAPHORES FALSE -/*lint restore*/ -#endif - -#if (CH_CFG_FACTORY_MAILBOXES == TRUE) && (CH_CFG_USE_MAILBOXES == FALSE) -/*lint -save -e767 [20.5] Valid because the #undef.*/ -#undef CH_CFG_FACTORY_MAILBOXES -#define CH_CFG_FACTORY_MAILBOXES FALSE -/*lint restore*/ -#endif - -#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) && (CH_CFG_USE_OBJ_FIFOS == FALSE) -/*lint -save -e767 [20.5] Valid because the #undef.*/ -#undef CH_CFG_FACTORY_OBJ_FIFOS -#define CH_CFG_FACTORY_OBJ_FIFOS FALSE -/*lint restore*/ -#endif - -#if (CH_CFG_FACTORY_PIPES == TRUE) && (CH_CFG_USE_PIPES == FALSE) -/*lint -save -e767 [20.5] Valid because the #undef.*/ -#undef CH_CFG_FACTORY_PIPES -#define CH_CFG_FACTORY_PIPES FALSE -/*lint restore*/ -#endif - -#define CH_FACTORY_REQUIRES_POOLS \ - ((CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || \ - (CH_CFG_FACTORY_SEMAPHORES == TRUE)) - -#define CH_FACTORY_REQUIRES_HEAP \ - ((CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || \ - (CH_CFG_FACTORY_MAILBOXES == TRUE) || \ - (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || \ - (CH_CFG_FACTORY_PIPES == TRUE)) - -#if (CH_CFG_FACTORY_MAX_NAMES_LENGTH < 0) || \ - (CH_CFG_FACTORY_MAX_NAMES_LENGTH > 32) -#error "invalid CH_CFG_FACTORY_MAX_NAMES_LENGTH value" -#endif - -#if (CH_CFG_USE_MUTEXES == FALSE) && (CH_CFG_USE_SEMAPHORES == FALSE) -#error "CH_CFG_USE_FACTORY requires CH_CFG_USE_MUTEXES and/or CH_CFG_USE_SEMAPHORES" -#endif - -#if CH_CFG_USE_MEMCORE == FALSE -#error "CH_CFG_USE_FACTORY requires CH_CFG_USE_MEMCORE" -#endif - -#if CH_FACTORY_REQUIRES_POOLS && (CH_CFG_USE_MEMPOOLS == FALSE) -#error "CH_CFG_USE_MEMPOOLS is required" -#endif - -#if CH_FACTORY_REQUIRES_HEAP && (CH_CFG_USE_HEAP == FALSE) -#error "CH_CFG_USE_HEAP is required" -#endif - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of a dynamic object list element. - */ -typedef struct ch_dyn_element { - /** - * @brief Next dynamic object in the list. - */ - struct ch_dyn_element *next; - /** - * @brief Number of references to this object. - */ - ucnt_t refs; -#if (CH_CFG_FACTORY_MAX_NAMES_LENGTH > 0) || defined(__DOXYGEN__) - char name[CH_CFG_FACTORY_MAX_NAMES_LENGTH]; -#else - const char *name; -#endif -} dyn_element_t; - -/** - * @brief Type of a dynamic object list. - */ -typedef struct ch_dyn_list { - dyn_element_t *next; -} dyn_list_t; - -#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__) -/** - * @brief Type of a registered object. - */ -typedef struct ch_registered_static_object { - /** - * @brief List element of the registered object. - */ - dyn_element_t element; - /** - * @brief Pointer to the object. - * @note The type of the object is not stored in anyway. - */ - void *objp; -} registered_object_t; -#endif - -#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__) -/** - * @brief Type of a dynamic buffer object. - */ -typedef struct ch_dyn_object { - /** - * @brief List element of the dynamic buffer object. - */ - dyn_element_t element; - /*lint -save -e9038 [18.7] Required by design.*/ - /** - * @brief The buffer. - * @note This requires C99. - */ - uint8_t buffer[]; - /*lint restore*/ -} dyn_buffer_t; -#endif - -#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__) -/** - * @brief Type of a dynamic semaphore. - */ -typedef struct ch_dyn_semaphore { - /** - * @brief List element of the dynamic semaphore. - */ - dyn_element_t element; - /** - * @brief The semaphore. - */ - semaphore_t sem; -} dyn_semaphore_t; -#endif - -#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__) -/** - * @brief Type of a dynamic buffer object. - */ -typedef struct ch_dyn_mailbox { - /** - * @brief List element of the dynamic buffer object. - */ - dyn_element_t element; - /** - * @brief The mailbox. - */ - mailbox_t mbx; - /*lint -save -e9038 [18.7] Required by design.*/ - /** - * @brief Messages buffer. - * @note This requires C99. - */ - msg_t msgbuf[]; - /*lint restore*/ -} dyn_mailbox_t; -#endif - -#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) -/** - * @brief Type of a dynamic buffer object. - */ -typedef struct ch_dyn_objects_fifo { - /** - * @brief List element of the dynamic buffer object. - */ - dyn_element_t element; - /** - * @brief The objects FIFO. - */ - objects_fifo_t fifo; - /*lint -save -e9038 [18.7] Required by design.*/ - /** - * @brief Messages buffer. - * @note This open array is followed by another area containing the - * objects, this area is not represented in this structure. - * @note This requires C99. - */ - msg_t msgbuf[]; - /*lint restore*/ -} dyn_objects_fifo_t; -#endif - -#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__) -/** - * @brief Type of a dynamic pipe object. - */ -typedef struct ch_dyn_pipe { - /** - * @brief List element of the dynamic pipe object. - */ - dyn_element_t element; - /** - * @brief The pipe. - */ - pipe_t pipe; - /*lint -save -e9038 [18.7] Required by design.*/ - /** - * @brief Messages buffer. - * @note This requires C99. - */ - uint8_t buffer[]; - /*lint restore*/ -} dyn_pipe_t; -#endif - -/** - * @brief Type of the factory main object. - */ -typedef struct ch_objects_factory { - /** - * @brief Factory access mutex or semaphore. - */ -#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) - mutex_t mtx; -#else - semaphore_t sem; -#endif - /** - * @brief List of the registered objects. - */ - dyn_list_t obj_list; - /** - * @brief Pool of the available registered objects. - */ - memory_pool_t obj_pool; -#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__) - /** - * @brief List of the allocated buffer objects. - */ - dyn_list_t buf_list; -#endif /* CH_CFG_FACTORY_GENERIC_BUFFERS = TRUE */ -#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__) - /** - * @brief List of the allocated semaphores. - */ - dyn_list_t sem_list; - /** - * @brief Pool of the available semaphores. - */ - memory_pool_t sem_pool; -#endif /* CH_CFG_FACTORY_SEMAPHORES = TRUE */ -#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__) - /** - * @brief List of the allocated buffer objects. - */ - dyn_list_t mbx_list; -#endif /* CH_CFG_FACTORY_MAILBOXES = TRUE */ -#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) - /** - * @brief List of the allocated "objects FIFO" objects. - */ - dyn_list_t fifo_list; -#endif /* CH_CFG_FACTORY_OBJ_FIFOS = TRUE */ -#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__) - /** - * @brief List of the allocated pipe objects. - */ - dyn_list_t pipe_list; -#endif /* CH_CFG_FACTORY_PIPES = TRUE */ -} objects_factory_t; - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern objects_factory_t ch_factory; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void _factory_init(void); -#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__) - registered_object_t *chFactoryRegisterObject(const char *name, - void *objp); - registered_object_t *chFactoryFindObject(const char *name); - registered_object_t *chFactoryFindObjectByPointer(void *objp); - void chFactoryReleaseObject(registered_object_t *rop); -#endif -#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__) - dyn_buffer_t *chFactoryCreateBuffer(const char *name, size_t size); - dyn_buffer_t *chFactoryFindBuffer(const char *name); - void chFactoryReleaseBuffer(dyn_buffer_t *dbp); -#endif -#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__) - dyn_semaphore_t *chFactoryCreateSemaphore(const char *name, cnt_t n); - dyn_semaphore_t *chFactoryFindSemaphore(const char *name); - void chFactoryReleaseSemaphore(dyn_semaphore_t *dsp); -#endif -#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__) - dyn_mailbox_t *chFactoryCreateMailbox(const char *name, size_t n); - dyn_mailbox_t *chFactoryFindMailbox(const char *name); - void chFactoryReleaseMailbox(dyn_mailbox_t *dmp); -#endif -#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) - dyn_objects_fifo_t *chFactoryCreateObjectsFIFO(const char *name, - size_t objsize, - size_t objn, - unsigned objalign); - dyn_objects_fifo_t *chFactoryFindObjectsFIFO(const char *name); - void chFactoryReleaseObjectsFIFO(dyn_objects_fifo_t *dofp); -#endif -#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__) - dyn_pipe_t *chFactoryCreatePipe(const char *name, size_t size); - dyn_pipe_t *chFactoryFindPipe(const char *name); - void chFactoryReleasePipe(dyn_pipe_t *dpp); -#endif -#ifdef __cplusplus -} -#endif - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/** - * @brief Duplicates an object reference. - * @note This function can be used on any kind of dynamic object. - * - * @param[in] dep pointer to the element field of the object - * @return The duplicated object reference. - * - * @api - */ -static inline dyn_element_t *chFactoryDuplicateReference(dyn_element_t *dep) { - - dep->refs++; - - return dep; -} - -#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__) -/** - * @brief Returns the pointer to the inner registered object. - * - * @param[in] rop registered object reference - * @return The pointer to the registered object. - * - * @api - */ -static inline void *chFactoryGetObject(registered_object_t *rop) { - - return rop->objp; -} -#endif /* CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE */ - -#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__) -/** - * @brief Returns the size of a generic dynamic buffer object. - * - * @param[in] dbp dynamic buffer object reference - * @return The size of the buffer object in bytes. - * - * @api - */ -static inline size_t chFactoryGetBufferSize(dyn_buffer_t *dbp) { - - return chHeapGetSize(dbp) - sizeof (dyn_element_t); -} - -/** - * @brief Returns the pointer to the inner buffer. - * - * @param[in] dbp dynamic buffer object reference - * @return The pointer to the dynamic buffer. - * - * @api - */ -static inline uint8_t *chFactoryGetBuffer(dyn_buffer_t *dbp) { - - return dbp->buffer; -} -#endif /* CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE */ - -#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__) -/** - * @brief Returns the pointer to the inner semaphore. - * - * @param[in] dsp dynamic semaphore object reference - * @return The pointer to the semaphore. - * - * @api - */ -static inline semaphore_t *chFactoryGetSemaphore(dyn_semaphore_t *dsp) { - - return &dsp->sem; -} -#endif /* CH_CFG_FACTORY_SEMAPHORES == TRUE */ - -#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__) -/** - * @brief Returns the pointer to the inner mailbox. - * - * @param[in] dmp dynamic mailbox object reference - * @return The pointer to the mailbox. - * - * @api - */ -static inline mailbox_t *chFactoryGetMailbox(dyn_mailbox_t *dmp) { - - return &dmp->mbx; -} -#endif /* CH_CFG_FACTORY_MAILBOXES == TRUE */ - -#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) -/** - * @brief Returns the pointer to the inner objects FIFO. - * - * @param[in] dofp dynamic "objects FIFO" object reference - * @return The pointer to the objects FIFO. - * - * @api - */ -static inline objects_fifo_t *chFactoryGetObjectsFIFO(dyn_objects_fifo_t *dofp) { - - return &dofp->fifo; -} -#endif /* CH_CFG_FACTORY_OBJ_FIFOS == TRUE */ - -#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__) -/** - * @brief Returns the pointer to the inner pipe. - * - * @param[in] dpp dynamic pipe object reference - * @return The pointer to the pipe. - * - * @api - */ -static inline pipe_t *chFactoryGetPipe(dyn_pipe_t *dpp) { - - return &dpp->pipe; -} -#endif /* CH_CFG_FACTORY_PIPES == TRUE */ - -#endif /* CH_CFG_USE_FACTORY == TRUE */ - -#endif /* CHFACTORY_H */ - -/** @} */ diff --git a/os/lib/include/chlib.h b/os/lib/include/chlib.h deleted file mode 100644 index 495d03643..000000000 --- a/os/lib/include/chlib.h +++ /dev/null @@ -1,217 +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 chlib.h - * @brief ChibiOS/LIB main include file. - * @details This header includes all the required library headers. This file - * is meant do be included by @p ch.h not directly by user. - * - * @addtogroup oslib_info - * @details OS Library related info. - * @{ - */ - -#ifndef CHLIB_H -#define CHLIB_H - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/** - * @brief ChibiOS/LIB identification macro. - */ -#define _CHIBIOS_OSLIB_ - -/** - * @brief Stable release flag. - */ -#define CH_OSLIB_STABLE 0 - -/** - * @name ChibiOS/LIB version identification - * @{ - */ -/** - * @brief OS Library version string. - */ -#define CH_OSLIB_VERSION "1.0.0" - -/** - * @brief Kernel version major number. - */ -#define CH_OSLIB_MAJOR 1 - -/** - * @brief Kernel version minor number. - */ -#define CH_OSLIB_MINOR 0 - -/** - * @brief Kernel version patch number. - */ -#define CH_OSLIB_PATCH 0 -/** @} */ - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/* Host OS checks.*/ -#if !defined(_CHIBIOS_RT_) && !defined(_CHIBIOS_NIL_) -#error "OS check failed, must be included after ch.h" -#endif - -/* Configuration file checks.*/ -#if !defined(CH_CFG_USE_MAILBOXES) -#error "CH_CFG_USE_MAILBOXES not defined in chconf.h" -#endif - -#if !defined(CH_CFG_USE_MEMCORE) -#error "CH_CFG_USE_MEMCORE not defined in chconf.h" -#endif - -#if !defined(CH_CFG_USE_HEAP) -#error "CH_CFG_USE_HEAP not defined in chconf.h" -#endif - -#if !defined(CH_CFG_USE_MEMPOOLS) -#error "CH_CFG_USE_MEMPOOLS not defined in chconf.h" -#endif - -#if !defined(CH_CFG_USE_OBJ_FIFOS) -#error "CH_CFG_USE_OBJ_FIFOS not defined in chconf.h" -#endif - -#if !defined(CH_CFG_USE_PIPES) -#error "CH_CFG_USE_PIPES not defined in chconf.h" -#endif - -/* Objects factory options checks.*/ -#if !defined(CH_CFG_USE_FACTORY) -#error "CH_CFG_USE_FACTORY not defined in chconf.h" -#endif - -#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) -#error "CH_CFG_FACTORY_MAX_NAMES_LENGTH not defined in chconf.h" -#endif - -#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) -#error "CH_CFG_FACTORY_OBJECTS_REGISTRY not defined in chconf.h" -#endif - -#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) -#error "CH_CFG_FACTORY_GENERIC_BUFFERS not defined in chconf.h" -#endif - -#if !defined(CH_CFG_FACTORY_SEMAPHORES) -#error "CH_CFG_FACTORY_SEMAPHORES not defined in chconf.h" -#endif - -#if !defined(CH_CFG_FACTORY_MAILBOXES) -#error "CH_CFG_FACTORY_MAILBOXES not defined in chconf.h" -#endif - -#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) -#error "CH_CFG_FACTORY_OBJ_FIFOS not defined in chconf.h" -#endif - -/* License checks.*/ -#if !defined(CH_CUSTOMER_LIC_OSLIB) || !defined(CH_LICENSE_FEATURES) -#error "malformed chlicense.h" -#endif - -#if CH_CUSTOMER_LIC_OSLIB== FALSE -#error "ChibiOS/LIB not licensed" -#endif - -#if (CH_LICENSE_FEATURES != CH_FEATURES_FULL) && \ - (CH_LICENSE_FEATURES != CH_FEATURES_INTERMEDIATE) && \ - (CH_LICENSE_FEATURES != CH_FEATURES_BASIC) -#error "invalid CH_LICENSE_FEATURES setting" -#endif - -/* Restrictions in basic and intermediate modes.*/ -#if (CH_CUSTOMER_LIC_OSLIB == FALSE) || \ - (CH_LICENSE_FEATURES == CH_FEATURES_INTERMEDIATE) || \ - (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) - -/* Restricted subsystems.*/ -#undef CH_CFG_USE_FACTORY - -#define CH_CFG_USE_FACTORY FALSE - -#endif /* (CH_CUSTOMER_LIC_OSLIB == FALSE) || - (CH_LICENSE_FEATURES == CH_FEATURES_INTERMEDIATE) || - (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) */ - -/* Restrictions in basic mode.*/ -#if (CH_CUSTOMER_LIC_OSLIB == FALSE) || \ - (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) - -/* Restricted subsystems.*/ -#undef CH_CFG_USE_MEMCORE -#undef CH_CFG_USE_HEAP -#undef CH_CFG_USE_MEMPOOLS -#undef CH_CFG_USE_OBJ_FIFOS -#undef CH_CFG_USE_PIPES - -#define CH_CFG_USE_MEMCORE FALSE -#define CH_CFG_USE_HEAP FALSE -#define CH_CFG_USE_MEMPOOLS FALSE -#define CH_CFG_USE_OBJ_FIFOS FALSE -#define CH_CFG_USE_PIPES FALSE - -#endif /* (CH_CUSTOMER_LIC_OSLIB == FALSE) || - (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) */ - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Late inclusions. */ -/*===========================================================================*/ - -/* OS Library headers.*/ -#include "chbsem.h" -#include "chmboxes.h" -#include "chmemcore.h" -#include "chmemheaps.h" -#include "chmempools.h" -#include "chobjfifos.h" -#include "chpipes.h" -#include "chfactory.h" - -#endif /* CHLIB_H */ - -/** @} */ diff --git a/os/lib/include/chmboxes.h b/os/lib/include/chmboxes.h deleted file mode 100644 index fd76b995a..000000000 --- a/os/lib/include/chmboxes.h +++ /dev/null @@ -1,209 +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 chmboxes.h - * @brief Mailboxes macros and structures. - * - * @addtogroup oslib_mailboxes - * @{ - */ - -#ifndef CHMBOXES_H -#define CHMBOXES_H - -#if (CH_CFG_USE_MAILBOXES == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Structure representing a mailbox object. - */ -typedef struct { - msg_t *buffer; /**< @brief Pointer to the mailbox - buffer. */ - msg_t *top; /**< @brief Pointer to the location - after the buffer. */ - msg_t *wrptr; /**< @brief Write pointer. */ - msg_t *rdptr; /**< @brief Read pointer. */ - size_t cnt; /**< @brief Messages in queue. */ - bool reset; /**< @brief True in reset state. */ - threads_queue_t qw; /**< @brief Queued writers. */ - threads_queue_t qr; /**< @brief Queued readers. */ -} mailbox_t; - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/** - * @brief Data part of a static mailbox initializer. - * @details This macro should be used when statically initializing a - * mailbox that is part of a bigger structure. - * - * @param[in] name the name of the mailbox variable - * @param[in] buffer pointer to the mailbox buffer array of @p msg_t - * @param[in] size number of @p msg_t elements in the buffer array - */ -#define _MAILBOX_DATA(name, buffer, size) { \ - (msg_t *)(buffer), \ - (msg_t *)(buffer) + size, \ - (msg_t *)(buffer), \ - (msg_t *)(buffer), \ - (size_t)0, \ - false, \ - _THREADS_QUEUE_DATA(name.qw), \ - _THREADS_QUEUE_DATA(name.qr), \ -} - -/** - * @brief Static mailbox initializer. - * @details Statically initialized mailboxes require no explicit - * initialization using @p chMBObjectInit(). - * - * @param[in] name the name of the mailbox variable - * @param[in] buffer pointer to the mailbox buffer array of @p msg_t - * @param[in] size number of @p msg_t elements in the buffer array - */ -#define MAILBOX_DECL(name, buffer, size) \ - mailbox_t name = _MAILBOX_DATA(name, buffer, size) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void chMBObjectInit(mailbox_t *mbp, msg_t *buf, size_t n); - void chMBReset(mailbox_t *mbp); - void chMBResetI(mailbox_t *mbp); - msg_t chMBPostTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout); - msg_t chMBPostTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout); - msg_t chMBPostI(mailbox_t *mbp, msg_t msg); - msg_t chMBPostAheadTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout); - msg_t chMBPostAheadTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout); - msg_t chMBPostAheadI(mailbox_t *mbp, msg_t msg); - msg_t chMBFetchTimeout(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout); - msg_t chMBFetchTimeoutS(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout); - msg_t chMBFetchI(mailbox_t *mbp, msg_t *msgp); -#ifdef __cplusplus -} -#endif - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/** - * @brief Returns the mailbox buffer size as number of messages. - * - * @param[in] mbp the pointer to an initialized @p mailbox_t object - * @return The size of the mailbox. - * - * @iclass - */ -static inline size_t chMBGetSizeI(const mailbox_t *mbp) { - - /*lint -save -e9033 [10.8] Perfectly safe pointers - arithmetic.*/ - return (size_t)(mbp->top - mbp->buffer); - /*lint -restore*/ -} - -/** - * @brief Returns the number of used message slots into a mailbox. - * - * @param[in] mbp the pointer to an initialized @p mailbox_t object - * @return The number of queued messages. - * - * @iclass - */ -static inline size_t chMBGetUsedCountI(const mailbox_t *mbp) { - - chDbgCheckClassI(); - - return mbp->cnt; -} - -/** - * @brief Returns the number of free message slots into a mailbox. - * - * @param[in] mbp the pointer to an initialized @p mailbox_t object - * @return The number of empty message slots. - * - * @iclass - */ -static inline size_t chMBGetFreeCountI(const mailbox_t *mbp) { - - chDbgCheckClassI(); - - return chMBGetSizeI(mbp) - chMBGetUsedCountI(mbp); -} - -/** - * @brief Returns the next message in the queue without removing it. - * @pre A message must be waiting in the queue for this function to work - * or it would return garbage. The correct way to use this macro is - * to use @p chMBGetUsedCountI() and then use this macro, all within - * a lock state. - * - * @param[in] mbp the pointer to an initialized @p mailbox_t object - * @return The next message in queue. - * - * @iclass - */ -static inline msg_t chMBPeekI(const mailbox_t *mbp) { - - chDbgCheckClassI(); - - return *mbp->rdptr; -} - -/** - * @brief Terminates the reset state. - * - * @param[in] mbp the pointer to an initialized @p mailbox_t object - * - * @xclass - */ -static inline void chMBResumeX(mailbox_t *mbp) { - - mbp->reset = false; -} - -#endif /* CH_CFG_USE_MAILBOXES == TRUE */ - -#endif /* CHMBOXES_H */ - -/** @} */ diff --git a/os/lib/include/chmemcore.h b/os/lib/include/chmemcore.h deleted file mode 100644 index b9b728389..000000000 --- a/os/lib/include/chmemcore.h +++ /dev/null @@ -1,198 +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 chmemcore.h - * @brief Core memory manager macros and structures. - * - * @addtogroup oslib_memcore - * @{ - */ - -#ifndef CHMEMCORE_H -#define CHMEMCORE_H - -#if (CH_CFG_USE_MEMCORE == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief Managed RAM size. - * @details Size of the RAM area to be managed by the OS. If set to zero - * then the whole available RAM is used. The core memory is made - * available to the heap allocator and/or can be used directly through - * the simplified core memory allocator. - * - * @note In order to let the OS manage the whole RAM the linker script must - * provide the @p __heap_base__ and @p __heap_end__ symbols. - * @note Requires @p CH_CFG_USE_MEMCORE. - */ -#if !defined(CH_CFG_MEMCORE_SIZE) || defined(__DOXYGEN__) -#define CH_CFG_MEMCORE_SIZE 0 -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if CH_CFG_MEMCORE_SIZE < 0 -#error "invalid CH_CFG_MEMCORE_SIZE value specified" -#endif - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Memory get function. - */ -typedef void *(*memgetfunc_t)(size_t size, unsigned align); - -/** - * @brief Enhanced memory get function. - */ -typedef void *(*memgetfunc2_t)(size_t size, unsigned align, size_t offset); - -/** - * @brief Type of memory core object. - */ -typedef struct { - /** - * @brief Next free address. - */ - uint8_t *nextmem; - /** - * @brief Final address. - */ - uint8_t *endmem; -} memcore_t; - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern memcore_t ch_memcore; -#endif - -#ifdef __cplusplus -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); - size_t chCoreGetStatusX(void); -#ifdef __cplusplus -} -#endif - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/** - * @brief Allocates a memory block. - * @details The allocated block is guaranteed to be properly aligned to the - * specified alignment. - * - * @param[in] size the size of the block to be allocated. - * @param[in] align desired memory alignment - * @return A pointer to the allocated memory block. - * @retval NULL allocation failed, core memory exhausted. - * - * @iclass - */ -static inline void *chCoreAllocAlignedI(size_t size, unsigned align) { - - return chCoreAllocAlignedWithOffsetI(size, align, 0U); -} - -/** - * @brief Allocates a memory block. - * @details The allocated block is guaranteed to be properly aligned to the - * specified alignment. - * - * @param[in] size the size of the block to be allocated - * @param[in] align desired memory alignment - * @return A pointer to the allocated memory block. - * @retval NULL allocation failed, core memory exhausted. - * - * @api - */ -static inline void *chCoreAllocAligned(size_t size, unsigned align) { - void *p; - - chSysLock(); - p = chCoreAllocAlignedWithOffsetI(size, align, 0U); - chSysUnlock(); - - return p; -} - -/** - * @brief Allocates a memory block. - * @details The allocated block is guaranteed to be properly aligned for a - * pointer data type. - * - * @param[in] size the size of the block to be allocated. - * @return A pointer to the allocated memory block. - * @retval NULL allocation failed, core memory exhausted. - * - * @iclass - */ -static inline void *chCoreAllocI(size_t size) { - - return chCoreAllocAlignedWithOffsetI(size, PORT_NATURAL_ALIGN, 0U); -} - -/** - * @brief Allocates a memory block. - * @details The allocated block is guaranteed to be properly aligned for a - * pointer data type. - * - * @param[in] size the size of the block to be allocated. - * @return A pointer to the allocated memory block. - * @retval NULL allocation failed, core memory exhausted. - * - * @api - */ -static inline void *chCoreAlloc(size_t size) { - - return chCoreAllocAlignedWithOffset(size, PORT_NATURAL_ALIGN, 0U); -} - -#endif /* CH_CFG_USE_MEMCORE == TRUE */ - -#endif /* CHMEMCORE_H */ - -/** @} */ diff --git a/os/lib/include/chmemheaps.h b/os/lib/include/chmemheaps.h deleted file mode 100644 index f20969a32..000000000 --- a/os/lib/include/chmemheaps.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 chmemheaps.h - * @brief Memory heaps macros and structures. - * - * @addtogroup oslib_memheaps - * @{ - */ - -#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) || defined(__DOXYGEN__) - 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/chmempools.h b/os/lib/include/chmempools.h deleted file mode 100644 index 6e5a45277..000000000 --- a/os/lib/include/chmempools.h +++ /dev/null @@ -1,371 +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 chmempools.h - * @brief Memory Pools macros and structures. - * - * @addtogroup oslib_mempools - * @{ - */ - -#ifndef CHMEMPOOLS_H -#define CHMEMPOOLS_H - -#if (CH_CFG_USE_MEMPOOLS == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if CH_CFG_USE_MEMCORE == FALSE -#error "CH_CFG_USE_MEMPOOLS requires CH_CFG_USE_MEMCORE" -#endif - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Memory pool free object header. - */ -struct pool_header { - struct pool_header *next; /**< @brief Pointer to the next pool - header in the list. */ -}; - -/** - * @brief Memory pool descriptor. - */ -typedef struct { - struct pool_header *next; /**< @brief Pointer to the header. */ - size_t object_size; /**< @brief Memory pool objects - size. */ - unsigned align; /**< @brief Required alignment. */ - memgetfunc_t provider; /**< @brief Memory blocks provider - 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 guarding - the memory pool. */ - memory_pool_t pool; /**< @brief The memory pool itself. */ -} guarded_memory_pool_t; -#endif /* CH_CFG_USE_SEMAPHORES == TRUE */ - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/** - * @brief Data part of a static 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 - * @param[in] align required memory alignment - * @param[in] provider memory provider function for the memory pool - */ -#define _MEMORYPOOL_DATA(name, size, align, provider) \ - {NULL, size, align, provider} - -/** - * @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] align required memory alignment - * @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, align, provider) \ - memory_pool_t name = _MEMORYPOOL_DATA(name, size, align, 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 - * @param[in] align required memory alignment - */ -#define _GUARDEDMEMORYPOOL_DATA(name, size, align) { \ - _SEMAPHORE_DATA(name.sem, (cnt_t)0), \ - _MEMORYPOOL_DATA(NULL, size, align, NULL) \ -} - -/** - * @brief Static guarded memory pool initializer. - * @details Statically initialized guarded memory 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 - * @param[in] align required memory alignment - */ -#define GUARDEDMEMORYPOOL_DECL(name, size, align) \ - guarded_memory_pool_t name = _GUARDEDMEMORYPOOL_DATA(name, size, align) -#endif /* CH_CFG_USE_SEMAPHORES == TRUE */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void chPoolObjectInitAligned(memory_pool_t *mp, size_t size, - unsigned align, memgetfunc_t provider); - void chPoolLoadArray(memory_pool_t *mp, void *p, size_t n); - void *chPoolAllocI(memory_pool_t *mp); - 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 chGuardedPoolObjectInitAligned(guarded_memory_pool_t *gmp, - size_t size, - unsigned align); - void chGuardedPoolLoadArray(guarded_memory_pool_t *gmp, void *p, size_t n); - void *chGuardedPoolAllocTimeoutS(guarded_memory_pool_t *gmp, - sysinterval_t timeout); - void *chGuardedPoolAllocTimeout(guarded_memory_pool_t *gmp, - sysinterval_t timeout); - void chGuardedPoolFree(guarded_memory_pool_t *gmp, void *objp); -#endif -#ifdef __cplusplus -} -#endif - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes an empty memory pool. - * - * @param[out] mp pointer to a @p memory_pool_t structure - * @param[in] size the size of the objects contained in this memory pool, - * the minimum accepted size is the size of a pointer to - * void. - * @param[in] provider memory provider function for the memory pool or - * @p NULL if the pool is not allowed to grow - * automatically - * - * @init - */ -static inline void chPoolObjectInit(memory_pool_t *mp, - size_t size, - memgetfunc_t provider) { - - chPoolObjectInitAligned(mp, size, PORT_NATURAL_ALIGN, provider); -} - -/** - * @brief Adds an object to a memory pool. - * @pre The memory pool must be already been initialized. - * @pre The added object must be of the right size for the specified - * memory pool. - * @pre The added object must be properly aligned. - * @note This function is just an alias for @p chPoolFree() and has been - * added for clarity. - * - * @param[in] mp pointer to a @p memory_pool_t structure - * @param[in] objp the pointer to the object to be added - * - * @api - */ -static inline void chPoolAdd(memory_pool_t *mp, void *objp) { - - chPoolFree(mp, objp); -} - -/** - * @brief Adds an object to a memory pool. - * @pre The memory pool must be already been initialized. - * @pre The added object must be of the right size for the specified - * memory pool. - * @pre The added object must be properly aligned. - * @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 - * @param[in] objp the pointer to the object to be added - * - * @iclass - */ -static inline void chPoolAddI(memory_pool_t *mp, void *objp) { - - chPoolFreeI(mp, objp); -} - -#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__) -/** - * @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 - */ -static inline void chGuardedPoolObjectInit(guarded_memory_pool_t *gmp, - size_t size) { - - chGuardedPoolObjectInitAligned(gmp, size, PORT_NATURAL_ALIGN); -} - -/** - * @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 - * @return The pointer to the allocated object. - * @retval NULL if the pool is empty. - * - * @iclass - */ -static inline void *chGuardedPoolAllocI(guarded_memory_pool_t *gmp) { - void *p; - - p = chPoolAllocI(&gmp->pool); - if (p != NULL) { - chSemFastWaitI(&gmp->sem); - chDbgAssert(chSemGetCounterI(&gmp->sem) >= (cnt_t)0, - "semaphore out of sync"); - } - return p; -} - -/** - * @brief Releases an object into a guarded memory pool. - * @pre The guarded memory pool must already be 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 - */ -static inline 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 already be 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 - * - * @sclass - */ -static inline void chGuardedPoolFreeS(guarded_memory_pool_t *gmp, void *objp) { - - chGuardedPoolFreeI(gmp, objp); - chSchRescheduleS(); -} - -/** - * @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) { - - chGuardedPoolFreeI(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 - * - * @sclass - */ -static inline void chGuardedPoolAddS(guarded_memory_pool_t *gmp, void *objp) { - - chGuardedPoolFreeS(gmp, objp); -} -#endif /* CH_CFG_USE_SEMAPHORES == TRUE */ - -#endif /* CH_CFG_USE_MEMPOOLS == TRUE */ - -#endif /* CHMEMPOOLS_H */ - -/** @} */ diff --git a/os/lib/include/chobjfifos.h b/os/lib/include/chobjfifos.h deleted file mode 100644 index c75937eb7..000000000 --- a/os/lib/include/chobjfifos.h +++ /dev/null @@ -1,430 +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 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 oslib_objects_fifos - * @{ - */ - -#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 chFifoObjectInitAligned(objects_fifo_t *ofp, size_t objsize, - size_t objn, unsigned objalign, - void *objbuf, msg_t *msgbuf) { - - chDbgCheck((objsize >= objalign) && (objsize % objalign == 0U)); - - chGuardedPoolObjectInitAligned(&ofp->free, objsize, objalign); - chGuardedPoolLoadArray(&ofp->free, objbuf, objn); - chMBObjectInit(&ofp->mbx, msgbuf, objn); -} - -/** - * @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] 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, void *objbuf, - msg_t *msgbuf) { - - chFifoObjectInitAligned(ofp, objsize, objn, - PORT_NATURAL_ALIGN, - objbuf, msgbuf); -} - -/** - * @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 - * - * @sclass - */ -static inline void chFifoReturnObjectS(objects_fifo_t *ofp, - void *objp) { - - chGuardedPoolFreeS(&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 Posts an high priority 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 chFifoSendObjectAheadI(objects_fifo_t *ofp, - void *objp) { - msg_t msg; - - msg = chMBPostAheadI(&ofp->mbx, (msg_t)objp); - chDbgAssert(msg == MSG_OK, "post failed"); -} - -/** - * @brief Posts an high priority 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 chFifoSendObjectAheadS(objects_fifo_t *ofp, - void *objp) { - msg_t msg; - - msg = chMBPostAheadTimeoutS(&ofp->mbx, (msg_t)objp, TIME_IMMEDIATE); - chDbgAssert(msg == MSG_OK, "post failed"); -} - -/** - * @brief Posts an high priority 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 chFifoSendObjectAhead(objects_fifo_t *ofp, void *objp) { - - msg_t msg; - - msg = chMBPostAheadTimeout(&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/include/chpipes.h b/os/lib/include/chpipes.h deleted file mode 100644 index 8bf26c62b..000000000 --- a/os/lib/include/chpipes.h +++ /dev/null @@ -1,208 +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 chpipes.h - * @brief Pipes macros and structures. - * - * @addtogroup oslib_pipes - * @{ - */ - -#ifndef CHPIPES_H -#define CHPIPES_H - -#if (CH_CFG_USE_PIPES == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Structure representing a pipe object. - */ -typedef struct { - uint8_t *buffer; /**< @brief Pointer to the pipe - buffer. */ - uint8_t *top; /**< @brief Pointer to the location - after the buffer. */ - uint8_t *wrptr; /**< @brief Write pointer. */ - uint8_t *rdptr; /**< @brief Read pointer. */ - size_t cnt; /**< @brief Bytes in the pipe. */ - bool reset; /**< @brief True if in reset state. */ - thread_reference_t wtr; /**< @brief Waiting writer. */ - thread_reference_t rtr; /**< @brief Waiting reader. */ -#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) - mutex_t cmtx; /**< @brief Common access mutex. */ - mutex_t wmtx; /**< @brief Write access mutex. */ - mutex_t rmtx; /**< @brief Read access mutex. */ -#else - semaphore_t csem; /**< @brief Common access semaphore.*/ - semaphore_t wsem; /**< @brief Write access semaphore. */ - semaphore_t rsem; /**< @brief Read access semaphore. */ -#endif -} pipe_t; - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/** - * @brief Data part of a static pipe initializer. - * @details This macro should be used when statically initializing a - * pipe that is part of a bigger structure. - * - * @param[in] name the name of the pipe variable - * @param[in] buffer pointer to the pipe buffer array of @p uint8_t - * @param[in] size number of @p uint8_t elements in the buffer array - */ -#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) -#define _PIPE_DATA(name, buffer, size) { \ - (uint8_t *)(buffer), \ - (uint8_t *)(buffer) + size, \ - (uint8_t *)(buffer), \ - (uint8_t *)(buffer), \ - (size_t)0, \ - false, \ - NULL, \ - NULL, \ - _MUTEX_DATA(name.cmtx), \ - _MUTEX_DATA(name.wmtx), \ - _MUTEX_DATA(name.rmtx), \ -} -#else /* CH_CFG_USE_MUTEXES == FALSE */ -#define _PIPE_DATA(name, buffer, size) { \ - (uint8_t *)(buffer), \ - (uint8_t *)(buffer) + size, \ - (uint8_t *)(buffer), \ - (uint8_t *)(buffer), \ - (size_t)0, \ - false, \ - NULL, \ - NULL, \ - _SEMAPHORE_DATA(name.csem, (cnt_t)1), \ - _SEMAPHORE_DATA(name.wsem, (cnt_t)1), \ - _SEMAPHORE_DATA(name.rsem, (cnt_t)1), \ -} -#endif /* CH_CFG_USE_MUTEXES == FALSE */ - -/** - * @brief Static pipe initializer. - * @details Statically initialized pipes require no explicit - * initialization using @p chPipeObjectInit(). - * - * @param[in] name the name of the pipe variable - * @param[in] buffer pointer to the pipe buffer array of @p uint8_t - * @param[in] size number of @p uint8_t elements in the buffer array - */ -#define PIPE_DECL(name, buffer, size) \ - pipe_t name = _PIPE_DATA(name, buffer, size) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void chPipeObjectInit(pipe_t *pp, uint8_t *buf, size_t n); - void chPipeReset(pipe_t *pp); - size_t chPipeWriteTimeout(pipe_t *pp, const uint8_t *bp, - size_t n, sysinterval_t timeout); - size_t chPipeReadTimeout(pipe_t *pp, uint8_t *bp, - size_t n, sysinterval_t timeout); -#ifdef __cplusplus -} -#endif - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/** - * @brief Returns the pipe buffer size as number of bytes. - * - * @param[in] pp the pointer to an initialized @p pipe_t object - * @return The size of the pipe. - * - * @api - */ -static inline size_t chPipeGetSize(const pipe_t *pp) { - - /*lint -save -e9033 [10.8] Perfectly safe pointers - arithmetic.*/ - return (size_t)(pp->top - pp->buffer); - /*lint -restore*/ -} - -/** - * @brief Returns the number of used byte slots into a pipe. - * - * @param[in] pp the pointer to an initialized @p pipe_t object - * @return The number of queued bytes. - * - * @api - */ -static inline size_t chPipeGetUsedCount(const pipe_t *pp) { - - return pp->cnt; -} - -/** - * @brief Returns the number of free byte slots into a pipe. - * - * @param[in] pp the pointer to an initialized @p pipe_t object - * @return The number of empty byte slots. - * - * @api - */ -static inline size_t chPipeGetFreeCount(const pipe_t *pp) { - - return chPipeGetSize(pp) - chPipeGetUsedCount(pp); -} - -/** - * @brief Terminates the reset state. - * - * @param[in] pp the pointer to an initialized @p pipe_t object - * - * @api - */ -static inline void chPipeResume(pipe_t *pp) { - - pp->reset = false; -} - -#endif /* CH_CFG_USE_PIPES == TRUE */ - -#endif /* CHPIPES_H */ - -/** @} */ diff --git a/os/lib/lib.mk b/os/lib/lib.mk deleted file mode 100644 index 7780318d2..000000000 --- a/os/lib/lib.mk +++ /dev/null @@ -1,49 +0,0 @@ -# List of all the ChibiOS/LIB files, there is no need to remove the files -# from this list, you can disable parts of the kernel by editing chlibconf.h. -ifeq ($(USE_SMART_BUILD),yes) - -# Configuration files directory -ifeq ($(CHCONFDIR),) - ifeq ($(CONFDIR),) - CHCONFDIR = . - else - CHCONFDIR := $(CONFDIR) - endif -endif - -CHLIBCONF := $(strip $(shell cat $(CHCONFDIR)/chconf.h | egrep -e "\#define")) - -LIBSRC := -ifneq ($(findstring CH_CFG_USE_MAILBOXES TRUE,$(CHLIBCONF)),) -LIBSRC += $(CHIBIOS)/os/lib/src/chmboxes.c -endif -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/chmemheaps.c -endif -ifneq ($(findstring CH_CFG_USE_MEMPOOLS TRUE,$(CHLIBCONF)),) -LIBSRC += $(CHIBIOS)/os/lib/src/chmempools.c -endif -ifneq ($(findstring CH_CFG_USE_PIPES TRUE,$(CHLIBCONF)),) -LIBSRC += $(CHIBIOS)/os/lib/src/chpipes.c -endif -ifneq ($(findstring CH_CFG_USE_FACTORY TRUE,$(CHLIBCONF)),) -LIBSRC += $(CHIBIOS)/os/lib/src/chfactory.c -endif -else -LIBSRC := $(CHIBIOS)/os/lib/src/chmboxes.c \ - $(CHIBIOS)/os/lib/src/chmemcore.c \ - $(CHIBIOS)/os/lib/src/chmemheaps.c \ - $(CHIBIOS)/os/lib/src/chmempools.c \ - $(CHIBIOS)/os/lib/src/chpipes.c \ - $(CHIBIOS)/os/lib/src/chfactory.c -endif - -# Required include directories -LIBINC := $(CHIBIOS)/os/lib/include - -# Shared variables -ALLCSRC += $(LIBSRC) -ALLINC += $(LIBINC) diff --git a/os/lib/readme.txt b/os/lib/readme.txt deleted file mode 100644 index d2e0e7222..000000000 --- a/os/lib/readme.txt +++ /dev/null @@ -1,2 +0,0 @@ -All the code contained under ./os/lib are high level RTOS extension modules -compatible with both RT and NIL. \ No newline at end of file diff --git a/os/lib/src/chfactory.c b/os/lib/src/chfactory.c deleted file mode 100644 index b8d9bb07d..000000000 --- a/os/lib/src/chfactory.c +++ /dev/null @@ -1,810 +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 chfactory.c - * @brief ChibiOS objects factory and registry code. - * - * @addtogroup oslib_objects_factory - * @details The object factory is a subsystem that allows to: - * - Register static objects by name. - * - Dynamically create objects and assign them a name. - * - Retrieve existing objects by name. - * - Free objects by reference. - * . - * Allocated OS objects are handled using a reference counter, only - * when all references have been released then the object memory is - * freed in a pool.
- * @pre This subsystem requires the @p CH_CFG_USE_MEMCORE and - * @p CH_CFG_USE_MEMPOOLS options to be set to @p TRUE. The - * option @p CH_CFG_USE_HEAP is also required if the support - * for variable length objects is enabled. - * @note Compatible with RT and NIL. - * @{ - */ - -#include - -#include "ch.h" - -#if (CH_CFG_USE_FACTORY == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Module local definitions. */ -/*===========================================================================*/ - -/* - * Defaults on the best synchronization mechanism available. - */ -#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) -#define F_LOCK() chMtxLock(&ch_factory.mtx) -#define F_UNLOCK() chMtxUnlock(&ch_factory.mtx) -#else -#define F_LOCK() (void) chSemWait(&ch_factory.sem) -#define F_UNLOCK() chSemSignal(&ch_factory.sem) -#endif - -/*===========================================================================*/ -/* Module exported variables. */ -/*===========================================================================*/ - -/** - * @brief Factory object static instance. - * @note It is a global object because it could be accessed through - * a specific debugger plugin. - */ -objects_factory_t ch_factory; - -/*===========================================================================*/ -/* Module local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local functions. */ -/*===========================================================================*/ - -static inline void dyn_list_init(dyn_list_t *dlp) { - - dlp->next = (dyn_element_t *)dlp; -} - -static dyn_element_t *dyn_list_find(const char *name, dyn_list_t *dlp) { - dyn_element_t *p = dlp->next; - - while (p != (dyn_element_t *)dlp) { - if (strncmp(p->name, name, CH_CFG_FACTORY_MAX_NAMES_LENGTH) == 0) { - return p; - } - p = p->next; - } - - return NULL; -} - -static dyn_element_t *dyn_list_unlink(dyn_element_t *element, - dyn_list_t *dlp) { - dyn_element_t *prev = (dyn_element_t *)dlp; - - /* Scanning the list.*/ - while (prev->next != (dyn_element_t *)dlp) { - if (prev->next == element) { - /* Found.*/ - prev->next = element->next; - return element; - } - - /* Next element in the list.*/ - prev = prev->next; - } - - return NULL; -} - -#if CH_FACTORY_REQUIRES_HEAP || defined(__DOXYGEN__) -static dyn_element_t *dyn_create_object_heap(const char *name, - dyn_list_t *dlp, - size_t size) { - dyn_element_t *dep; - - chDbgCheck(name != NULL); - - /* Checking if an object with this name has already been created.*/ - dep = dyn_list_find(name, dlp); - if (dep != NULL) { - return NULL; - } - - /* Allocating space for the new buffer object.*/ - /*lint -save -e668 [] Lint is confused by the above chDbgCheck() and - incorrectly assumes that strncpy() could receive a NULL pointer.*/ - dep = (dyn_element_t *)chHeapAlloc(NULL, size); - if (dep == NULL) { - return NULL; - } - - /* Initializing object list element.*/ - strncpy(dep->name, name, CH_CFG_FACTORY_MAX_NAMES_LENGTH); - /*lint -restore*/ - dep->refs = (ucnt_t)1; - dep->next = dlp->next; - - /* Updating factory list.*/ - dlp->next = dep; - - return dep; -} - -static void dyn_release_object_heap(dyn_element_t *dep, - dyn_list_t *dlp) { - - chDbgCheck(dep != NULL); - chDbgAssert(dep->refs > (ucnt_t)0, "invalid references number"); - - - dep->refs--; - if (dep->refs == (ucnt_t)0) { - dep = dyn_list_unlink(dep, dlp); - chHeapFree((void *)dep); - } -} -#endif /* CH_FACTORY_REQUIRES_HEAP */ - -#if CH_FACTORY_REQUIRES_POOLS || defined(__DOXYGEN__) -static dyn_element_t *dyn_create_object_pool(const char *name, - dyn_list_t *dlp, - memory_pool_t *mp) { - dyn_element_t *dep; - - chDbgCheck(name != NULL); - - /* Checking if an object object with this name has already been created.*/ - dep = dyn_list_find(name, dlp); - if (dep != NULL) { - return NULL; - } - - /* Allocating space for the new object.*/ - dep = (dyn_element_t *)chPoolAlloc(mp); - if (dep == NULL) { - return NULL; - } - - /* Initializing object list element.*/ - /*lint -save -e668 [] Lint is confused by the above chDbgCheck() and - incorrectly assumes that strncpy() could receive a NULL pointer.*/ - strncpy(dep->name, name, CH_CFG_FACTORY_MAX_NAMES_LENGTH); - /*lint -restore*/ - dep->refs = (ucnt_t)1; - dep->next = dlp->next; - - /* Updating factory list.*/ - dlp->next = (dyn_element_t *)dep; - - return dep; -} - -static void dyn_release_object_pool(dyn_element_t *dep, - dyn_list_t *dlp, - memory_pool_t *mp) { - - chDbgCheck(dep != NULL); - chDbgAssert(dep->refs > (ucnt_t)0, "invalid references number"); - - dep->refs--; - if (dep->refs == (ucnt_t)0) { - dep = dyn_list_unlink(dep, dlp); - chPoolFree(mp, (void *)dep); - } -} -#endif /* CH_FACTORY_REQUIRES_POOLS */ - -static dyn_element_t *dyn_find_object(const char *name, dyn_list_t *dlp) { - dyn_element_t *dep; - - chDbgCheck(name != NULL); - - /* Checking if an object with this name has already been created.*/ - dep = dyn_list_find(name, dlp); - if (dep != NULL) { - /* Increasing references counter.*/ - dep->refs++; - } - - return dep; -} - -/*===========================================================================*/ -/* Module exported functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the objects factory. - * - * @init - */ -void _factory_init(void) { - -#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) - chMtxObjectInit(&ch_factory.mtx); -#else - chSemObjectInit(&ch_factory.sem, (cnt_t)1); -#endif - -#if CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE - dyn_list_init(&ch_factory.obj_list); - chPoolObjectInit(&ch_factory.obj_pool, - sizeof (registered_object_t), - chCoreAllocAlignedI); -#endif -#if CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE - dyn_list_init(&ch_factory.buf_list); -#endif -#if CH_CFG_FACTORY_SEMAPHORES == TRUE - dyn_list_init(&ch_factory.sem_list); - chPoolObjectInit(&ch_factory.sem_pool, - sizeof (dyn_semaphore_t), - chCoreAllocAlignedI); -#endif -#if CH_CFG_FACTORY_MAILBOXES == TRUE - dyn_list_init(&ch_factory.mbx_list); -#endif -#if CH_CFG_FACTORY_OBJ_FIFOS == TRUE - dyn_list_init(&ch_factory.fifo_list); -#endif -#if CH_CFG_FACTORY_PIPES == TRUE - dyn_list_init(&ch_factory.pipe_list); -#endif -} - -#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXIGEN__) -/** - * @brief Registers a generic object. - * @post A reference to the registered object is returned and the - * reference counter is initialized to one. - * - * @param[in] name name to be assigned to the registered object - * @param[in] objp pointer to the object to be registered - * - * @return The reference to the registered object. - * @retval NULL if the object to be registered cannot be allocated or - * a registered object with the same name exists. - * - * @api - */ -registered_object_t *chFactoryRegisterObject(const char *name, - void *objp) { - registered_object_t *rop; - - F_LOCK(); - - rop = (registered_object_t *)dyn_create_object_pool(name, - &ch_factory.obj_list, - &ch_factory.obj_pool); - if (rop != NULL) { - /* Initializing registered object data.*/ - rop->objp = objp; - } - - F_UNLOCK(); - - return rop; -} - -/** - * @brief Retrieves a registered object. - * @post A reference to the registered object is returned with the - * reference counter increased by one. - * - * @param[in] name name of the registered object - * - * @return The reference to the found registered object. - * @retval NULL if a registered object with the specified name - * does not exist. - * - * @api - */ -registered_object_t *chFactoryFindObject(const char *name) { - registered_object_t *rop; - - F_LOCK(); - - rop = (registered_object_t *)dyn_find_object(name, &ch_factory.obj_list); - - F_UNLOCK(); - - return rop; -} - -/** - * @brief Retrieves a registered object by pointer. - * @post A reference to the registered object is returned with the - * reference counter increased by one. - * - * @param[in] objp pointer to the object to be retrieved - * - * @return The reference to the found registered object. - * @retval NULL if a registered object with the specified pointer - * does not exist. - * - * @api - */ -registered_object_t *chFactoryFindObjectByPointer(void *objp) { - registered_object_t *rop = (registered_object_t *)ch_factory.obj_list.next; - - F_LOCK(); - - while ((void *)rop != (void *)&ch_factory.obj_list) { - if (rop->objp == objp) { - rop->element.refs++; - - F_UNLOCK(); - - return rop; - } - rop = (registered_object_t *)rop->element.next; - } - - F_UNLOCK(); - - return NULL; -} - -/** - * @brief Releases a registered object. - * @details The reference counter of the registered object is decreased - * by one, if reaches zero then the registered object memory - * is freed. - * @note The object itself is not freed, it could be static, only the - * allocated list element is freed. - * - * @param[in] rop registered object reference - * - * @api - */ -void chFactoryReleaseObject(registered_object_t *rop){ - - F_LOCK(); - - dyn_release_object_pool(&rop->element, - &ch_factory.obj_list, - &ch_factory.obj_pool); - - F_UNLOCK(); -} -#endif /* CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE */ - -#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXIGEN__) -/** - * @brief Creates a generic dynamic buffer object. - * @post A reference to the dynamic buffer object is returned and the - * reference counter is initialized to one. - * @post The dynamic buffer object is filled with zeros. - * - * @param[in] name name to be assigned to the new dynamic buffer object - * @param[in] size payload size of the dynamic buffer object to be created - * - * @return The reference to the created dynamic buffer object. - * @retval NULL if the dynamic buffer object cannot be allocated or - * a dynamic buffer object with the same name exists. - * - * @api - */ -dyn_buffer_t *chFactoryCreateBuffer(const char *name, size_t size) { - dyn_buffer_t *dbp; - - F_LOCK(); - - dbp = (dyn_buffer_t *)dyn_create_object_heap(name, - &ch_factory.buf_list, - size); - if (dbp != NULL) { - /* Initializing buffer object data.*/ - memset((void *)dbp->buffer, 0, size); - } - - F_UNLOCK(); - - return dbp; -} - -/** - * @brief Retrieves a dynamic buffer object. - * @post A reference to the dynamic buffer object is returned with the - * reference counter increased by one. - * - * @param[in] name name of the dynamic buffer object - * - * @return The reference to the found dynamic buffer object. - * @retval NULL if a dynamic buffer object with the specified name - * does not exist. - * - * @api - */ -dyn_buffer_t *chFactoryFindBuffer(const char *name) { - dyn_buffer_t *dbp; - - F_LOCK(); - - dbp = (dyn_buffer_t *)dyn_find_object(name, &ch_factory.buf_list); - - F_UNLOCK(); - - return dbp; -} - -/** - * @brief Releases a dynamic buffer object. - * @details The reference counter of the dynamic buffer object is decreased - * by one, if reaches zero then the dynamic buffer object memory - * is freed. - * - * @param[in] dbp dynamic buffer object reference - * - * @api - */ -void chFactoryReleaseBuffer(dyn_buffer_t *dbp) { - - F_LOCK(); - - dyn_release_object_heap(&dbp->element, &ch_factory.buf_list); - - F_UNLOCK(); -} -#endif /* CH_CFG_FACTORY_GENERIC_BUFFERS = TRUE */ - -#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXIGEN__) -/** - * @brief Creates a dynamic semaphore object. - * @post A reference to the dynamic semaphore object is returned and the - * reference counter is initialized to one. - * @post The dynamic semaphore object is initialized and ready to use. - * - * @param[in] name name to be assigned to the new dynamic semaphore object - * @param[in] n dynamic semaphore object counter initialization value - * - * @return The reference to the created dynamic semaphore object. - * @retval NULL if the dynamic semaphore object cannot be allocated or - * a dynamic semaphore with the same name exists. - * - * @api - */ -dyn_semaphore_t *chFactoryCreateSemaphore(const char *name, cnt_t n) { - dyn_semaphore_t *dsp; - - F_LOCK(); - - dsp = (dyn_semaphore_t *)dyn_create_object_pool(name, - &ch_factory.sem_list, - &ch_factory.sem_pool); - if (dsp != NULL) { - /* Initializing semaphore object dataa.*/ - chSemObjectInit(&dsp->sem, n); - } - - F_UNLOCK(); - - return dsp; -} - -/** - * @brief Retrieves a dynamic semaphore object. - * @post A reference to the dynamic semaphore object is returned with the - * reference counter increased by one. - * - * @param[in] name name of the dynamic semaphore object - * - * @return The reference to the found dynamic semaphore object. - * @retval NULL if a dynamic semaphore object with the specified name - * does not exist. - * - * @api - */ -dyn_semaphore_t *chFactoryFindSemaphore(const char *name) { - dyn_semaphore_t *dsp; - - F_LOCK(); - - dsp = (dyn_semaphore_t *)dyn_find_object(name, &ch_factory.sem_list); - - F_UNLOCK(); - - return dsp; -} - -/** - * @brief Releases a dynamic semaphore object. - * @details The reference counter of the dynamic semaphore object is decreased - * by one, if reaches zero then the dynamic semaphore object memory - * is freed. - * - * @param[in] dsp dynamic semaphore object reference - * - * @api - */ -void chFactoryReleaseSemaphore(dyn_semaphore_t *dsp) { - - F_LOCK(); - - dyn_release_object_pool(&dsp->element, - &ch_factory.sem_list, - &ch_factory.sem_pool); - - F_UNLOCK(); -} -#endif /* CH_CFG_FACTORY_SEMAPHORES = TRUE */ - -#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXIGEN__) -/** - * @brief Creates a dynamic mailbox object. - * @post A reference to the dynamic mailbox object is returned and the - * reference counter is initialized to one. - * @post The dynamic mailbox object is initialized and ready to use. - * - * @param[in] name name to be assigned to the new dynamic mailbox object - * @param[in] n mailbox buffer size as number of messages - * - * @return The reference to the created dynamic mailbox object. - * @retval NULL if the dynamic mailbox object cannot be allocated or - * a dynamic mailbox object with the same name exists. - * - * @api - */ -dyn_mailbox_t *chFactoryCreateMailbox(const char *name, size_t n) { - dyn_mailbox_t *dmp; - - F_LOCK(); - - dmp = (dyn_mailbox_t *)dyn_create_object_heap(name, - &ch_factory.mbx_list, - sizeof (dyn_mailbox_t) + - (n * sizeof (msg_t))); - if (dmp != NULL) { - /* Initializing mailbox object data.*/ - chMBObjectInit(&dmp->mbx, dmp->msgbuf, n); - } - - F_UNLOCK(); - - return dmp; -} - -/** - * @brief Retrieves a dynamic mailbox object. - * @post A reference to the dynamic mailbox object is returned with the - * reference counter increased by one. - * - * @param[in] name name of the dynamic mailbox object - * - * @return The reference to the found dynamic mailbox object. - * @retval NULL if a dynamic mailbox object with the specified name - * does not exist. - * - * @api - */ -dyn_mailbox_t *chFactoryFindMailbox(const char *name) { - dyn_mailbox_t *dmp; - - F_LOCK(); - - dmp = (dyn_mailbox_t *)dyn_find_object(name, &ch_factory.mbx_list); - - F_UNLOCK(); - - return dmp; -} - -/** - * @brief Releases a dynamic mailbox object. - * @details The reference counter of the dynamic mailbox object is decreased - * by one, if reaches zero then the dynamic mailbox object memory - * is freed. - * - * @param[in] dmp dynamic mailbox object reference - * - * @api - */ -void chFactoryReleaseMailbox(dyn_mailbox_t *dmp) { - - F_LOCK(); - - dyn_release_object_heap(&dmp->element, &ch_factory.mbx_list); - - F_UNLOCK(); -} -#endif /* CH_CFG_FACTORY_MAILBOXES = TRUE */ - -#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXIGEN__) -/** - * @brief Creates a dynamic "objects FIFO" object. - * @post A reference to the dynamic "objects FIFO" object is returned and - * the reference counter is initialized to one. - * @post The dynamic "objects FIFO" object is initialized and ready to use. - * - * @param[in] name name to be assigned to the new dynamic "objects FIFO" - * object - * @param[in] objsize size of objects - * @param[in] objn number of objects available - * @param[in] objalign required objects alignment - * @return The reference to the created dynamic "objects FIFO" - * object. - * @retval NULL if the dynamic "objects FIFO" object cannot be - * allocated or a dynamic "objects FIFO" object with - * the same name exists. - * - * @api - */ -dyn_objects_fifo_t *chFactoryCreateObjectsFIFO(const char *name, - size_t objsize, - size_t objn, - unsigned objalign) { - dyn_objects_fifo_t *dofp; - - F_LOCK(); - - dofp = (dyn_objects_fifo_t *)dyn_create_object_heap(name, - &ch_factory.fifo_list, - sizeof (dyn_objects_fifo_t) + - (objn * sizeof (msg_t)) + - (objn * objsize)); - if (dofp != NULL) { - /* Initializing mailbox object data.*/ - chFifoObjectInitAligned(&dofp->fifo, objsize, objn, objalign, - (void *)&dofp->msgbuf[objn], dofp->msgbuf); - } - - F_UNLOCK(); - - return dofp; -} - -/** - * @brief Retrieves a dynamic "objects FIFO" object. - * @post A reference to the dynamic "objects FIFO" object is returned with - * the reference counter increased by one. - * - * @param[in] name name of the dynamic "objects FIFO" object - * - * @return The reference to the found dynamic "objects FIFO" - * object. - * @retval NULL if a dynamic "objects FIFO" object with the specified - * name does not exist. - * - * @api - */ -dyn_objects_fifo_t *chFactoryFindObjectsFIFO(const char *name) { - dyn_objects_fifo_t *dofp; - - F_LOCK(); - - dofp = (dyn_objects_fifo_t *)dyn_find_object(name, &ch_factory.fifo_list); - - F_UNLOCK(); - - return dofp; -} - -/** - * @brief Releases a dynamic "objects FIFO" object. - * @details The reference counter of the dynamic "objects FIFO" object is - * decreased by one, if reaches zero then the dynamic "objects FIFO" - * object memory is freed. - * - * @param[in] dofp dynamic "objects FIFO" object reference - * - * @api - */ -void chFactoryReleaseObjectsFIFO(dyn_objects_fifo_t *dofp) { - - F_LOCK(); - - dyn_release_object_heap(&dofp->element, &ch_factory.fifo_list); - - F_UNLOCK(); -} -#endif /* CH_CFG_FACTORY_OBJ_FIFOS = TRUE */ - -#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXIGEN__) -/** - * @brief Creates a dynamic pipe object. - * @post A reference to the dynamic pipe object is returned and - * the reference counter is initialized to one. - * @post The dynamic pipe object is initialized and ready to use. - * - * @param[in] name name to be assigned to the new dynamic pipe - * object - * @param[in] size pipe buffer size - * @return The reference to the created dynamic pipe - * object. - * @retval NULL if the dynamic pipe object cannot be - * allocated or a dynamic pipe object with - * the same name exists. - * - * @api - */ -dyn_pipe_t *chFactoryCreatePipe(const char *name, size_t size) { - dyn_pipe_t *dpp; - - F_LOCK(); - - dpp = (dyn_pipe_t *)dyn_create_object_heap(name, - &ch_factory.pipe_list, - sizeof (dyn_pipe_t) + size); - if (dpp != NULL) { - /* Initializing mailbox object data.*/ - chPipeObjectInit(&dpp->pipe, dpp->buffer, size); - } - - F_UNLOCK(); - - return dpp; -} - -/** - * @brief Retrieves a dynamic pipe object. - * @post A reference to the dynamic pipe object is returned with - * the reference counter increased by one. - * - * @param[in] name name of the pipe object - * - * @return The reference to the found dynamic pipe - * object. - * @retval NULL if a dynamic pipe object with the specified - * name does not exist. - * - * @api - */ -dyn_pipe_t *chFactoryFindPipe(const char *name) { - dyn_pipe_t *dpp; - - F_LOCK(); - - dpp = (dyn_pipe_t *)dyn_find_object(name, &ch_factory.pipe_list); - - F_UNLOCK(); - - return dpp; -} - -/** - * @brief Releases a dynamic pipe object. - * @details The reference counter of the dynamic pipe object is - * decreased by one, if reaches zero then the dynamic pipe - * object memory is freed. - * - * @param[in] dpp dynamic pipe object reference - * - * @api - */ -void chFactoryReleasePipe(dyn_pipe_t *dpp) { - - F_LOCK(); - - dyn_release_object_heap(&dpp->element, &ch_factory.pipe_list); - - F_UNLOCK(); -} -#endif /* CH_CFG_FACTORY_PIPES = TRUE */ - -#endif /* CH_CFG_USE_FACTORY == TRUE */ - -/** @} */ diff --git a/os/lib/src/chmboxes.c b/os/lib/src/chmboxes.c deleted file mode 100644 index 1b23bf2e0..000000000 --- a/os/lib/src/chmboxes.c +++ /dev/null @@ -1,522 +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 chmboxes.c - * @brief Mailboxes code. - * - * @addtogroup oslib_mailboxes - * @details Asynchronous messages. - *

Operation mode

- * A mailbox is an asynchronous communication mechanism.
- * Operations defined for mailboxes: - * - Post: Posts a message on the mailbox in FIFO order. - * - Post Ahead: Posts a message on the mailbox with urgent - * priority. - * - Fetch: A message is fetched from the mailbox and removed - * from the queue. - * - Reset: The mailbox is emptied and all the stored messages - * are lost. - * . - * A message is a variable of type msg_t that is guaranteed to have - * the same size of and be compatible with (data) pointers (anyway an - * explicit cast is needed). - * If larger messages need to be exchanged then a pointer to a - * structure can be posted in the mailbox but the posting side has - * no predefined way to know when the message has been processed. A - * possible approach is to allocate memory (from a memory pool for - * example) from the posting side and free it on the fetching side. - * Another approach is to set a "done" flag into the structure pointed - * by the message. - * @pre In order to use the mailboxes APIs the @p CH_CFG_USE_MAILBOXES - * option must be enabled in @p chconf.h. - * @note Compatible with RT and NIL. - * @{ - */ - -#include "ch.h" - -#if (CH_CFG_USE_MAILBOXES == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Module exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes a @p mailbox_t object. - * - * @param[out] mbp the pointer to the @p mailbox_t structure to be - * initialized - * @param[in] buf pointer to the messages buffer as an array of @p msg_t - * @param[in] n number of elements in the buffer array - * - * @init - */ -void chMBObjectInit(mailbox_t *mbp, msg_t *buf, size_t n) { - - chDbgCheck((mbp != NULL) && (buf != NULL) && (n > (size_t)0)); - - mbp->buffer = buf; - mbp->rdptr = buf; - mbp->wrptr = buf; - mbp->top = &buf[n]; - mbp->cnt = (size_t)0; - mbp->reset = false; - chThdQueueObjectInit(&mbp->qw); - chThdQueueObjectInit(&mbp->qr); -} - -/** - * @brief Resets a @p mailbox_t object. - * @details All the waiting threads are resumed with status @p MSG_RESET and - * the queued messages are lost. - * @post The mailbox is in reset state, all operations will fail and - * return @p MSG_RESET until the mailbox is enabled again using - * @p chMBResumeX(). - * - * @param[in] mbp the pointer to an initialized @p mailbox_t object - * - * @api - */ -void chMBReset(mailbox_t *mbp) { - - chSysLock(); - chMBResetI(mbp); - chSchRescheduleS(); - chSysUnlock(); -} - -/** - * @brief Resets a @p mailbox_t object. - * @details All the waiting threads are resumed with status @p MSG_RESET and - * the queued messages are lost. - * @post The mailbox is in reset state, all operations will fail and - * return @p MSG_RESET until the mailbox is enabled again using - * @p chMBResumeX(). - * - * @param[in] mbp the pointer to an initialized @p mailbox_t object - * - * @api - */ -void chMBResetI(mailbox_t *mbp) { - - chDbgCheckClassI(); - chDbgCheck(mbp != NULL); - - mbp->wrptr = mbp->buffer; - mbp->rdptr = mbp->buffer; - mbp->cnt = (size_t)0; - mbp->reset = true; - chThdDequeueAllI(&mbp->qw, MSG_RESET); - chThdDequeueAllI(&mbp->qr, MSG_RESET); -} - -/** - * @brief Posts a message into a mailbox. - * @details The invoking thread waits until a empty slot in the mailbox becomes - * available or the specified time runs out. - * - * @param[in] mbp the pointer to an initialized @p mailbox_t object - * @param[in] msg the message to be posted on the mailbox - * @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 a message has been correctly posted. - * @retval MSG_RESET if the mailbox has been reset. - * @retval MSG_TIMEOUT if the operation has timed out. - * - * @api - */ -msg_t chMBPostTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) { - msg_t rdymsg; - - chSysLock(); - rdymsg = chMBPostTimeoutS(mbp, msg, timeout); - chSysUnlock(); - - return rdymsg; -} - -/** - * @brief Posts a message into a mailbox. - * @details The invoking thread waits until a empty slot in the mailbox becomes - * available or the specified time runs out. - * - * @param[in] mbp the pointer to an initialized @p mailbox_t object - * @param[in] msg the message to be posted on the mailbox - * @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 a message has been correctly posted. - * @retval MSG_RESET if the mailbox has been reset. - * @retval MSG_TIMEOUT if the operation has timed out. - * - * @sclass - */ -msg_t chMBPostTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) { - msg_t rdymsg; - - chDbgCheckClassS(); - chDbgCheck(mbp != NULL); - - do { - /* If the mailbox is in reset state then returns immediately.*/ - if (mbp->reset) { - return MSG_RESET; - } - - /* Is there a free message slot in queue? if so then post.*/ - if (chMBGetFreeCountI(mbp) > (size_t)0) { - *mbp->wrptr++ = msg; - if (mbp->wrptr >= mbp->top) { - mbp->wrptr = mbp->buffer; - } - mbp->cnt++; - - /* If there is a reader waiting then makes it ready.*/ - chThdDequeueNextI(&mbp->qr, MSG_OK); - chSchRescheduleS(); - - return MSG_OK; - } - - /* No space in the queue, waiting for a slot to become available.*/ - rdymsg = chThdEnqueueTimeoutS(&mbp->qw, timeout); - } while (rdymsg == MSG_OK); - - return rdymsg; -} - -/** - * @brief Posts a message into a mailbox. - * @details This variant is non-blocking, the function returns a timeout - * condition if the queue is full. - * - * @param[in] mbp the pointer to an initialized @p mailbox_t object - * @param[in] msg the message to be posted on the mailbox - * @return The operation status. - * @retval MSG_OK if a message has been correctly posted. - * @retval MSG_RESET if the mailbox has been reset. - * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be - * posted. - * - * @iclass - */ -msg_t chMBPostI(mailbox_t *mbp, msg_t msg) { - - chDbgCheckClassI(); - chDbgCheck(mbp != NULL); - - /* If the mailbox is in reset state then returns immediately.*/ - if (mbp->reset) { - return MSG_RESET; - } - - /* Is there a free message slot in queue? if so then post.*/ - if (chMBGetFreeCountI(mbp) > (size_t)0) { - *mbp->wrptr++ = msg; - if (mbp->wrptr >= mbp->top) { - mbp->wrptr = mbp->buffer; - } - mbp->cnt++; - - /* If there is a reader waiting then makes it ready.*/ - chThdDequeueNextI(&mbp->qr, MSG_OK); - - return MSG_OK; - } - - /* No space, immediate timeout.*/ - return MSG_TIMEOUT; -} - -/** - * @brief Posts an high priority message into a mailbox. - * @details The invoking thread waits until a empty slot in the mailbox becomes - * available or the specified time runs out. - * - * @param[in] mbp the pointer to an initialized @p mailbox_t object - * @param[in] msg the message to be posted on the mailbox - * @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 a message has been correctly posted. - * @retval MSG_RESET if the mailbox has been reset. - * @retval MSG_TIMEOUT if the operation has timed out. - * - * @api - */ -msg_t chMBPostAheadTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) { - msg_t rdymsg; - - chSysLock(); - rdymsg = chMBPostAheadTimeoutS(mbp, msg, timeout); - chSysUnlock(); - - return rdymsg; -} - -/** - * @brief Posts an high priority message into a mailbox. - * @details The invoking thread waits until a empty slot in the mailbox becomes - * available or the specified time runs out. - * - * @param[in] mbp the pointer to an initialized @p mailbox_t object - * @param[in] msg the message to be posted on the mailbox - * @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 a message has been correctly posted. - * @retval MSG_RESET if the mailbox has been reset. - * @retval MSG_TIMEOUT if the operation has timed out. - * - * @sclass - */ -msg_t chMBPostAheadTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) { - msg_t rdymsg; - - chDbgCheckClassS(); - chDbgCheck(mbp != NULL); - - do { - /* If the mailbox is in reset state then returns immediately.*/ - if (mbp->reset) { - return MSG_RESET; - } - - /* Is there a free message slot in queue? if so then post.*/ - if (chMBGetFreeCountI(mbp) > (size_t)0) { - if (--mbp->rdptr < mbp->buffer) { - mbp->rdptr = mbp->top - 1; - } - *mbp->rdptr = msg; - mbp->cnt++; - - /* If there is a reader waiting then makes it ready.*/ - chThdDequeueNextI(&mbp->qr, MSG_OK); - chSchRescheduleS(); - - return MSG_OK; - } - - /* No space in the queue, waiting for a slot to become available.*/ - rdymsg = chThdEnqueueTimeoutS(&mbp->qw, timeout); - } while (rdymsg == MSG_OK); - - return rdymsg; -} - -/** - * @brief Posts an high priority message into a mailbox. - * @details This variant is non-blocking, the function returns a timeout - * condition if the queue is full. - * - * @param[in] mbp the pointer to an initialized @p mailbox_t object - * @param[in] msg the message to be posted on the mailbox - * @return The operation status. - * @retval MSG_OK if a message has been correctly posted. - * @retval MSG_RESET if the mailbox has been reset. - * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be - * posted. - * - * @iclass - */ -msg_t chMBPostAheadI(mailbox_t *mbp, msg_t msg) { - - chDbgCheckClassI(); - chDbgCheck(mbp != NULL); - - /* If the mailbox is in reset state then returns immediately.*/ - if (mbp->reset) { - return MSG_RESET; - } - - /* Is there a free message slot in queue? if so then post.*/ - if (chMBGetFreeCountI(mbp) > (size_t)0) { - if (--mbp->rdptr < mbp->buffer) { - mbp->rdptr = mbp->top - 1; - } - *mbp->rdptr = msg; - mbp->cnt++; - - /* If there is a reader waiting then makes it ready.*/ - chThdDequeueNextI(&mbp->qr, MSG_OK); - - return MSG_OK; - } - - /* No space, immediate timeout.*/ - return MSG_TIMEOUT; -} - -/** - * @brief Retrieves a message from a mailbox. - * @details The invoking thread waits until a message is posted in the mailbox - * or the specified time runs out. - * - * @param[in] mbp the pointer to an initialized @p mailbox_t object - * @param[out] msgp pointer to a message variable for the received message - * @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 a message has been correctly fetched. - * @retval MSG_RESET if the mailbox has been reset. - * @retval MSG_TIMEOUT if the operation has timed out. - * - * @api - */ -msg_t chMBFetchTimeout(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout) { - msg_t rdymsg; - - chSysLock(); - rdymsg = chMBFetchTimeoutS(mbp, msgp, timeout); - chSysUnlock(); - - return rdymsg; -} - -/** - * @brief Retrieves a message from a mailbox. - * @details The invoking thread waits until a message is posted in the mailbox - * or the specified time runs out. - * - * @param[in] mbp the pointer to an initialized @p mailbox_t object - * @param[out] msgp pointer to a message variable for the received message - * @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 a message has been correctly fetched. - * @retval MSG_RESET if the mailbox has been reset. - * @retval MSG_TIMEOUT if the operation has timed out. - * - * @sclass - */ -msg_t chMBFetchTimeoutS(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout) { - msg_t rdymsg; - - chDbgCheckClassS(); - chDbgCheck((mbp != NULL) && (msgp != NULL)); - - do { - /* If the mailbox is in reset state then returns immediately.*/ - if (mbp->reset) { - return MSG_RESET; - } - - /* Is there a message in queue? if so then fetch.*/ - if (chMBGetUsedCountI(mbp) > (size_t)0) { - *msgp = *mbp->rdptr++; - if (mbp->rdptr >= mbp->top) { - mbp->rdptr = mbp->buffer; - } - mbp->cnt--; - - /* If there is a writer waiting then makes it ready.*/ - chThdDequeueNextI(&mbp->qw, MSG_OK); - chSchRescheduleS(); - - return MSG_OK; - } - - /* No message in the queue, waiting for a message to become available.*/ - rdymsg = chThdEnqueueTimeoutS(&mbp->qr, timeout); - } while (rdymsg == MSG_OK); - - return rdymsg; -} - -/** - * @brief Retrieves a message from a mailbox. - * @details This variant is non-blocking, the function returns a timeout - * condition if the queue is empty. - * - * @param[in] mbp the pointer to an initialized @p mailbox_t object - * @param[out] msgp pointer to a message variable for the received message - * @return The operation status. - * @retval MSG_OK if a message has been correctly fetched. - * @retval MSG_RESET if the mailbox has been reset. - * @retval MSG_TIMEOUT if the mailbox is empty and a message cannot be - * fetched. - * - * @iclass - */ -msg_t chMBFetchI(mailbox_t *mbp, msg_t *msgp) { - - chDbgCheckClassI(); - chDbgCheck((mbp != NULL) && (msgp != NULL)); - - /* If the mailbox is in reset state then returns immediately.*/ - if (mbp->reset) { - return MSG_RESET; - } - - /* Is there a message in queue? if so then fetch.*/ - if (chMBGetUsedCountI(mbp) > (size_t)0) { - *msgp = *mbp->rdptr++; - if (mbp->rdptr >= mbp->top) { - mbp->rdptr = mbp->buffer; - } - mbp->cnt--; - - /* If there is a writer waiting then makes it ready.*/ - chThdDequeueNextI(&mbp->qw, MSG_OK); - - return MSG_OK; - } - - /* No message, immediate timeout.*/ - return MSG_TIMEOUT; -} -#endif /* CH_CFG_USE_MAILBOXES == TRUE */ - -/** @} */ diff --git a/os/lib/src/chmemcore.c b/os/lib/src/chmemcore.c deleted file mode 100644 index 5dc3ce446..000000000 --- a/os/lib/src/chmemcore.c +++ /dev/null @@ -1,175 +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 chmemcore.c - * @brief Core memory manager code. - * - * @addtogroup oslib_memcore - * @details Core Memory Manager related APIs and services. - *

Operation mode

- * The core memory manager is a simplified allocator that only - * allows to allocate memory blocks without the possibility to - * free them.
- * This allocator is meant as a memory blocks provider for the - * other allocators such as: - * - C-Runtime allocator (through a compiler specific adapter module). - * - Heap allocator (see @ref oslib_memheaps). - * - Memory pools allocator (see @ref oslib_mempools). - * . - * By having a centralized memory provider the various allocators - * can coexist and share the main memory.
- * This allocator, alone, is also useful for very simple - * applications that just require a simple way to get memory - * blocks. - * @pre In order to use the core memory manager APIs the @p CH_CFG_USE_MEMCORE - * option must be enabled in @p chconf.h. - * @note Compatible with RT and NIL. - * @{ - */ - -#include "ch.h" - -#if (CH_CFG_USE_MEMCORE == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Module exported variables. */ -/*===========================================================================*/ - -/** - * @brief Memory core descriptor. - */ -memcore_t ch_memcore; - -/*===========================================================================*/ -/* Module local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level memory manager initialization. - * - * @notapi - */ -void _core_init(void) { -#if CH_CFG_MEMCORE_SIZE == 0 - extern uint8_t __heap_base__[]; - extern uint8_t __heap_end__[]; - - /*lint -save -e9033 [10.8] Required cast operations.*/ - ch_memcore.nextmem = __heap_base__; - ch_memcore.endmem = __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]; -#endif -} - -/** - * @brief Allocates a memory block. - * @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 *chCoreAllocAlignedWithOffsetI(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); - next = p + size; - - /* Considering also the case where there is numeric overflow.*/ - if ((next > ch_memcore.endmem) || (next < ch_memcore.nextmem)) { - return NULL; - } - - ch_memcore.nextmem = next; - - return p; -} - -/** - * @brief Allocates a memory block. - * @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 *chCoreAllocAlignedWithOffset(size_t size, - unsigned align, - size_t offset) { - void *p; - - chSysLock(); - p = chCoreAllocAlignedWithOffsetI(size, align, offset); - chSysUnlock(); - - return p; -} - -/** - * @brief Core memory status. - * - * @return The size, in bytes, of the free core memory. - * - * @xclass - */ -size_t chCoreGetStatusX(void) { - - /*lint -save -e9033 [10.8] The cast is safe.*/ - return (size_t)(ch_memcore.endmem - ch_memcore.nextmem); - /*lint -restore*/ -} -#endif /* CH_CFG_USE_MEMCORE == TRUE */ - -/** @} */ diff --git a/os/lib/src/chmemheaps.c b/os/lib/src/chmemheaps.c deleted file mode 100644 index a03bde2e7..000000000 --- a/os/lib/src/chmemheaps.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 chmemheaps.c - * @brief Memory heaps code. - * - * @addtogroup oslib_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 * 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 @p NULL - * @param[in] largestp pointer to a variable that will receive the largest - * free free block found space or @p 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/chmempools.c b/os/lib/src/chmempools.c deleted file mode 100644 index 996b66329..000000000 --- a/os/lib/src/chmempools.c +++ /dev/null @@ -1,336 +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 chmempools.c - * @brief Memory Pools code. - * - * @addtogroup oslib_mempools - * @details Memory Pools related APIs and services. - *

Operation mode

- * The Memory Pools APIs allow to allocate/free fixed size objects in - * constant time and reliably without memory fragmentation - * problems.
- * Memory Pools do not enforce any alignment constraint on the - * contained object however the objects must be properly aligned - * to contain a pointer to void. - * @pre In order to use the memory pools APIs the @p CH_CFG_USE_MEMPOOLS option - * must be enabled in @p chconf.h. - * @note Compatible with RT and NIL. - * @{ - */ - -#include "ch.h" - -#if (CH_CFG_USE_MEMPOOLS == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Module exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes an empty memory pool. - * - * @param[out] mp pointer to a @p memory_pool_t structure - * @param[in] size the size of the objects contained in this memory pool, - * the minimum accepted size is the size of a pointer to - * void. - * @param[in] align required memory alignment - * @param[in] provider memory provider function for the memory pool or - * @p NULL if the pool is not allowed to grow - * automatically - * - * @init - */ -void chPoolObjectInitAligned(memory_pool_t *mp, size_t size, - unsigned align, memgetfunc_t provider) { - - chDbgCheck((mp != NULL) && - (size >= sizeof(void *)) && - (align >= PORT_NATURAL_ALIGN) && - MEM_IS_VALID_ALIGNMENT(align)); - - mp->next = NULL; - mp->object_size = size; - mp->align = align; - mp->provider = provider; -} - -/** - * @brief Loads a memory pool with an array of static objects. - * @pre The memory pool must already be initialized. - * @pre The array elements must be of the right size for the specified - * memory pool. - * @pre The array elements size must be a multiple of the alignment - * requirement for the pool. - * @post The memory pool contains the elements of the input array. - * - * @param[in] mp pointer to a @p memory_pool_t structure - * @param[in] p pointer to the array first element - * @param[in] n number of elements in the array - * - * @api - */ -void chPoolLoadArray(memory_pool_t *mp, void *p, size_t n) { - - chDbgCheck((mp != NULL) && (n != 0U)); - - while (n != 0U) { - chPoolAdd(mp, p); - /*lint -save -e9087 [11.3] Safe cast.*/ - p = (void *)(((uint8_t *)p) + mp->object_size); - /*lint -restore*/ - n--; - } -} - -/** - * @brief Allocates an object from a memory pool. - * @pre The memory pool must already be initialized. - * - * @param[in] mp pointer to a @p memory_pool_t structure - * @return The pointer to the allocated object. - * @retval NULL if pool is empty. - * - * @iclass - */ -void *chPoolAllocI(memory_pool_t *mp) { - void *objp; - - chDbgCheckClassI(); - chDbgCheck(mp != NULL); - - objp = mp->next; - /*lint -save -e9013 [15.7] There is no else because it is not needed.*/ - if (objp != NULL) { - mp->next = mp->next->next; - } - else if (mp->provider != NULL) { - objp = mp->provider(mp->object_size, mp->align); - - chDbgAssert(MEM_IS_ALIGNED(objp, mp->align), - "returned object not aligned"); - } - /*lint -restore*/ - - return objp; -} - -/** - * @brief Allocates an object from a memory pool. - * @pre The memory pool must already be initialized. - * - * @param[in] mp pointer to a @p memory_pool_t structure - * @return The pointer to the allocated object. - * @retval NULL if pool is empty. - * - * @api - */ -void *chPoolAlloc(memory_pool_t *mp) { - void *objp; - - chSysLock(); - objp = chPoolAllocI(mp); - chSysUnlock(); - - return objp; -} - -/** - * @brief Releases an object into a memory pool. - * @pre The memory pool must already be initialized. - * @pre The freed object must be of the right size for the specified - * memory pool. - * @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 - * - * @iclass - */ -void chPoolFreeI(memory_pool_t *mp, void *objp) { - struct pool_header *php = objp; - - chDbgCheckClassI(); - chDbgCheck((mp != NULL) && - (objp != NULL) && - MEM_IS_ALIGNED(objp, mp->align)); - - php->next = mp->next; - mp->next = php; -} - -/** - * @brief Releases an object into a memory pool. - * @pre The memory pool must already be initialized. - * @pre The freed object must be of the right size for the specified - * memory pool. - * @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 - * - * @api - */ -void chPoolFree(memory_pool_t *mp, void *objp) { - - chSysLock(); - chPoolFreeI(mp, objp); - chSysUnlock(); -} - -#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__) -/** - * @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. - * @param[in] align required memory alignment - * - * @init - */ -void chGuardedPoolObjectInitAligned(guarded_memory_pool_t *gmp, - size_t size, - unsigned align) { - - chPoolObjectInitAligned(&gmp->pool, size, align, 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 already be 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 already be 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, - sysinterval_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 already be 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, - sysinterval_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 already be 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 */ - -/** @} */ diff --git a/os/lib/src/chpipes.c b/os/lib/src/chpipes.c deleted file mode 100644 index 6f6e8a30f..000000000 --- a/os/lib/src/chpipes.c +++ /dev/null @@ -1,388 +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 chpipes.c - * @brief Pipes code. - * @details Byte pipes. - *

Operation mode

- * A pipe is an asynchronous communication mechanism.
- * Operations defined for mailboxes: - * - Write: Writes a buffer of data in the pipe in FIFO order. - * - Read: A buffer of data is read from the read and removed. - * - Reset: The pipe is emptied and all the stored data - * is lost. - * . - * @pre In order to use the pipes APIs the @p CH_CFG_USE_PIPES - * option must be enabled in @p chconf.h. - * @note Compatible with RT and NIL. - * - * @addtogroup oslib_pipes - * @{ - */ - -#include - -#include "ch.h" - -#if (CH_CFG_USE_PIPES == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Module local definitions. */ -/*===========================================================================*/ - -/* - * Defaults on the best synchronization mechanism available. - */ -#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) -#define PC_INIT(p) chMtxObjectInit(&(p)->cmtx) -#define PC_LOCK(p) chMtxLock(&(p)->cmtx) -#define PC_UNLOCK(p) chMtxUnlock(&(p)->cmtx) -#define PW_INIT(p) chMtxObjectInit(&(p)->wmtx) -#define PW_LOCK(p) chMtxLock(&(p)->wmtx) -#define PW_UNLOCK(p) chMtxUnlock(&(p)->wmtx) -#define PR_INIT(p) chMtxObjectInit(&(p)->rmtx) -#define PR_LOCK(p) chMtxLock(&(p)->rmtx) -#define PR_UNLOCK(p) chMtxUnlock(&(p)->rmtx) -#else -#define PC_INIT(p) chSemObjectInit(&(p)->csem, (cnt_t)1) -#define PC_LOCK(p) (void) chSemWait(&(p)->csem) -#define PC_UNLOCK(p) chSemSignal(&(p)->csem) -#define PW_INIT(p) chSemObjectInit(&(p)->wsem, (cnt_t)1) -#define PW_LOCK(p) (void) chSemWait(&(p)->wsem) -#define PW_UNLOCK(p) chSemSignal(&(p)->wsem) -#define PR_INIT(p) chSemObjectInit(&(p)->rsem, (cnt_t)1) -#define PR_LOCK(p) (void) chSemWait(&(p)->rsem) -#define PR_UNLOCK(p) chSemSignal(&(p)->rsem) -#endif - -/*===========================================================================*/ -/* Module exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local functions. */ -/*===========================================================================*/ - -/** - * @brief Non-blocking pipe write. - * @details The function writes data from a buffer to a pipe. The - * operation completes when the specified amount of data has been - * transferred or when the pipe buffer has been filled. - * - * @param[in] pp the pointer to an initialized @p pipe_t object - * @param[in] bp pointer to the data buffer - * @param[in] n the maximum amount of data to be transferred, the - * value 0 is reserved - * @return The number of bytes effectively transferred. - * - * @notapi - */ -static size_t pipe_write(pipe_t *pp, const uint8_t *bp, size_t n) { - size_t s1, s2; - - PC_LOCK(pp); - - /* Number of bytes that can be written in a single atomic operation.*/ - if (n > chPipeGetFreeCount(pp)) { - n = chPipeGetFreeCount(pp); - } - pp->cnt += n; - - /* Number of bytes before buffer limit.*/ - /*lint -save -e9033 [10.8] Checked to be safe.*/ - s1 = (size_t)(pp->top - pp->wrptr); - /*lint -restore*/ - - if (n < s1) { - memcpy((void *)pp->wrptr, (const void *)bp, n); - pp->wrptr += n; - } - else if (n > s1) { - memcpy((void *)pp->wrptr, (const void *)bp, s1); - bp += s1; - s2 = n - s1; - memcpy((void *)pp->buffer, (const void *)bp, s2); - pp->wrptr = pp->buffer + s2; - } - else { /* n == s1 */ - memcpy((void *)pp->wrptr, (const void *)bp, n); - pp->wrptr = pp->buffer; - } - - PC_UNLOCK(pp); - - return n; -} - -/** - * @brief Non-blocking pipe read. - * @details The function reads data from a pipe into a buffer. The - * operation completes when the specified amount of data has been - * transferred or when the pipe buffer has been emptied. - * - * @param[in] pp the pointer to an initialized @p pipe_t object - * @param[out] bp pointer to the data buffer - * @param[in] n the maximum amount of data to be transferred, the - * value 0 is reserved - * @return The number of bytes effectively transferred. - * - * @notapi - */ -static size_t pipe_read(pipe_t *pp, uint8_t *bp, size_t n) { - size_t s1, s2; - - PC_LOCK(pp); - - /* Number of bytes that can be read in a single atomic operation.*/ - if (n > chPipeGetUsedCount(pp)) { - n = chPipeGetUsedCount(pp); - } - pp->cnt -= n; - - /* Number of bytes before buffer limit.*/ - /*lint -save -e9033 [10.8] Checked to be safe.*/ - s1 = (size_t)(pp->top - pp->rdptr); - /*lint -restore*/ - - if (n < s1) { - memcpy((void *)bp, (void *)pp->rdptr, n); - pp->rdptr += n; - } - else if (n > s1) { - memcpy((void *)bp, (void *)pp->rdptr, s1); - bp += s1; - s2 = n - s1; - memcpy((void *)bp, (void *)pp->buffer, s2); - pp->rdptr = pp->buffer + s2; - } - else { /* n == s1 */ - memcpy((void *)bp, (void *)pp->rdptr, n); - pp->rdptr = pp->buffer; - } - - PC_UNLOCK(pp); - - return n; -} - -/*===========================================================================*/ -/* Module exported functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes a @p mailbox_t object. - * - * @param[out] pp the pointer to the @p pipe_t structure to be - * initialized - * @param[in] buf pointer to the pipe buffer as an array of @p uint8_t - * @param[in] n number of elements in the buffer array - * - * @init - */ -void chPipeObjectInit(pipe_t *pp, uint8_t *buf, size_t n) { - - chDbgCheck((pp != NULL) && (buf != NULL) && (n > (size_t)0)); - - pp->buffer = buf; - pp->rdptr = buf; - pp->wrptr = buf; - pp->top = &buf[n]; - pp->cnt = (size_t)0; - pp->reset = false; - pp->wtr = NULL; - pp->rtr = NULL; - PC_INIT(pp); - PW_INIT(pp); - PR_INIT(pp); -} - -/** - * @brief Resets a @p pipe_t object. - * @details All the waiting threads are resumed with status @p MSG_RESET and - * the queued data is lost. - * @post The pipe is in reset state, all operations will fail and - * return @p MSG_RESET until the mailbox is enabled again using - * @p chPipeResumeX(). - * - * @param[in] pp the pointer to an initialized @p pipe_t object - * - * @api - */ -void chPipeReset(pipe_t *pp) { - - chDbgCheck(pp != NULL); - - PC_LOCK(pp); - - pp->wrptr = pp->buffer; - pp->rdptr = pp->buffer; - pp->cnt = (size_t)0; - pp->reset = true; - - chSysLock(); - chThdResumeI(&pp->wtr, MSG_RESET); - chThdResumeI(&pp->rtr, MSG_RESET); - chSchRescheduleS(); - chSysUnlock(); - - PC_UNLOCK(pp); -} - -/** - * @brief Pipe write with timeout. - * @details The function writes data from a buffer to a pipe. The - * operation completes when the specified amount of data has been - * transferred or after the specified timeout or if the pipe has - * been reset. - * - * @param[in] pp the pointer to an initialized @p pipe_t object - * @param[in] bp pointer to the data buffer - * @param[in] n the number of bytes to be written, the value 0 is - * reserved - * @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 number of bytes effectively transferred. A number - * lower than @p n means that a timeout occurred or the - * pipe went in reset state. - * - * @api - */ -size_t chPipeWriteTimeout(pipe_t *pp, const uint8_t *bp, - size_t n, sysinterval_t timeout) { - size_t max = n; - - chDbgCheck(n > 0U); - - /* If the pipe is in reset state then returns immediately.*/ - if (pp->reset) { - return (size_t)0; - } - - PW_LOCK(pp); - - while (n > 0U) { - size_t done; - - done = pipe_write(pp, bp, n); - if (done == (size_t)0) { - msg_t msg; - - chSysLock(); - msg = chThdSuspendTimeoutS(&pp->wtr, timeout); - chSysUnlock(); - - /* Anything except MSG_OK causes the operation to stop.*/ - if (msg != MSG_OK) { - break; - } - } - else { - n -= done; - bp += done; - - /* Resuming the reader, if present.*/ - chThdResume(&pp->rtr, MSG_OK); - } - } - - PW_UNLOCK(pp); - - return max - n; -} - -/** - * @brief Pipe read with timeout. - * @details The function reads data from a pipe into a buffer. The - * operation completes when the specified amount of data has been - * transferred or after the specified timeout or if the pipe has - * been reset. - * - * @param[in] pp the pointer to an initialized @p pipe_t object - * @param[out] bp pointer to the data buffer - * @param[in] n the number of bytes to be read, the value 0 is - * reserved - * @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 number of bytes effectively transferred. A number - * lower than @p n means that a timeout occurred or the - * pipe went in reset state. - * - * @api - */ -size_t chPipeReadTimeout(pipe_t *pp, uint8_t *bp, - size_t n, sysinterval_t timeout) { - size_t max = n; - - chDbgCheck(n > 0U); - - /* If the pipe is in reset state then returns immediately.*/ - if (pp->reset) { - return (size_t)0; - } - - PR_LOCK(pp); - - while (n > 0U) { - size_t done; - - done = pipe_read(pp, bp, n); - if (done == (size_t)0) { - msg_t msg; - - chSysLock(); - msg = chThdSuspendTimeoutS(&pp->rtr, timeout); - chSysUnlock(); - - /* Anything except MSG_OK causes the operation to stop.*/ - if (msg != MSG_OK) { - break; - } - } - else { - n -= done; - bp += done; - - /* Resuming the writer, if present.*/ - chThdResume(&pp->wtr, MSG_OK); - } - } - - PR_UNLOCK(pp); - - return max - n; -} - -#endif /* CH_CFG_USE_MAILBOXES == TRUE */ - -/** @} */ diff --git a/os/nil/nil.mk b/os/nil/nil.mk index fa08333ce..69238e91e 100644 --- a/os/nil/nil.mk +++ b/os/nil/nil.mk @@ -26,4 +26,4 @@ ALLCSRC += $(KERNSRC) ALLINC += $(KERNINC) # OS Library -include $(CHIBIOS)/os/lib/lib.mk +include $(CHIBIOS)/os/oslib/oslib.mk diff --git a/os/oslib/dox/lib.dox b/os/oslib/dox/lib.dox new file mode 100644 index 000000000..4dfcdce58 --- /dev/null +++ b/os/oslib/dox/lib.dox @@ -0,0 +1,85 @@ +/* + 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 . +*/ +/** + * @defgroup oslib OS Library + * @details The OS Library is a set of RTOS extensions compatible with both + * the RT and NIL RTOSes. + */ + +/** + * @defgroup oslib_info Version Numbers and Identification + * @ingroup oslib + */ + +/** + * @defgroup oslib_synchronization Synchronization + * @details Synchronization services. + * @ingroup oslib + */ + +/** + * @defgroup oslib_binary_semaphores Binary Semaphores + * @ingroup oslib_synchronization + */ + +/** + * @defgroup oslib_mailboxes Mailboxes + * @ingroup oslib_synchronization + */ + +/** + * @defgroup oslib_pipes Pipes + * @ingroup oslib_synchronization + */ + +/** + * @defgroup oslib_memory Memory Management + * @details Memory Management services. + * @ingroup oslib + */ + +/** + * @defgroup oslib_memcore Core Memory Manager + * @ingroup oslib_memory + */ + +/** + * @defgroup oslib_memheaps Memory Heaps + * @ingroup oslib_memory + */ + +/** + * @defgroup oslib_mempools Memory Pools + * @ingroup oslib_memory + */ + +/** + * @defgroup oslib_complex Complex Services + * @ingroup oslib + */ + +/** + * @defgroup oslib_objects_fifos Objects FIFOs + * @ingroup oslib_complex + */ + +/** + * @defgroup oslib_objects_factory Dynamic Objects Factory + * @ingroup oslib_complex + */ diff --git a/os/oslib/include/chbsem.h b/os/oslib/include/chbsem.h new file mode 100644 index 000000000..192aec86a --- /dev/null +++ b/os/oslib/include/chbsem.h @@ -0,0 +1,311 @@ +/* + 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 chbsem.h + * @brief Binary semaphores structures and macros. + * @details Binary semaphores related APIs and services. + *

Operation mode

+ * Binary semaphores are implemented as a set of inline functions + * that use the existing counting semaphores primitives. The + * difference between counting and binary semaphores is that the + * counter of binary semaphores is not allowed to grow above the + * value 1. Repeated signal operation are ignored. A binary + * semaphore can thus have only two defined states: + * - Taken, when its counter has a value of zero or lower + * than zero. A negative number represent the number of threads + * queued on the binary semaphore. + * - Not taken, when its counter has a value of one. + * . + * Binary semaphores are different from mutexes because there is no + * concept of ownership, a binary semaphore can be taken by a + * thread and signaled by another thread or an interrupt handler, + * mutexes can only be taken and released by the same thread. Another + * difference is that binary semaphores, unlike mutexes, do not + * implement the priority inheritance protocol.
+ * In order to use the binary semaphores APIs the + * @p CH_CFG_USE_SEMAPHORES option must be enabled in @p chconf.h. + * + * @addtogroup oslib_binary_semaphores + * @{ + */ + +#ifndef CHBSEM_H +#define CHBSEM_H + +#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @extends semaphore_t + * + * @brief Binary semaphore type. + */ +typedef struct ch_binary_semaphore { + semaphore_t sem; +} binary_semaphore_t; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Data part of a static semaphore initializer. + * @details This macro should be used when statically initializing a semaphore + * that is part of a bigger structure. + * + * @param[in] name the name of the semaphore variable + * @param[in] taken the semaphore initial state + */ +#define _BSEMAPHORE_DATA(name, taken) \ + {_SEMAPHORE_DATA(name.sem, ((taken) ? 0 : 1))} + +/** + * @brief Static semaphore initializer. + * @details Statically initialized semaphores require no explicit + * initialization using @p chBSemInit(). + * + * @param[in] name the name of the semaphore variable + * @param[in] taken the semaphore initial state + */ +#define BSEMAPHORE_DECL(name, taken) \ + binary_semaphore_t name = _BSEMAPHORE_DATA(name, taken) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes a binary semaphore. + * + * @param[out] bsp pointer to a @p binary_semaphore_t structure + * @param[in] taken initial state of the binary semaphore: + * - @a false, the initial state is not taken. + * - @a true, the initial state is taken. + * . + * + * @init + */ +static inline void chBSemObjectInit(binary_semaphore_t *bsp, bool taken) { + + chSemObjectInit(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1); +} + +/** + * @brief Wait operation on the binary semaphore. + * + * @param[in] bsp pointer to a @p binary_semaphore_t structure + * @return A message specifying how the invoking thread has been + * released from the semaphore. + * @retval MSG_OK if the binary semaphore has been successfully taken. + * @retval MSG_RESET if the binary semaphore has been reset using + * @p bsemReset(). + * + * @api + */ +static inline msg_t chBSemWait(binary_semaphore_t *bsp) { + + return chSemWait(&bsp->sem); +} + +/** + * @brief Wait operation on the binary semaphore. + * + * @param[in] bsp pointer to a @p binary_semaphore_t structure + * @return A message specifying how the invoking thread has been + * released from the semaphore. + * @retval MSG_OK if the binary semaphore has been successfully taken. + * @retval MSG_RESET if the binary semaphore has been reset using + * @p bsemReset(). + * + * @sclass + */ +static inline msg_t chBSemWaitS(binary_semaphore_t *bsp) { + + chDbgCheckClassS(); + + return chSemWaitS(&bsp->sem); +} + +/** + * @brief Wait operation on the binary semaphore. + * + * @param[in] bsp pointer to a @p binary_semaphore_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 A message specifying how the invoking thread has been + * released from the semaphore. + * @retval MSG_OK if the binary semaphore has been successfully taken. + * @retval MSG_RESET if the binary semaphore has been reset using + * @p bsemReset(). + * @retval MSG_TIMEOUT if the binary semaphore has not been signaled or reset + * within the specified timeout. + * + * @sclass + */ +static inline msg_t chBSemWaitTimeoutS(binary_semaphore_t *bsp, + sysinterval_t timeout) { + + chDbgCheckClassS(); + + return chSemWaitTimeoutS(&bsp->sem, timeout); +} + +/** + * @brief Wait operation on the binary semaphore. + * + * @param[in] bsp pointer to a @p binary_semaphore_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 A message specifying how the invoking thread has been + * released from the semaphore. + * @retval MSG_OK if the binary semaphore has been successfully taken. + * @retval MSG_RESET if the binary semaphore has been reset using + * @p bsemReset(). + * @retval MSG_TIMEOUT if the binary semaphore has not been signaled or reset + * within the specified timeout. + * + * @api + */ +static inline msg_t chBSemWaitTimeout(binary_semaphore_t *bsp, + sysinterval_t timeout) { + + return chSemWaitTimeout(&bsp->sem, timeout); +} + +/** + * @brief Reset operation on the binary semaphore. + * @note The released threads can recognize they were waked up by a reset + * rather than a signal because the @p bsemWait() will return + * @p MSG_RESET instead of @p MSG_OK. + * @note This function does not reschedule. + * + * @param[in] bsp pointer to a @p binary_semaphore_t structure + * @param[in] taken new state of the binary semaphore + * - @a false, the new state is not taken. + * - @a true, the new state is taken. + * . + * + * @iclass + */ +static inline void chBSemResetI(binary_semaphore_t *bsp, bool taken) { + + chDbgCheckClassI(); + + chSemResetI(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1); +} + +/** + * @brief Reset operation on the binary semaphore. + * @note The released threads can recognize they were waked up by a reset + * rather than a signal because the @p bsemWait() will return + * @p MSG_RESET instead of @p MSG_OK. + * + * @param[in] bsp pointer to a @p binary_semaphore_t structure + * @param[in] taken new state of the binary semaphore + * - @a false, the new state is not taken. + * - @a true, the new state is taken. + * . + * + * @api + */ +static inline void chBSemReset(binary_semaphore_t *bsp, bool taken) { + + chSemReset(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1); +} + +/** + * @brief Performs a signal operation on a binary semaphore. + * @note This function does not reschedule. + * + * @param[in] bsp pointer to a @p binary_semaphore_t structure + * + * @iclass + */ +static inline void chBSemSignalI(binary_semaphore_t *bsp) { + + chDbgCheckClassI(); + + if (bsp->sem.cnt < (cnt_t)1) { + chSemSignalI(&bsp->sem); + } +} + +/** + * @brief Performs a signal operation on a binary semaphore. + * + * @param[in] bsp pointer to a @p binary_semaphore_t structure + * + * @api + */ +static inline void chBSemSignal(binary_semaphore_t *bsp) { + + chSysLock(); + chBSemSignalI(bsp); + chSchRescheduleS(); + chSysUnlock(); +} + +/** + * @brief Returns the binary semaphore current state. + * + * @param[in] bsp pointer to a @p binary_semaphore_t structure + * @return The binary semaphore current state. + * @retval false if the binary semaphore is not taken. + * @retval true if the binary semaphore is taken. + * + * @iclass + */ +static inline bool chBSemGetStateI(const binary_semaphore_t *bsp) { + + chDbgCheckClassI(); + + return (bsp->sem.cnt > (cnt_t)0) ? false : true; +} + +#endif /* CH_CFG_USE_SEMAPHORES == TRUE */ + +#endif /* CHBSEM_H */ + +/** @} */ diff --git a/os/oslib/include/chfactory.h b/os/oslib/include/chfactory.h new file mode 100644 index 000000000..aaaa5d2c2 --- /dev/null +++ b/os/oslib/include/chfactory.h @@ -0,0 +1,553 @@ +/* + 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 chfactory.h + * @brief ChibiOS objects factory structures and macros. + * + * @addtogroup oslib_objects_factory + * @{ + */ + +#ifndef CHFACTORY_H +#define CHFACTORY_H + +#if (CH_CFG_USE_FACTORY == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Maximum length for object names. + * @details If the specified length is zero then the name is stored by + * pointer but this could have unintended side effects. + */ +#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8 +#endif + +/** + * @brief Enables the registry of generic objects. + */ +#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE +#endif + +/** + * @brief Enables factory for generic buffers. + */ +#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE +#endif + +/** + * @brief Enables factory for semaphores. + */ +#if !defined(CH_CFG_FACTORY_SEMAPHORES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_SEMAPHORES TRUE +#endif + +/** + * @brief Enables factory for mailboxes. + */ +#if !defined(CH_CFG_FACTORY_MAILBOXES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_MAILBOXES TRUE +#endif + +/** + * @brief Enables factory for objects FIFOs. + */ +#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE +#endif + +/** + * @brief Enables factory for objects FIFOs. + */ +#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_OBJ_FIFOS TRUE +#endif + +/** + * @brief Enables factory for Pipes. + */ +#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__) +#define CH_CFG_FACTORY_PIPES TRUE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) && (CH_CFG_USE_SEMAPHORES == FALSE) +/*lint -save -e767 [20.5] Valid because the #undef.*/ +#undef CH_CFG_FACTORY_SEMAPHORES +#define CH_CFG_FACTORY_SEMAPHORES FALSE +/*lint restore*/ +#endif + +#if (CH_CFG_FACTORY_MAILBOXES == TRUE) && (CH_CFG_USE_MAILBOXES == FALSE) +/*lint -save -e767 [20.5] Valid because the #undef.*/ +#undef CH_CFG_FACTORY_MAILBOXES +#define CH_CFG_FACTORY_MAILBOXES FALSE +/*lint restore*/ +#endif + +#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) && (CH_CFG_USE_OBJ_FIFOS == FALSE) +/*lint -save -e767 [20.5] Valid because the #undef.*/ +#undef CH_CFG_FACTORY_OBJ_FIFOS +#define CH_CFG_FACTORY_OBJ_FIFOS FALSE +/*lint restore*/ +#endif + +#if (CH_CFG_FACTORY_PIPES == TRUE) && (CH_CFG_USE_PIPES == FALSE) +/*lint -save -e767 [20.5] Valid because the #undef.*/ +#undef CH_CFG_FACTORY_PIPES +#define CH_CFG_FACTORY_PIPES FALSE +/*lint restore*/ +#endif + +#define CH_FACTORY_REQUIRES_POOLS \ + ((CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || \ + (CH_CFG_FACTORY_SEMAPHORES == TRUE)) + +#define CH_FACTORY_REQUIRES_HEAP \ + ((CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || \ + (CH_CFG_FACTORY_MAILBOXES == TRUE) || \ + (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || \ + (CH_CFG_FACTORY_PIPES == TRUE)) + +#if (CH_CFG_FACTORY_MAX_NAMES_LENGTH < 0) || \ + (CH_CFG_FACTORY_MAX_NAMES_LENGTH > 32) +#error "invalid CH_CFG_FACTORY_MAX_NAMES_LENGTH value" +#endif + +#if (CH_CFG_USE_MUTEXES == FALSE) && (CH_CFG_USE_SEMAPHORES == FALSE) +#error "CH_CFG_USE_FACTORY requires CH_CFG_USE_MUTEXES and/or CH_CFG_USE_SEMAPHORES" +#endif + +#if CH_CFG_USE_MEMCORE == FALSE +#error "CH_CFG_USE_FACTORY requires CH_CFG_USE_MEMCORE" +#endif + +#if CH_FACTORY_REQUIRES_POOLS && (CH_CFG_USE_MEMPOOLS == FALSE) +#error "CH_CFG_USE_MEMPOOLS is required" +#endif + +#if CH_FACTORY_REQUIRES_HEAP && (CH_CFG_USE_HEAP == FALSE) +#error "CH_CFG_USE_HEAP is required" +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a dynamic object list element. + */ +typedef struct ch_dyn_element { + /** + * @brief Next dynamic object in the list. + */ + struct ch_dyn_element *next; + /** + * @brief Number of references to this object. + */ + ucnt_t refs; +#if (CH_CFG_FACTORY_MAX_NAMES_LENGTH > 0) || defined(__DOXYGEN__) + char name[CH_CFG_FACTORY_MAX_NAMES_LENGTH]; +#else + const char *name; +#endif +} dyn_element_t; + +/** + * @brief Type of a dynamic object list. + */ +typedef struct ch_dyn_list { + dyn_element_t *next; +} dyn_list_t; + +#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__) +/** + * @brief Type of a registered object. + */ +typedef struct ch_registered_static_object { + /** + * @brief List element of the registered object. + */ + dyn_element_t element; + /** + * @brief Pointer to the object. + * @note The type of the object is not stored in anyway. + */ + void *objp; +} registered_object_t; +#endif + +#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__) +/** + * @brief Type of a dynamic buffer object. + */ +typedef struct ch_dyn_object { + /** + * @brief List element of the dynamic buffer object. + */ + dyn_element_t element; + /*lint -save -e9038 [18.7] Required by design.*/ + /** + * @brief The buffer. + * @note This requires C99. + */ + uint8_t buffer[]; + /*lint restore*/ +} dyn_buffer_t; +#endif + +#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__) +/** + * @brief Type of a dynamic semaphore. + */ +typedef struct ch_dyn_semaphore { + /** + * @brief List element of the dynamic semaphore. + */ + dyn_element_t element; + /** + * @brief The semaphore. + */ + semaphore_t sem; +} dyn_semaphore_t; +#endif + +#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__) +/** + * @brief Type of a dynamic buffer object. + */ +typedef struct ch_dyn_mailbox { + /** + * @brief List element of the dynamic buffer object. + */ + dyn_element_t element; + /** + * @brief The mailbox. + */ + mailbox_t mbx; + /*lint -save -e9038 [18.7] Required by design.*/ + /** + * @brief Messages buffer. + * @note This requires C99. + */ + msg_t msgbuf[]; + /*lint restore*/ +} dyn_mailbox_t; +#endif + +#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) +/** + * @brief Type of a dynamic buffer object. + */ +typedef struct ch_dyn_objects_fifo { + /** + * @brief List element of the dynamic buffer object. + */ + dyn_element_t element; + /** + * @brief The objects FIFO. + */ + objects_fifo_t fifo; + /*lint -save -e9038 [18.7] Required by design.*/ + /** + * @brief Messages buffer. + * @note This open array is followed by another area containing the + * objects, this area is not represented in this structure. + * @note This requires C99. + */ + msg_t msgbuf[]; + /*lint restore*/ +} dyn_objects_fifo_t; +#endif + +#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__) +/** + * @brief Type of a dynamic pipe object. + */ +typedef struct ch_dyn_pipe { + /** + * @brief List element of the dynamic pipe object. + */ + dyn_element_t element; + /** + * @brief The pipe. + */ + pipe_t pipe; + /*lint -save -e9038 [18.7] Required by design.*/ + /** + * @brief Messages buffer. + * @note This requires C99. + */ + uint8_t buffer[]; + /*lint restore*/ +} dyn_pipe_t; +#endif + +/** + * @brief Type of the factory main object. + */ +typedef struct ch_objects_factory { + /** + * @brief Factory access mutex or semaphore. + */ +#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) + mutex_t mtx; +#else + semaphore_t sem; +#endif + /** + * @brief List of the registered objects. + */ + dyn_list_t obj_list; + /** + * @brief Pool of the available registered objects. + */ + memory_pool_t obj_pool; +#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__) + /** + * @brief List of the allocated buffer objects. + */ + dyn_list_t buf_list; +#endif /* CH_CFG_FACTORY_GENERIC_BUFFERS = TRUE */ +#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__) + /** + * @brief List of the allocated semaphores. + */ + dyn_list_t sem_list; + /** + * @brief Pool of the available semaphores. + */ + memory_pool_t sem_pool; +#endif /* CH_CFG_FACTORY_SEMAPHORES = TRUE */ +#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__) + /** + * @brief List of the allocated buffer objects. + */ + dyn_list_t mbx_list; +#endif /* CH_CFG_FACTORY_MAILBOXES = TRUE */ +#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) + /** + * @brief List of the allocated "objects FIFO" objects. + */ + dyn_list_t fifo_list; +#endif /* CH_CFG_FACTORY_OBJ_FIFOS = TRUE */ +#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__) + /** + * @brief List of the allocated pipe objects. + */ + dyn_list_t pipe_list; +#endif /* CH_CFG_FACTORY_PIPES = TRUE */ +} objects_factory_t; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern objects_factory_t ch_factory; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void _factory_init(void); +#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__) + registered_object_t *chFactoryRegisterObject(const char *name, + void *objp); + registered_object_t *chFactoryFindObject(const char *name); + registered_object_t *chFactoryFindObjectByPointer(void *objp); + void chFactoryReleaseObject(registered_object_t *rop); +#endif +#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__) + dyn_buffer_t *chFactoryCreateBuffer(const char *name, size_t size); + dyn_buffer_t *chFactoryFindBuffer(const char *name); + void chFactoryReleaseBuffer(dyn_buffer_t *dbp); +#endif +#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__) + dyn_semaphore_t *chFactoryCreateSemaphore(const char *name, cnt_t n); + dyn_semaphore_t *chFactoryFindSemaphore(const char *name); + void chFactoryReleaseSemaphore(dyn_semaphore_t *dsp); +#endif +#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__) + dyn_mailbox_t *chFactoryCreateMailbox(const char *name, size_t n); + dyn_mailbox_t *chFactoryFindMailbox(const char *name); + void chFactoryReleaseMailbox(dyn_mailbox_t *dmp); +#endif +#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) + dyn_objects_fifo_t *chFactoryCreateObjectsFIFO(const char *name, + size_t objsize, + size_t objn, + unsigned objalign); + dyn_objects_fifo_t *chFactoryFindObjectsFIFO(const char *name); + void chFactoryReleaseObjectsFIFO(dyn_objects_fifo_t *dofp); +#endif +#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__) + dyn_pipe_t *chFactoryCreatePipe(const char *name, size_t size); + dyn_pipe_t *chFactoryFindPipe(const char *name); + void chFactoryReleasePipe(dyn_pipe_t *dpp); +#endif +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Duplicates an object reference. + * @note This function can be used on any kind of dynamic object. + * + * @param[in] dep pointer to the element field of the object + * @return The duplicated object reference. + * + * @api + */ +static inline dyn_element_t *chFactoryDuplicateReference(dyn_element_t *dep) { + + dep->refs++; + + return dep; +} + +#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXYGEN__) +/** + * @brief Returns the pointer to the inner registered object. + * + * @param[in] rop registered object reference + * @return The pointer to the registered object. + * + * @api + */ +static inline void *chFactoryGetObject(registered_object_t *rop) { + + return rop->objp; +} +#endif /* CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE */ + +#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXYGEN__) +/** + * @brief Returns the size of a generic dynamic buffer object. + * + * @param[in] dbp dynamic buffer object reference + * @return The size of the buffer object in bytes. + * + * @api + */ +static inline size_t chFactoryGetBufferSize(dyn_buffer_t *dbp) { + + return chHeapGetSize(dbp) - sizeof (dyn_element_t); +} + +/** + * @brief Returns the pointer to the inner buffer. + * + * @param[in] dbp dynamic buffer object reference + * @return The pointer to the dynamic buffer. + * + * @api + */ +static inline uint8_t *chFactoryGetBuffer(dyn_buffer_t *dbp) { + + return dbp->buffer; +} +#endif /* CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE */ + +#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXYGEN__) +/** + * @brief Returns the pointer to the inner semaphore. + * + * @param[in] dsp dynamic semaphore object reference + * @return The pointer to the semaphore. + * + * @api + */ +static inline semaphore_t *chFactoryGetSemaphore(dyn_semaphore_t *dsp) { + + return &dsp->sem; +} +#endif /* CH_CFG_FACTORY_SEMAPHORES == TRUE */ + +#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXYGEN__) +/** + * @brief Returns the pointer to the inner mailbox. + * + * @param[in] dmp dynamic mailbox object reference + * @return The pointer to the mailbox. + * + * @api + */ +static inline mailbox_t *chFactoryGetMailbox(dyn_mailbox_t *dmp) { + + return &dmp->mbx; +} +#endif /* CH_CFG_FACTORY_MAILBOXES == TRUE */ + +#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXYGEN__) +/** + * @brief Returns the pointer to the inner objects FIFO. + * + * @param[in] dofp dynamic "objects FIFO" object reference + * @return The pointer to the objects FIFO. + * + * @api + */ +static inline objects_fifo_t *chFactoryGetObjectsFIFO(dyn_objects_fifo_t *dofp) { + + return &dofp->fifo; +} +#endif /* CH_CFG_FACTORY_OBJ_FIFOS == TRUE */ + +#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXYGEN__) +/** + * @brief Returns the pointer to the inner pipe. + * + * @param[in] dpp dynamic pipe object reference + * @return The pointer to the pipe. + * + * @api + */ +static inline pipe_t *chFactoryGetPipe(dyn_pipe_t *dpp) { + + return &dpp->pipe; +} +#endif /* CH_CFG_FACTORY_PIPES == TRUE */ + +#endif /* CH_CFG_USE_FACTORY == TRUE */ + +#endif /* CHFACTORY_H */ + +/** @} */ diff --git a/os/oslib/include/chlib.h b/os/oslib/include/chlib.h new file mode 100644 index 000000000..495d03643 --- /dev/null +++ b/os/oslib/include/chlib.h @@ -0,0 +1,217 @@ +/* + 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 chlib.h + * @brief ChibiOS/LIB main include file. + * @details This header includes all the required library headers. This file + * is meant do be included by @p ch.h not directly by user. + * + * @addtogroup oslib_info + * @details OS Library related info. + * @{ + */ + +#ifndef CHLIB_H +#define CHLIB_H + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @brief ChibiOS/LIB identification macro. + */ +#define _CHIBIOS_OSLIB_ + +/** + * @brief Stable release flag. + */ +#define CH_OSLIB_STABLE 0 + +/** + * @name ChibiOS/LIB version identification + * @{ + */ +/** + * @brief OS Library version string. + */ +#define CH_OSLIB_VERSION "1.0.0" + +/** + * @brief Kernel version major number. + */ +#define CH_OSLIB_MAJOR 1 + +/** + * @brief Kernel version minor number. + */ +#define CH_OSLIB_MINOR 0 + +/** + * @brief Kernel version patch number. + */ +#define CH_OSLIB_PATCH 0 +/** @} */ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* Host OS checks.*/ +#if !defined(_CHIBIOS_RT_) && !defined(_CHIBIOS_NIL_) +#error "OS check failed, must be included after ch.h" +#endif + +/* Configuration file checks.*/ +#if !defined(CH_CFG_USE_MAILBOXES) +#error "CH_CFG_USE_MAILBOXES not defined in chconf.h" +#endif + +#if !defined(CH_CFG_USE_MEMCORE) +#error "CH_CFG_USE_MEMCORE not defined in chconf.h" +#endif + +#if !defined(CH_CFG_USE_HEAP) +#error "CH_CFG_USE_HEAP not defined in chconf.h" +#endif + +#if !defined(CH_CFG_USE_MEMPOOLS) +#error "CH_CFG_USE_MEMPOOLS not defined in chconf.h" +#endif + +#if !defined(CH_CFG_USE_OBJ_FIFOS) +#error "CH_CFG_USE_OBJ_FIFOS not defined in chconf.h" +#endif + +#if !defined(CH_CFG_USE_PIPES) +#error "CH_CFG_USE_PIPES not defined in chconf.h" +#endif + +/* Objects factory options checks.*/ +#if !defined(CH_CFG_USE_FACTORY) +#error "CH_CFG_USE_FACTORY not defined in chconf.h" +#endif + +#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) +#error "CH_CFG_FACTORY_MAX_NAMES_LENGTH not defined in chconf.h" +#endif + +#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) +#error "CH_CFG_FACTORY_OBJECTS_REGISTRY not defined in chconf.h" +#endif + +#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) +#error "CH_CFG_FACTORY_GENERIC_BUFFERS not defined in chconf.h" +#endif + +#if !defined(CH_CFG_FACTORY_SEMAPHORES) +#error "CH_CFG_FACTORY_SEMAPHORES not defined in chconf.h" +#endif + +#if !defined(CH_CFG_FACTORY_MAILBOXES) +#error "CH_CFG_FACTORY_MAILBOXES not defined in chconf.h" +#endif + +#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) +#error "CH_CFG_FACTORY_OBJ_FIFOS not defined in chconf.h" +#endif + +/* License checks.*/ +#if !defined(CH_CUSTOMER_LIC_OSLIB) || !defined(CH_LICENSE_FEATURES) +#error "malformed chlicense.h" +#endif + +#if CH_CUSTOMER_LIC_OSLIB== FALSE +#error "ChibiOS/LIB not licensed" +#endif + +#if (CH_LICENSE_FEATURES != CH_FEATURES_FULL) && \ + (CH_LICENSE_FEATURES != CH_FEATURES_INTERMEDIATE) && \ + (CH_LICENSE_FEATURES != CH_FEATURES_BASIC) +#error "invalid CH_LICENSE_FEATURES setting" +#endif + +/* Restrictions in basic and intermediate modes.*/ +#if (CH_CUSTOMER_LIC_OSLIB == FALSE) || \ + (CH_LICENSE_FEATURES == CH_FEATURES_INTERMEDIATE) || \ + (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) + +/* Restricted subsystems.*/ +#undef CH_CFG_USE_FACTORY + +#define CH_CFG_USE_FACTORY FALSE + +#endif /* (CH_CUSTOMER_LIC_OSLIB == FALSE) || + (CH_LICENSE_FEATURES == CH_FEATURES_INTERMEDIATE) || + (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) */ + +/* Restrictions in basic mode.*/ +#if (CH_CUSTOMER_LIC_OSLIB == FALSE) || \ + (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) + +/* Restricted subsystems.*/ +#undef CH_CFG_USE_MEMCORE +#undef CH_CFG_USE_HEAP +#undef CH_CFG_USE_MEMPOOLS +#undef CH_CFG_USE_OBJ_FIFOS +#undef CH_CFG_USE_PIPES + +#define CH_CFG_USE_MEMCORE FALSE +#define CH_CFG_USE_HEAP FALSE +#define CH_CFG_USE_MEMPOOLS FALSE +#define CH_CFG_USE_OBJ_FIFOS FALSE +#define CH_CFG_USE_PIPES FALSE + +#endif /* (CH_CUSTOMER_LIC_OSLIB == FALSE) || + (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) */ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Late inclusions. */ +/*===========================================================================*/ + +/* OS Library headers.*/ +#include "chbsem.h" +#include "chmboxes.h" +#include "chmemcore.h" +#include "chmemheaps.h" +#include "chmempools.h" +#include "chobjfifos.h" +#include "chpipes.h" +#include "chfactory.h" + +#endif /* CHLIB_H */ + +/** @} */ diff --git a/os/oslib/include/chmboxes.h b/os/oslib/include/chmboxes.h new file mode 100644 index 000000000..fd76b995a --- /dev/null +++ b/os/oslib/include/chmboxes.h @@ -0,0 +1,209 @@ +/* + 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 chmboxes.h + * @brief Mailboxes macros and structures. + * + * @addtogroup oslib_mailboxes + * @{ + */ + +#ifndef CHMBOXES_H +#define CHMBOXES_H + +#if (CH_CFG_USE_MAILBOXES == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Structure representing a mailbox object. + */ +typedef struct { + msg_t *buffer; /**< @brief Pointer to the mailbox + buffer. */ + msg_t *top; /**< @brief Pointer to the location + after the buffer. */ + msg_t *wrptr; /**< @brief Write pointer. */ + msg_t *rdptr; /**< @brief Read pointer. */ + size_t cnt; /**< @brief Messages in queue. */ + bool reset; /**< @brief True in reset state. */ + threads_queue_t qw; /**< @brief Queued writers. */ + threads_queue_t qr; /**< @brief Queued readers. */ +} mailbox_t; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Data part of a static mailbox initializer. + * @details This macro should be used when statically initializing a + * mailbox that is part of a bigger structure. + * + * @param[in] name the name of the mailbox variable + * @param[in] buffer pointer to the mailbox buffer array of @p msg_t + * @param[in] size number of @p msg_t elements in the buffer array + */ +#define _MAILBOX_DATA(name, buffer, size) { \ + (msg_t *)(buffer), \ + (msg_t *)(buffer) + size, \ + (msg_t *)(buffer), \ + (msg_t *)(buffer), \ + (size_t)0, \ + false, \ + _THREADS_QUEUE_DATA(name.qw), \ + _THREADS_QUEUE_DATA(name.qr), \ +} + +/** + * @brief Static mailbox initializer. + * @details Statically initialized mailboxes require no explicit + * initialization using @p chMBObjectInit(). + * + * @param[in] name the name of the mailbox variable + * @param[in] buffer pointer to the mailbox buffer array of @p msg_t + * @param[in] size number of @p msg_t elements in the buffer array + */ +#define MAILBOX_DECL(name, buffer, size) \ + mailbox_t name = _MAILBOX_DATA(name, buffer, size) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void chMBObjectInit(mailbox_t *mbp, msg_t *buf, size_t n); + void chMBReset(mailbox_t *mbp); + void chMBResetI(mailbox_t *mbp); + msg_t chMBPostTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout); + msg_t chMBPostTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout); + msg_t chMBPostI(mailbox_t *mbp, msg_t msg); + msg_t chMBPostAheadTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout); + msg_t chMBPostAheadTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout); + msg_t chMBPostAheadI(mailbox_t *mbp, msg_t msg); + msg_t chMBFetchTimeout(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout); + msg_t chMBFetchTimeoutS(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout); + msg_t chMBFetchI(mailbox_t *mbp, msg_t *msgp); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Returns the mailbox buffer size as number of messages. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @return The size of the mailbox. + * + * @iclass + */ +static inline size_t chMBGetSizeI(const mailbox_t *mbp) { + + /*lint -save -e9033 [10.8] Perfectly safe pointers + arithmetic.*/ + return (size_t)(mbp->top - mbp->buffer); + /*lint -restore*/ +} + +/** + * @brief Returns the number of used message slots into a mailbox. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @return The number of queued messages. + * + * @iclass + */ +static inline size_t chMBGetUsedCountI(const mailbox_t *mbp) { + + chDbgCheckClassI(); + + return mbp->cnt; +} + +/** + * @brief Returns the number of free message slots into a mailbox. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @return The number of empty message slots. + * + * @iclass + */ +static inline size_t chMBGetFreeCountI(const mailbox_t *mbp) { + + chDbgCheckClassI(); + + return chMBGetSizeI(mbp) - chMBGetUsedCountI(mbp); +} + +/** + * @brief Returns the next message in the queue without removing it. + * @pre A message must be waiting in the queue for this function to work + * or it would return garbage. The correct way to use this macro is + * to use @p chMBGetUsedCountI() and then use this macro, all within + * a lock state. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @return The next message in queue. + * + * @iclass + */ +static inline msg_t chMBPeekI(const mailbox_t *mbp) { + + chDbgCheckClassI(); + + return *mbp->rdptr; +} + +/** + * @brief Terminates the reset state. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * + * @xclass + */ +static inline void chMBResumeX(mailbox_t *mbp) { + + mbp->reset = false; +} + +#endif /* CH_CFG_USE_MAILBOXES == TRUE */ + +#endif /* CHMBOXES_H */ + +/** @} */ diff --git a/os/oslib/include/chmemcore.h b/os/oslib/include/chmemcore.h new file mode 100644 index 000000000..b9b728389 --- /dev/null +++ b/os/oslib/include/chmemcore.h @@ -0,0 +1,198 @@ +/* + 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 chmemcore.h + * @brief Core memory manager macros and structures. + * + * @addtogroup oslib_memcore + * @{ + */ + +#ifndef CHMEMCORE_H +#define CHMEMCORE_H + +#if (CH_CFG_USE_MEMCORE == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#if !defined(CH_CFG_MEMCORE_SIZE) || defined(__DOXYGEN__) +#define CH_CFG_MEMCORE_SIZE 0 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if CH_CFG_MEMCORE_SIZE < 0 +#error "invalid CH_CFG_MEMCORE_SIZE value specified" +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Memory get function. + */ +typedef void *(*memgetfunc_t)(size_t size, unsigned align); + +/** + * @brief Enhanced memory get function. + */ +typedef void *(*memgetfunc2_t)(size_t size, unsigned align, size_t offset); + +/** + * @brief Type of memory core object. + */ +typedef struct { + /** + * @brief Next free address. + */ + uint8_t *nextmem; + /** + * @brief Final address. + */ + uint8_t *endmem; +} memcore_t; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern memcore_t ch_memcore; +#endif + +#ifdef __cplusplus +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); + size_t chCoreGetStatusX(void); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Allocates a memory block. + * @details The allocated block is guaranteed to be properly aligned to the + * specified alignment. + * + * @param[in] size the size of the block to be allocated. + * @param[in] align desired memory alignment + * @return A pointer to the allocated memory block. + * @retval NULL allocation failed, core memory exhausted. + * + * @iclass + */ +static inline void *chCoreAllocAlignedI(size_t size, unsigned align) { + + return chCoreAllocAlignedWithOffsetI(size, align, 0U); +} + +/** + * @brief Allocates a memory block. + * @details The allocated block is guaranteed to be properly aligned to the + * specified alignment. + * + * @param[in] size the size of the block to be allocated + * @param[in] align desired memory alignment + * @return A pointer to the allocated memory block. + * @retval NULL allocation failed, core memory exhausted. + * + * @api + */ +static inline void *chCoreAllocAligned(size_t size, unsigned align) { + void *p; + + chSysLock(); + p = chCoreAllocAlignedWithOffsetI(size, align, 0U); + chSysUnlock(); + + return p; +} + +/** + * @brief Allocates a memory block. + * @details The allocated block is guaranteed to be properly aligned for a + * pointer data type. + * + * @param[in] size the size of the block to be allocated. + * @return A pointer to the allocated memory block. + * @retval NULL allocation failed, core memory exhausted. + * + * @iclass + */ +static inline void *chCoreAllocI(size_t size) { + + return chCoreAllocAlignedWithOffsetI(size, PORT_NATURAL_ALIGN, 0U); +} + +/** + * @brief Allocates a memory block. + * @details The allocated block is guaranteed to be properly aligned for a + * pointer data type. + * + * @param[in] size the size of the block to be allocated. + * @return A pointer to the allocated memory block. + * @retval NULL allocation failed, core memory exhausted. + * + * @api + */ +static inline void *chCoreAlloc(size_t size) { + + return chCoreAllocAlignedWithOffset(size, PORT_NATURAL_ALIGN, 0U); +} + +#endif /* CH_CFG_USE_MEMCORE == TRUE */ + +#endif /* CHMEMCORE_H */ + +/** @} */ diff --git a/os/oslib/include/chmemheaps.h b/os/oslib/include/chmemheaps.h new file mode 100644 index 000000000..f20969a32 --- /dev/null +++ b/os/oslib/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 oslib_memheaps + * @{ + */ + +#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) || defined(__DOXYGEN__) + 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/oslib/include/chmempools.h b/os/oslib/include/chmempools.h new file mode 100644 index 000000000..6e5a45277 --- /dev/null +++ b/os/oslib/include/chmempools.h @@ -0,0 +1,371 @@ +/* + 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 chmempools.h + * @brief Memory Pools macros and structures. + * + * @addtogroup oslib_mempools + * @{ + */ + +#ifndef CHMEMPOOLS_H +#define CHMEMPOOLS_H + +#if (CH_CFG_USE_MEMPOOLS == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if CH_CFG_USE_MEMCORE == FALSE +#error "CH_CFG_USE_MEMPOOLS requires CH_CFG_USE_MEMCORE" +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Memory pool free object header. + */ +struct pool_header { + struct pool_header *next; /**< @brief Pointer to the next pool + header in the list. */ +}; + +/** + * @brief Memory pool descriptor. + */ +typedef struct { + struct pool_header *next; /**< @brief Pointer to the header. */ + size_t object_size; /**< @brief Memory pool objects + size. */ + unsigned align; /**< @brief Required alignment. */ + memgetfunc_t provider; /**< @brief Memory blocks provider + 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 guarding + the memory pool. */ + memory_pool_t pool; /**< @brief The memory pool itself. */ +} guarded_memory_pool_t; +#endif /* CH_CFG_USE_SEMAPHORES == TRUE */ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Data part of a static 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 + * @param[in] align required memory alignment + * @param[in] provider memory provider function for the memory pool + */ +#define _MEMORYPOOL_DATA(name, size, align, provider) \ + {NULL, size, align, provider} + +/** + * @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] align required memory alignment + * @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, align, provider) \ + memory_pool_t name = _MEMORYPOOL_DATA(name, size, align, 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 + * @param[in] align required memory alignment + */ +#define _GUARDEDMEMORYPOOL_DATA(name, size, align) { \ + _SEMAPHORE_DATA(name.sem, (cnt_t)0), \ + _MEMORYPOOL_DATA(NULL, size, align, NULL) \ +} + +/** + * @brief Static guarded memory pool initializer. + * @details Statically initialized guarded memory 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 + * @param[in] align required memory alignment + */ +#define GUARDEDMEMORYPOOL_DECL(name, size, align) \ + guarded_memory_pool_t name = _GUARDEDMEMORYPOOL_DATA(name, size, align) +#endif /* CH_CFG_USE_SEMAPHORES == TRUE */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void chPoolObjectInitAligned(memory_pool_t *mp, size_t size, + unsigned align, memgetfunc_t provider); + void chPoolLoadArray(memory_pool_t *mp, void *p, size_t n); + void *chPoolAllocI(memory_pool_t *mp); + 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 chGuardedPoolObjectInitAligned(guarded_memory_pool_t *gmp, + size_t size, + unsigned align); + void chGuardedPoolLoadArray(guarded_memory_pool_t *gmp, void *p, size_t n); + void *chGuardedPoolAllocTimeoutS(guarded_memory_pool_t *gmp, + sysinterval_t timeout); + void *chGuardedPoolAllocTimeout(guarded_memory_pool_t *gmp, + sysinterval_t timeout); + void chGuardedPoolFree(guarded_memory_pool_t *gmp, void *objp); +#endif +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes an empty memory pool. + * + * @param[out] mp pointer to a @p memory_pool_t structure + * @param[in] size the size of the objects contained in this memory pool, + * the minimum accepted size is the size of a pointer to + * void. + * @param[in] provider memory provider function for the memory pool or + * @p NULL if the pool is not allowed to grow + * automatically + * + * @init + */ +static inline void chPoolObjectInit(memory_pool_t *mp, + size_t size, + memgetfunc_t provider) { + + chPoolObjectInitAligned(mp, size, PORT_NATURAL_ALIGN, provider); +} + +/** + * @brief Adds an object to a memory pool. + * @pre The memory pool must be already been initialized. + * @pre The added object must be of the right size for the specified + * memory pool. + * @pre The added object must be properly aligned. + * @note This function is just an alias for @p chPoolFree() and has been + * added for clarity. + * + * @param[in] mp pointer to a @p memory_pool_t structure + * @param[in] objp the pointer to the object to be added + * + * @api + */ +static inline void chPoolAdd(memory_pool_t *mp, void *objp) { + + chPoolFree(mp, objp); +} + +/** + * @brief Adds an object to a memory pool. + * @pre The memory pool must be already been initialized. + * @pre The added object must be of the right size for the specified + * memory pool. + * @pre The added object must be properly aligned. + * @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 + * @param[in] objp the pointer to the object to be added + * + * @iclass + */ +static inline void chPoolAddI(memory_pool_t *mp, void *objp) { + + chPoolFreeI(mp, objp); +} + +#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__) +/** + * @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 + */ +static inline void chGuardedPoolObjectInit(guarded_memory_pool_t *gmp, + size_t size) { + + chGuardedPoolObjectInitAligned(gmp, size, PORT_NATURAL_ALIGN); +} + +/** + * @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 + * @return The pointer to the allocated object. + * @retval NULL if the pool is empty. + * + * @iclass + */ +static inline void *chGuardedPoolAllocI(guarded_memory_pool_t *gmp) { + void *p; + + p = chPoolAllocI(&gmp->pool); + if (p != NULL) { + chSemFastWaitI(&gmp->sem); + chDbgAssert(chSemGetCounterI(&gmp->sem) >= (cnt_t)0, + "semaphore out of sync"); + } + return p; +} + +/** + * @brief Releases an object into a guarded memory pool. + * @pre The guarded memory pool must already be 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 + */ +static inline 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 already be 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 + * + * @sclass + */ +static inline void chGuardedPoolFreeS(guarded_memory_pool_t *gmp, void *objp) { + + chGuardedPoolFreeI(gmp, objp); + chSchRescheduleS(); +} + +/** + * @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) { + + chGuardedPoolFreeI(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 + * + * @sclass + */ +static inline void chGuardedPoolAddS(guarded_memory_pool_t *gmp, void *objp) { + + chGuardedPoolFreeS(gmp, objp); +} +#endif /* CH_CFG_USE_SEMAPHORES == TRUE */ + +#endif /* CH_CFG_USE_MEMPOOLS == TRUE */ + +#endif /* CHMEMPOOLS_H */ + +/** @} */ diff --git a/os/oslib/include/chobjfifos.h b/os/oslib/include/chobjfifos.h new file mode 100644 index 000000000..c75937eb7 --- /dev/null +++ b/os/oslib/include/chobjfifos.h @@ -0,0 +1,430 @@ +/* + 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 oslib_objects_fifos + * @{ + */ + +#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 chFifoObjectInitAligned(objects_fifo_t *ofp, size_t objsize, + size_t objn, unsigned objalign, + void *objbuf, msg_t *msgbuf) { + + chDbgCheck((objsize >= objalign) && (objsize % objalign == 0U)); + + chGuardedPoolObjectInitAligned(&ofp->free, objsize, objalign); + chGuardedPoolLoadArray(&ofp->free, objbuf, objn); + chMBObjectInit(&ofp->mbx, msgbuf, objn); +} + +/** + * @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] 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, void *objbuf, + msg_t *msgbuf) { + + chFifoObjectInitAligned(ofp, objsize, objn, + PORT_NATURAL_ALIGN, + objbuf, msgbuf); +} + +/** + * @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 + * + * @sclass + */ +static inline void chFifoReturnObjectS(objects_fifo_t *ofp, + void *objp) { + + chGuardedPoolFreeS(&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 Posts an high priority 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 chFifoSendObjectAheadI(objects_fifo_t *ofp, + void *objp) { + msg_t msg; + + msg = chMBPostAheadI(&ofp->mbx, (msg_t)objp); + chDbgAssert(msg == MSG_OK, "post failed"); +} + +/** + * @brief Posts an high priority 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 chFifoSendObjectAheadS(objects_fifo_t *ofp, + void *objp) { + msg_t msg; + + msg = chMBPostAheadTimeoutS(&ofp->mbx, (msg_t)objp, TIME_IMMEDIATE); + chDbgAssert(msg == MSG_OK, "post failed"); +} + +/** + * @brief Posts an high priority 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 chFifoSendObjectAhead(objects_fifo_t *ofp, void *objp) { + + msg_t msg; + + msg = chMBPostAheadTimeout(&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/oslib/include/chpipes.h b/os/oslib/include/chpipes.h new file mode 100644 index 000000000..8bf26c62b --- /dev/null +++ b/os/oslib/include/chpipes.h @@ -0,0 +1,208 @@ +/* + 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 chpipes.h + * @brief Pipes macros and structures. + * + * @addtogroup oslib_pipes + * @{ + */ + +#ifndef CHPIPES_H +#define CHPIPES_H + +#if (CH_CFG_USE_PIPES == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Structure representing a pipe object. + */ +typedef struct { + uint8_t *buffer; /**< @brief Pointer to the pipe + buffer. */ + uint8_t *top; /**< @brief Pointer to the location + after the buffer. */ + uint8_t *wrptr; /**< @brief Write pointer. */ + uint8_t *rdptr; /**< @brief Read pointer. */ + size_t cnt; /**< @brief Bytes in the pipe. */ + bool reset; /**< @brief True if in reset state. */ + thread_reference_t wtr; /**< @brief Waiting writer. */ + thread_reference_t rtr; /**< @brief Waiting reader. */ +#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) + mutex_t cmtx; /**< @brief Common access mutex. */ + mutex_t wmtx; /**< @brief Write access mutex. */ + mutex_t rmtx; /**< @brief Read access mutex. */ +#else + semaphore_t csem; /**< @brief Common access semaphore.*/ + semaphore_t wsem; /**< @brief Write access semaphore. */ + semaphore_t rsem; /**< @brief Read access semaphore. */ +#endif +} pipe_t; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Data part of a static pipe initializer. + * @details This macro should be used when statically initializing a + * pipe that is part of a bigger structure. + * + * @param[in] name the name of the pipe variable + * @param[in] buffer pointer to the pipe buffer array of @p uint8_t + * @param[in] size number of @p uint8_t elements in the buffer array + */ +#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) +#define _PIPE_DATA(name, buffer, size) { \ + (uint8_t *)(buffer), \ + (uint8_t *)(buffer) + size, \ + (uint8_t *)(buffer), \ + (uint8_t *)(buffer), \ + (size_t)0, \ + false, \ + NULL, \ + NULL, \ + _MUTEX_DATA(name.cmtx), \ + _MUTEX_DATA(name.wmtx), \ + _MUTEX_DATA(name.rmtx), \ +} +#else /* CH_CFG_USE_MUTEXES == FALSE */ +#define _PIPE_DATA(name, buffer, size) { \ + (uint8_t *)(buffer), \ + (uint8_t *)(buffer) + size, \ + (uint8_t *)(buffer), \ + (uint8_t *)(buffer), \ + (size_t)0, \ + false, \ + NULL, \ + NULL, \ + _SEMAPHORE_DATA(name.csem, (cnt_t)1), \ + _SEMAPHORE_DATA(name.wsem, (cnt_t)1), \ + _SEMAPHORE_DATA(name.rsem, (cnt_t)1), \ +} +#endif /* CH_CFG_USE_MUTEXES == FALSE */ + +/** + * @brief Static pipe initializer. + * @details Statically initialized pipes require no explicit + * initialization using @p chPipeObjectInit(). + * + * @param[in] name the name of the pipe variable + * @param[in] buffer pointer to the pipe buffer array of @p uint8_t + * @param[in] size number of @p uint8_t elements in the buffer array + */ +#define PIPE_DECL(name, buffer, size) \ + pipe_t name = _PIPE_DATA(name, buffer, size) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void chPipeObjectInit(pipe_t *pp, uint8_t *buf, size_t n); + void chPipeReset(pipe_t *pp); + size_t chPipeWriteTimeout(pipe_t *pp, const uint8_t *bp, + size_t n, sysinterval_t timeout); + size_t chPipeReadTimeout(pipe_t *pp, uint8_t *bp, + size_t n, sysinterval_t timeout); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Returns the pipe buffer size as number of bytes. + * + * @param[in] pp the pointer to an initialized @p pipe_t object + * @return The size of the pipe. + * + * @api + */ +static inline size_t chPipeGetSize(const pipe_t *pp) { + + /*lint -save -e9033 [10.8] Perfectly safe pointers + arithmetic.*/ + return (size_t)(pp->top - pp->buffer); + /*lint -restore*/ +} + +/** + * @brief Returns the number of used byte slots into a pipe. + * + * @param[in] pp the pointer to an initialized @p pipe_t object + * @return The number of queued bytes. + * + * @api + */ +static inline size_t chPipeGetUsedCount(const pipe_t *pp) { + + return pp->cnt; +} + +/** + * @brief Returns the number of free byte slots into a pipe. + * + * @param[in] pp the pointer to an initialized @p pipe_t object + * @return The number of empty byte slots. + * + * @api + */ +static inline size_t chPipeGetFreeCount(const pipe_t *pp) { + + return chPipeGetSize(pp) - chPipeGetUsedCount(pp); +} + +/** + * @brief Terminates the reset state. + * + * @param[in] pp the pointer to an initialized @p pipe_t object + * + * @api + */ +static inline void chPipeResume(pipe_t *pp) { + + pp->reset = false; +} + +#endif /* CH_CFG_USE_PIPES == TRUE */ + +#endif /* CHPIPES_H */ + +/** @} */ diff --git a/os/oslib/oslib.mk b/os/oslib/oslib.mk new file mode 100644 index 000000000..6f837c0b2 --- /dev/null +++ b/os/oslib/oslib.mk @@ -0,0 +1,49 @@ +# List of all the ChibiOS/LIB files, there is no need to remove the files +# from this list, you can disable parts of the kernel by editing chlibconf.h. +ifeq ($(USE_SMART_BUILD),yes) + +# Configuration files directory +ifeq ($(CHCONFDIR),) + ifeq ($(CONFDIR),) + CHCONFDIR = . + else + CHCONFDIR := $(CONFDIR) + endif +endif + +CHLIBCONF := $(strip $(shell cat $(CHCONFDIR)/chconf.h | egrep -e "\#define")) + +LIBSRC := +ifneq ($(findstring CH_CFG_USE_MAILBOXES TRUE,$(CHLIBCONF)),) +LIBSRC += $(CHIBIOS)/os/oslib/src/chmboxes.c +endif +ifneq ($(findstring CH_CFG_USE_MEMCORE TRUE,$(CHLIBCONF)),) +LIBSRC += $(CHIBIOS)/os/oslib/src/chmemcore.c +endif +ifneq ($(findstring CH_CFG_USE_HEAP TRUE,$(CHLIBCONF)),) +LIBSRC += $(CHIBIOS)/os/oslib/src/chmemheaps.c +endif +ifneq ($(findstring CH_CFG_USE_MEMPOOLS TRUE,$(CHLIBCONF)),) +LIBSRC += $(CHIBIOS)/os/oslib/src/chmempools.c +endif +ifneq ($(findstring CH_CFG_USE_PIPES TRUE,$(CHLIBCONF)),) +LIBSRC += $(CHIBIOS)/os/oslib/src/chpipes.c +endif +ifneq ($(findstring CH_CFG_USE_FACTORY TRUE,$(CHLIBCONF)),) +LIBSRC += $(CHIBIOS)/os/oslib/src/chfactory.c +endif +else +LIBSRC := $(CHIBIOS)/os/oslib/src/chmboxes.c \ + $(CHIBIOS)/os/oslib/src/chmemcore.c \ + $(CHIBIOS)/os/oslib/src/chmemheaps.c \ + $(CHIBIOS)/os/oslib/src/chmempools.c \ + $(CHIBIOS)/os/oslib/src/chpipes.c \ + $(CHIBIOS)/os/oslib/src/chfactory.c +endif + +# Required include directories +LIBINC := $(CHIBIOS)/os/oslib/include + +# Shared variables +ALLCSRC += $(LIBSRC) +ALLINC += $(LIBINC) diff --git a/os/oslib/readme.txt b/os/oslib/readme.txt new file mode 100644 index 000000000..d2e0e7222 --- /dev/null +++ b/os/oslib/readme.txt @@ -0,0 +1,2 @@ +All the code contained under ./os/lib are high level RTOS extension modules +compatible with both RT and NIL. \ No newline at end of file diff --git a/os/oslib/src/chfactory.c b/os/oslib/src/chfactory.c new file mode 100644 index 000000000..b8d9bb07d --- /dev/null +++ b/os/oslib/src/chfactory.c @@ -0,0 +1,810 @@ +/* + 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 chfactory.c + * @brief ChibiOS objects factory and registry code. + * + * @addtogroup oslib_objects_factory + * @details The object factory is a subsystem that allows to: + * - Register static objects by name. + * - Dynamically create objects and assign them a name. + * - Retrieve existing objects by name. + * - Free objects by reference. + * . + * Allocated OS objects are handled using a reference counter, only + * when all references have been released then the object memory is + * freed in a pool.
+ * @pre This subsystem requires the @p CH_CFG_USE_MEMCORE and + * @p CH_CFG_USE_MEMPOOLS options to be set to @p TRUE. The + * option @p CH_CFG_USE_HEAP is also required if the support + * for variable length objects is enabled. + * @note Compatible with RT and NIL. + * @{ + */ + +#include + +#include "ch.h" + +#if (CH_CFG_USE_FACTORY == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/* + * Defaults on the best synchronization mechanism available. + */ +#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) +#define F_LOCK() chMtxLock(&ch_factory.mtx) +#define F_UNLOCK() chMtxUnlock(&ch_factory.mtx) +#else +#define F_LOCK() (void) chSemWait(&ch_factory.sem) +#define F_UNLOCK() chSemSignal(&ch_factory.sem) +#endif + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/** + * @brief Factory object static instance. + * @note It is a global object because it could be accessed through + * a specific debugger plugin. + */ +objects_factory_t ch_factory; + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +static inline void dyn_list_init(dyn_list_t *dlp) { + + dlp->next = (dyn_element_t *)dlp; +} + +static dyn_element_t *dyn_list_find(const char *name, dyn_list_t *dlp) { + dyn_element_t *p = dlp->next; + + while (p != (dyn_element_t *)dlp) { + if (strncmp(p->name, name, CH_CFG_FACTORY_MAX_NAMES_LENGTH) == 0) { + return p; + } + p = p->next; + } + + return NULL; +} + +static dyn_element_t *dyn_list_unlink(dyn_element_t *element, + dyn_list_t *dlp) { + dyn_element_t *prev = (dyn_element_t *)dlp; + + /* Scanning the list.*/ + while (prev->next != (dyn_element_t *)dlp) { + if (prev->next == element) { + /* Found.*/ + prev->next = element->next; + return element; + } + + /* Next element in the list.*/ + prev = prev->next; + } + + return NULL; +} + +#if CH_FACTORY_REQUIRES_HEAP || defined(__DOXYGEN__) +static dyn_element_t *dyn_create_object_heap(const char *name, + dyn_list_t *dlp, + size_t size) { + dyn_element_t *dep; + + chDbgCheck(name != NULL); + + /* Checking if an object with this name has already been created.*/ + dep = dyn_list_find(name, dlp); + if (dep != NULL) { + return NULL; + } + + /* Allocating space for the new buffer object.*/ + /*lint -save -e668 [] Lint is confused by the above chDbgCheck() and + incorrectly assumes that strncpy() could receive a NULL pointer.*/ + dep = (dyn_element_t *)chHeapAlloc(NULL, size); + if (dep == NULL) { + return NULL; + } + + /* Initializing object list element.*/ + strncpy(dep->name, name, CH_CFG_FACTORY_MAX_NAMES_LENGTH); + /*lint -restore*/ + dep->refs = (ucnt_t)1; + dep->next = dlp->next; + + /* Updating factory list.*/ + dlp->next = dep; + + return dep; +} + +static void dyn_release_object_heap(dyn_element_t *dep, + dyn_list_t *dlp) { + + chDbgCheck(dep != NULL); + chDbgAssert(dep->refs > (ucnt_t)0, "invalid references number"); + + + dep->refs--; + if (dep->refs == (ucnt_t)0) { + dep = dyn_list_unlink(dep, dlp); + chHeapFree((void *)dep); + } +} +#endif /* CH_FACTORY_REQUIRES_HEAP */ + +#if CH_FACTORY_REQUIRES_POOLS || defined(__DOXYGEN__) +static dyn_element_t *dyn_create_object_pool(const char *name, + dyn_list_t *dlp, + memory_pool_t *mp) { + dyn_element_t *dep; + + chDbgCheck(name != NULL); + + /* Checking if an object object with this name has already been created.*/ + dep = dyn_list_find(name, dlp); + if (dep != NULL) { + return NULL; + } + + /* Allocating space for the new object.*/ + dep = (dyn_element_t *)chPoolAlloc(mp); + if (dep == NULL) { + return NULL; + } + + /* Initializing object list element.*/ + /*lint -save -e668 [] Lint is confused by the above chDbgCheck() and + incorrectly assumes that strncpy() could receive a NULL pointer.*/ + strncpy(dep->name, name, CH_CFG_FACTORY_MAX_NAMES_LENGTH); + /*lint -restore*/ + dep->refs = (ucnt_t)1; + dep->next = dlp->next; + + /* Updating factory list.*/ + dlp->next = (dyn_element_t *)dep; + + return dep; +} + +static void dyn_release_object_pool(dyn_element_t *dep, + dyn_list_t *dlp, + memory_pool_t *mp) { + + chDbgCheck(dep != NULL); + chDbgAssert(dep->refs > (ucnt_t)0, "invalid references number"); + + dep->refs--; + if (dep->refs == (ucnt_t)0) { + dep = dyn_list_unlink(dep, dlp); + chPoolFree(mp, (void *)dep); + } +} +#endif /* CH_FACTORY_REQUIRES_POOLS */ + +static dyn_element_t *dyn_find_object(const char *name, dyn_list_t *dlp) { + dyn_element_t *dep; + + chDbgCheck(name != NULL); + + /* Checking if an object with this name has already been created.*/ + dep = dyn_list_find(name, dlp); + if (dep != NULL) { + /* Increasing references counter.*/ + dep->refs++; + } + + return dep; +} + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the objects factory. + * + * @init + */ +void _factory_init(void) { + +#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) + chMtxObjectInit(&ch_factory.mtx); +#else + chSemObjectInit(&ch_factory.sem, (cnt_t)1); +#endif + +#if CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE + dyn_list_init(&ch_factory.obj_list); + chPoolObjectInit(&ch_factory.obj_pool, + sizeof (registered_object_t), + chCoreAllocAlignedI); +#endif +#if CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE + dyn_list_init(&ch_factory.buf_list); +#endif +#if CH_CFG_FACTORY_SEMAPHORES == TRUE + dyn_list_init(&ch_factory.sem_list); + chPoolObjectInit(&ch_factory.sem_pool, + sizeof (dyn_semaphore_t), + chCoreAllocAlignedI); +#endif +#if CH_CFG_FACTORY_MAILBOXES == TRUE + dyn_list_init(&ch_factory.mbx_list); +#endif +#if CH_CFG_FACTORY_OBJ_FIFOS == TRUE + dyn_list_init(&ch_factory.fifo_list); +#endif +#if CH_CFG_FACTORY_PIPES == TRUE + dyn_list_init(&ch_factory.pipe_list); +#endif +} + +#if (CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE) || defined(__DOXIGEN__) +/** + * @brief Registers a generic object. + * @post A reference to the registered object is returned and the + * reference counter is initialized to one. + * + * @param[in] name name to be assigned to the registered object + * @param[in] objp pointer to the object to be registered + * + * @return The reference to the registered object. + * @retval NULL if the object to be registered cannot be allocated or + * a registered object with the same name exists. + * + * @api + */ +registered_object_t *chFactoryRegisterObject(const char *name, + void *objp) { + registered_object_t *rop; + + F_LOCK(); + + rop = (registered_object_t *)dyn_create_object_pool(name, + &ch_factory.obj_list, + &ch_factory.obj_pool); + if (rop != NULL) { + /* Initializing registered object data.*/ + rop->objp = objp; + } + + F_UNLOCK(); + + return rop; +} + +/** + * @brief Retrieves a registered object. + * @post A reference to the registered object is returned with the + * reference counter increased by one. + * + * @param[in] name name of the registered object + * + * @return The reference to the found registered object. + * @retval NULL if a registered object with the specified name + * does not exist. + * + * @api + */ +registered_object_t *chFactoryFindObject(const char *name) { + registered_object_t *rop; + + F_LOCK(); + + rop = (registered_object_t *)dyn_find_object(name, &ch_factory.obj_list); + + F_UNLOCK(); + + return rop; +} + +/** + * @brief Retrieves a registered object by pointer. + * @post A reference to the registered object is returned with the + * reference counter increased by one. + * + * @param[in] objp pointer to the object to be retrieved + * + * @return The reference to the found registered object. + * @retval NULL if a registered object with the specified pointer + * does not exist. + * + * @api + */ +registered_object_t *chFactoryFindObjectByPointer(void *objp) { + registered_object_t *rop = (registered_object_t *)ch_factory.obj_list.next; + + F_LOCK(); + + while ((void *)rop != (void *)&ch_factory.obj_list) { + if (rop->objp == objp) { + rop->element.refs++; + + F_UNLOCK(); + + return rop; + } + rop = (registered_object_t *)rop->element.next; + } + + F_UNLOCK(); + + return NULL; +} + +/** + * @brief Releases a registered object. + * @details The reference counter of the registered object is decreased + * by one, if reaches zero then the registered object memory + * is freed. + * @note The object itself is not freed, it could be static, only the + * allocated list element is freed. + * + * @param[in] rop registered object reference + * + * @api + */ +void chFactoryReleaseObject(registered_object_t *rop){ + + F_LOCK(); + + dyn_release_object_pool(&rop->element, + &ch_factory.obj_list, + &ch_factory.obj_pool); + + F_UNLOCK(); +} +#endif /* CH_CFG_FACTORY_OBJECTS_REGISTRY == TRUE */ + +#if (CH_CFG_FACTORY_GENERIC_BUFFERS == TRUE) || defined(__DOXIGEN__) +/** + * @brief Creates a generic dynamic buffer object. + * @post A reference to the dynamic buffer object is returned and the + * reference counter is initialized to one. + * @post The dynamic buffer object is filled with zeros. + * + * @param[in] name name to be assigned to the new dynamic buffer object + * @param[in] size payload size of the dynamic buffer object to be created + * + * @return The reference to the created dynamic buffer object. + * @retval NULL if the dynamic buffer object cannot be allocated or + * a dynamic buffer object with the same name exists. + * + * @api + */ +dyn_buffer_t *chFactoryCreateBuffer(const char *name, size_t size) { + dyn_buffer_t *dbp; + + F_LOCK(); + + dbp = (dyn_buffer_t *)dyn_create_object_heap(name, + &ch_factory.buf_list, + size); + if (dbp != NULL) { + /* Initializing buffer object data.*/ + memset((void *)dbp->buffer, 0, size); + } + + F_UNLOCK(); + + return dbp; +} + +/** + * @brief Retrieves a dynamic buffer object. + * @post A reference to the dynamic buffer object is returned with the + * reference counter increased by one. + * + * @param[in] name name of the dynamic buffer object + * + * @return The reference to the found dynamic buffer object. + * @retval NULL if a dynamic buffer object with the specified name + * does not exist. + * + * @api + */ +dyn_buffer_t *chFactoryFindBuffer(const char *name) { + dyn_buffer_t *dbp; + + F_LOCK(); + + dbp = (dyn_buffer_t *)dyn_find_object(name, &ch_factory.buf_list); + + F_UNLOCK(); + + return dbp; +} + +/** + * @brief Releases a dynamic buffer object. + * @details The reference counter of the dynamic buffer object is decreased + * by one, if reaches zero then the dynamic buffer object memory + * is freed. + * + * @param[in] dbp dynamic buffer object reference + * + * @api + */ +void chFactoryReleaseBuffer(dyn_buffer_t *dbp) { + + F_LOCK(); + + dyn_release_object_heap(&dbp->element, &ch_factory.buf_list); + + F_UNLOCK(); +} +#endif /* CH_CFG_FACTORY_GENERIC_BUFFERS = TRUE */ + +#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXIGEN__) +/** + * @brief Creates a dynamic semaphore object. + * @post A reference to the dynamic semaphore object is returned and the + * reference counter is initialized to one. + * @post The dynamic semaphore object is initialized and ready to use. + * + * @param[in] name name to be assigned to the new dynamic semaphore object + * @param[in] n dynamic semaphore object counter initialization value + * + * @return The reference to the created dynamic semaphore object. + * @retval NULL if the dynamic semaphore object cannot be allocated or + * a dynamic semaphore with the same name exists. + * + * @api + */ +dyn_semaphore_t *chFactoryCreateSemaphore(const char *name, cnt_t n) { + dyn_semaphore_t *dsp; + + F_LOCK(); + + dsp = (dyn_semaphore_t *)dyn_create_object_pool(name, + &ch_factory.sem_list, + &ch_factory.sem_pool); + if (dsp != NULL) { + /* Initializing semaphore object dataa.*/ + chSemObjectInit(&dsp->sem, n); + } + + F_UNLOCK(); + + return dsp; +} + +/** + * @brief Retrieves a dynamic semaphore object. + * @post A reference to the dynamic semaphore object is returned with the + * reference counter increased by one. + * + * @param[in] name name of the dynamic semaphore object + * + * @return The reference to the found dynamic semaphore object. + * @retval NULL if a dynamic semaphore object with the specified name + * does not exist. + * + * @api + */ +dyn_semaphore_t *chFactoryFindSemaphore(const char *name) { + dyn_semaphore_t *dsp; + + F_LOCK(); + + dsp = (dyn_semaphore_t *)dyn_find_object(name, &ch_factory.sem_list); + + F_UNLOCK(); + + return dsp; +} + +/** + * @brief Releases a dynamic semaphore object. + * @details The reference counter of the dynamic semaphore object is decreased + * by one, if reaches zero then the dynamic semaphore object memory + * is freed. + * + * @param[in] dsp dynamic semaphore object reference + * + * @api + */ +void chFactoryReleaseSemaphore(dyn_semaphore_t *dsp) { + + F_LOCK(); + + dyn_release_object_pool(&dsp->element, + &ch_factory.sem_list, + &ch_factory.sem_pool); + + F_UNLOCK(); +} +#endif /* CH_CFG_FACTORY_SEMAPHORES = TRUE */ + +#if (CH_CFG_FACTORY_MAILBOXES == TRUE) || defined(__DOXIGEN__) +/** + * @brief Creates a dynamic mailbox object. + * @post A reference to the dynamic mailbox object is returned and the + * reference counter is initialized to one. + * @post The dynamic mailbox object is initialized and ready to use. + * + * @param[in] name name to be assigned to the new dynamic mailbox object + * @param[in] n mailbox buffer size as number of messages + * + * @return The reference to the created dynamic mailbox object. + * @retval NULL if the dynamic mailbox object cannot be allocated or + * a dynamic mailbox object with the same name exists. + * + * @api + */ +dyn_mailbox_t *chFactoryCreateMailbox(const char *name, size_t n) { + dyn_mailbox_t *dmp; + + F_LOCK(); + + dmp = (dyn_mailbox_t *)dyn_create_object_heap(name, + &ch_factory.mbx_list, + sizeof (dyn_mailbox_t) + + (n * sizeof (msg_t))); + if (dmp != NULL) { + /* Initializing mailbox object data.*/ + chMBObjectInit(&dmp->mbx, dmp->msgbuf, n); + } + + F_UNLOCK(); + + return dmp; +} + +/** + * @brief Retrieves a dynamic mailbox object. + * @post A reference to the dynamic mailbox object is returned with the + * reference counter increased by one. + * + * @param[in] name name of the dynamic mailbox object + * + * @return The reference to the found dynamic mailbox object. + * @retval NULL if a dynamic mailbox object with the specified name + * does not exist. + * + * @api + */ +dyn_mailbox_t *chFactoryFindMailbox(const char *name) { + dyn_mailbox_t *dmp; + + F_LOCK(); + + dmp = (dyn_mailbox_t *)dyn_find_object(name, &ch_factory.mbx_list); + + F_UNLOCK(); + + return dmp; +} + +/** + * @brief Releases a dynamic mailbox object. + * @details The reference counter of the dynamic mailbox object is decreased + * by one, if reaches zero then the dynamic mailbox object memory + * is freed. + * + * @param[in] dmp dynamic mailbox object reference + * + * @api + */ +void chFactoryReleaseMailbox(dyn_mailbox_t *dmp) { + + F_LOCK(); + + dyn_release_object_heap(&dmp->element, &ch_factory.mbx_list); + + F_UNLOCK(); +} +#endif /* CH_CFG_FACTORY_MAILBOXES = TRUE */ + +#if (CH_CFG_FACTORY_OBJ_FIFOS == TRUE) || defined(__DOXIGEN__) +/** + * @brief Creates a dynamic "objects FIFO" object. + * @post A reference to the dynamic "objects FIFO" object is returned and + * the reference counter is initialized to one. + * @post The dynamic "objects FIFO" object is initialized and ready to use. + * + * @param[in] name name to be assigned to the new dynamic "objects FIFO" + * object + * @param[in] objsize size of objects + * @param[in] objn number of objects available + * @param[in] objalign required objects alignment + * @return The reference to the created dynamic "objects FIFO" + * object. + * @retval NULL if the dynamic "objects FIFO" object cannot be + * allocated or a dynamic "objects FIFO" object with + * the same name exists. + * + * @api + */ +dyn_objects_fifo_t *chFactoryCreateObjectsFIFO(const char *name, + size_t objsize, + size_t objn, + unsigned objalign) { + dyn_objects_fifo_t *dofp; + + F_LOCK(); + + dofp = (dyn_objects_fifo_t *)dyn_create_object_heap(name, + &ch_factory.fifo_list, + sizeof (dyn_objects_fifo_t) + + (objn * sizeof (msg_t)) + + (objn * objsize)); + if (dofp != NULL) { + /* Initializing mailbox object data.*/ + chFifoObjectInitAligned(&dofp->fifo, objsize, objn, objalign, + (void *)&dofp->msgbuf[objn], dofp->msgbuf); + } + + F_UNLOCK(); + + return dofp; +} + +/** + * @brief Retrieves a dynamic "objects FIFO" object. + * @post A reference to the dynamic "objects FIFO" object is returned with + * the reference counter increased by one. + * + * @param[in] name name of the dynamic "objects FIFO" object + * + * @return The reference to the found dynamic "objects FIFO" + * object. + * @retval NULL if a dynamic "objects FIFO" object with the specified + * name does not exist. + * + * @api + */ +dyn_objects_fifo_t *chFactoryFindObjectsFIFO(const char *name) { + dyn_objects_fifo_t *dofp; + + F_LOCK(); + + dofp = (dyn_objects_fifo_t *)dyn_find_object(name, &ch_factory.fifo_list); + + F_UNLOCK(); + + return dofp; +} + +/** + * @brief Releases a dynamic "objects FIFO" object. + * @details The reference counter of the dynamic "objects FIFO" object is + * decreased by one, if reaches zero then the dynamic "objects FIFO" + * object memory is freed. + * + * @param[in] dofp dynamic "objects FIFO" object reference + * + * @api + */ +void chFactoryReleaseObjectsFIFO(dyn_objects_fifo_t *dofp) { + + F_LOCK(); + + dyn_release_object_heap(&dofp->element, &ch_factory.fifo_list); + + F_UNLOCK(); +} +#endif /* CH_CFG_FACTORY_OBJ_FIFOS = TRUE */ + +#if (CH_CFG_FACTORY_PIPES == TRUE) || defined(__DOXIGEN__) +/** + * @brief Creates a dynamic pipe object. + * @post A reference to the dynamic pipe object is returned and + * the reference counter is initialized to one. + * @post The dynamic pipe object is initialized and ready to use. + * + * @param[in] name name to be assigned to the new dynamic pipe + * object + * @param[in] size pipe buffer size + * @return The reference to the created dynamic pipe + * object. + * @retval NULL if the dynamic pipe object cannot be + * allocated or a dynamic pipe object with + * the same name exists. + * + * @api + */ +dyn_pipe_t *chFactoryCreatePipe(const char *name, size_t size) { + dyn_pipe_t *dpp; + + F_LOCK(); + + dpp = (dyn_pipe_t *)dyn_create_object_heap(name, + &ch_factory.pipe_list, + sizeof (dyn_pipe_t) + size); + if (dpp != NULL) { + /* Initializing mailbox object data.*/ + chPipeObjectInit(&dpp->pipe, dpp->buffer, size); + } + + F_UNLOCK(); + + return dpp; +} + +/** + * @brief Retrieves a dynamic pipe object. + * @post A reference to the dynamic pipe object is returned with + * the reference counter increased by one. + * + * @param[in] name name of the pipe object + * + * @return The reference to the found dynamic pipe + * object. + * @retval NULL if a dynamic pipe object with the specified + * name does not exist. + * + * @api + */ +dyn_pipe_t *chFactoryFindPipe(const char *name) { + dyn_pipe_t *dpp; + + F_LOCK(); + + dpp = (dyn_pipe_t *)dyn_find_object(name, &ch_factory.pipe_list); + + F_UNLOCK(); + + return dpp; +} + +/** + * @brief Releases a dynamic pipe object. + * @details The reference counter of the dynamic pipe object is + * decreased by one, if reaches zero then the dynamic pipe + * object memory is freed. + * + * @param[in] dpp dynamic pipe object reference + * + * @api + */ +void chFactoryReleasePipe(dyn_pipe_t *dpp) { + + F_LOCK(); + + dyn_release_object_heap(&dpp->element, &ch_factory.pipe_list); + + F_UNLOCK(); +} +#endif /* CH_CFG_FACTORY_PIPES = TRUE */ + +#endif /* CH_CFG_USE_FACTORY == TRUE */ + +/** @} */ diff --git a/os/oslib/src/chmboxes.c b/os/oslib/src/chmboxes.c new file mode 100644 index 000000000..1b23bf2e0 --- /dev/null +++ b/os/oslib/src/chmboxes.c @@ -0,0 +1,522 @@ +/* + 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 chmboxes.c + * @brief Mailboxes code. + * + * @addtogroup oslib_mailboxes + * @details Asynchronous messages. + *

Operation mode

+ * A mailbox is an asynchronous communication mechanism.
+ * Operations defined for mailboxes: + * - Post: Posts a message on the mailbox in FIFO order. + * - Post Ahead: Posts a message on the mailbox with urgent + * priority. + * - Fetch: A message is fetched from the mailbox and removed + * from the queue. + * - Reset: The mailbox is emptied and all the stored messages + * are lost. + * . + * A message is a variable of type msg_t that is guaranteed to have + * the same size of and be compatible with (data) pointers (anyway an + * explicit cast is needed). + * If larger messages need to be exchanged then a pointer to a + * structure can be posted in the mailbox but the posting side has + * no predefined way to know when the message has been processed. A + * possible approach is to allocate memory (from a memory pool for + * example) from the posting side and free it on the fetching side. + * Another approach is to set a "done" flag into the structure pointed + * by the message. + * @pre In order to use the mailboxes APIs the @p CH_CFG_USE_MAILBOXES + * option must be enabled in @p chconf.h. + * @note Compatible with RT and NIL. + * @{ + */ + +#include "ch.h" + +#if (CH_CFG_USE_MAILBOXES == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes a @p mailbox_t object. + * + * @param[out] mbp the pointer to the @p mailbox_t structure to be + * initialized + * @param[in] buf pointer to the messages buffer as an array of @p msg_t + * @param[in] n number of elements in the buffer array + * + * @init + */ +void chMBObjectInit(mailbox_t *mbp, msg_t *buf, size_t n) { + + chDbgCheck((mbp != NULL) && (buf != NULL) && (n > (size_t)0)); + + mbp->buffer = buf; + mbp->rdptr = buf; + mbp->wrptr = buf; + mbp->top = &buf[n]; + mbp->cnt = (size_t)0; + mbp->reset = false; + chThdQueueObjectInit(&mbp->qw); + chThdQueueObjectInit(&mbp->qr); +} + +/** + * @brief Resets a @p mailbox_t object. + * @details All the waiting threads are resumed with status @p MSG_RESET and + * the queued messages are lost. + * @post The mailbox is in reset state, all operations will fail and + * return @p MSG_RESET until the mailbox is enabled again using + * @p chMBResumeX(). + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * + * @api + */ +void chMBReset(mailbox_t *mbp) { + + chSysLock(); + chMBResetI(mbp); + chSchRescheduleS(); + chSysUnlock(); +} + +/** + * @brief Resets a @p mailbox_t object. + * @details All the waiting threads are resumed with status @p MSG_RESET and + * the queued messages are lost. + * @post The mailbox is in reset state, all operations will fail and + * return @p MSG_RESET until the mailbox is enabled again using + * @p chMBResumeX(). + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * + * @api + */ +void chMBResetI(mailbox_t *mbp) { + + chDbgCheckClassI(); + chDbgCheck(mbp != NULL); + + mbp->wrptr = mbp->buffer; + mbp->rdptr = mbp->buffer; + mbp->cnt = (size_t)0; + mbp->reset = true; + chThdDequeueAllI(&mbp->qw, MSG_RESET); + chThdDequeueAllI(&mbp->qr, MSG_RESET); +} + +/** + * @brief Posts a message into a mailbox. + * @details The invoking thread waits until a empty slot in the mailbox becomes + * available or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @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 a message has been correctly posted. + * @retval MSG_RESET if the mailbox has been reset. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @api + */ +msg_t chMBPostTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) { + msg_t rdymsg; + + chSysLock(); + rdymsg = chMBPostTimeoutS(mbp, msg, timeout); + chSysUnlock(); + + return rdymsg; +} + +/** + * @brief Posts a message into a mailbox. + * @details The invoking thread waits until a empty slot in the mailbox becomes + * available or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @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 a message has been correctly posted. + * @retval MSG_RESET if the mailbox has been reset. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @sclass + */ +msg_t chMBPostTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) { + msg_t rdymsg; + + chDbgCheckClassS(); + chDbgCheck(mbp != NULL); + + do { + /* If the mailbox is in reset state then returns immediately.*/ + if (mbp->reset) { + return MSG_RESET; + } + + /* Is there a free message slot in queue? if so then post.*/ + if (chMBGetFreeCountI(mbp) > (size_t)0) { + *mbp->wrptr++ = msg; + if (mbp->wrptr >= mbp->top) { + mbp->wrptr = mbp->buffer; + } + mbp->cnt++; + + /* If there is a reader waiting then makes it ready.*/ + chThdDequeueNextI(&mbp->qr, MSG_OK); + chSchRescheduleS(); + + return MSG_OK; + } + + /* No space in the queue, waiting for a slot to become available.*/ + rdymsg = chThdEnqueueTimeoutS(&mbp->qw, timeout); + } while (rdymsg == MSG_OK); + + return rdymsg; +} + +/** + * @brief Posts a message into a mailbox. + * @details This variant is non-blocking, the function returns a timeout + * condition if the queue is full. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @return The operation status. + * @retval MSG_OK if a message has been correctly posted. + * @retval MSG_RESET if the mailbox has been reset. + * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be + * posted. + * + * @iclass + */ +msg_t chMBPostI(mailbox_t *mbp, msg_t msg) { + + chDbgCheckClassI(); + chDbgCheck(mbp != NULL); + + /* If the mailbox is in reset state then returns immediately.*/ + if (mbp->reset) { + return MSG_RESET; + } + + /* Is there a free message slot in queue? if so then post.*/ + if (chMBGetFreeCountI(mbp) > (size_t)0) { + *mbp->wrptr++ = msg; + if (mbp->wrptr >= mbp->top) { + mbp->wrptr = mbp->buffer; + } + mbp->cnt++; + + /* If there is a reader waiting then makes it ready.*/ + chThdDequeueNextI(&mbp->qr, MSG_OK); + + return MSG_OK; + } + + /* No space, immediate timeout.*/ + return MSG_TIMEOUT; +} + +/** + * @brief Posts an high priority message into a mailbox. + * @details The invoking thread waits until a empty slot in the mailbox becomes + * available or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @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 a message has been correctly posted. + * @retval MSG_RESET if the mailbox has been reset. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @api + */ +msg_t chMBPostAheadTimeout(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) { + msg_t rdymsg; + + chSysLock(); + rdymsg = chMBPostAheadTimeoutS(mbp, msg, timeout); + chSysUnlock(); + + return rdymsg; +} + +/** + * @brief Posts an high priority message into a mailbox. + * @details The invoking thread waits until a empty slot in the mailbox becomes + * available or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @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 a message has been correctly posted. + * @retval MSG_RESET if the mailbox has been reset. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @sclass + */ +msg_t chMBPostAheadTimeoutS(mailbox_t *mbp, msg_t msg, sysinterval_t timeout) { + msg_t rdymsg; + + chDbgCheckClassS(); + chDbgCheck(mbp != NULL); + + do { + /* If the mailbox is in reset state then returns immediately.*/ + if (mbp->reset) { + return MSG_RESET; + } + + /* Is there a free message slot in queue? if so then post.*/ + if (chMBGetFreeCountI(mbp) > (size_t)0) { + if (--mbp->rdptr < mbp->buffer) { + mbp->rdptr = mbp->top - 1; + } + *mbp->rdptr = msg; + mbp->cnt++; + + /* If there is a reader waiting then makes it ready.*/ + chThdDequeueNextI(&mbp->qr, MSG_OK); + chSchRescheduleS(); + + return MSG_OK; + } + + /* No space in the queue, waiting for a slot to become available.*/ + rdymsg = chThdEnqueueTimeoutS(&mbp->qw, timeout); + } while (rdymsg == MSG_OK); + + return rdymsg; +} + +/** + * @brief Posts an high priority message into a mailbox. + * @details This variant is non-blocking, the function returns a timeout + * condition if the queue is full. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @return The operation status. + * @retval MSG_OK if a message has been correctly posted. + * @retval MSG_RESET if the mailbox has been reset. + * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be + * posted. + * + * @iclass + */ +msg_t chMBPostAheadI(mailbox_t *mbp, msg_t msg) { + + chDbgCheckClassI(); + chDbgCheck(mbp != NULL); + + /* If the mailbox is in reset state then returns immediately.*/ + if (mbp->reset) { + return MSG_RESET; + } + + /* Is there a free message slot in queue? if so then post.*/ + if (chMBGetFreeCountI(mbp) > (size_t)0) { + if (--mbp->rdptr < mbp->buffer) { + mbp->rdptr = mbp->top - 1; + } + *mbp->rdptr = msg; + mbp->cnt++; + + /* If there is a reader waiting then makes it ready.*/ + chThdDequeueNextI(&mbp->qr, MSG_OK); + + return MSG_OK; + } + + /* No space, immediate timeout.*/ + return MSG_TIMEOUT; +} + +/** + * @brief Retrieves a message from a mailbox. + * @details The invoking thread waits until a message is posted in the mailbox + * or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[out] msgp pointer to a message variable for the received message + * @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 a message has been correctly fetched. + * @retval MSG_RESET if the mailbox has been reset. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @api + */ +msg_t chMBFetchTimeout(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout) { + msg_t rdymsg; + + chSysLock(); + rdymsg = chMBFetchTimeoutS(mbp, msgp, timeout); + chSysUnlock(); + + return rdymsg; +} + +/** + * @brief Retrieves a message from a mailbox. + * @details The invoking thread waits until a message is posted in the mailbox + * or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[out] msgp pointer to a message variable for the received message + * @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 a message has been correctly fetched. + * @retval MSG_RESET if the mailbox has been reset. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @sclass + */ +msg_t chMBFetchTimeoutS(mailbox_t *mbp, msg_t *msgp, sysinterval_t timeout) { + msg_t rdymsg; + + chDbgCheckClassS(); + chDbgCheck((mbp != NULL) && (msgp != NULL)); + + do { + /* If the mailbox is in reset state then returns immediately.*/ + if (mbp->reset) { + return MSG_RESET; + } + + /* Is there a message in queue? if so then fetch.*/ + if (chMBGetUsedCountI(mbp) > (size_t)0) { + *msgp = *mbp->rdptr++; + if (mbp->rdptr >= mbp->top) { + mbp->rdptr = mbp->buffer; + } + mbp->cnt--; + + /* If there is a writer waiting then makes it ready.*/ + chThdDequeueNextI(&mbp->qw, MSG_OK); + chSchRescheduleS(); + + return MSG_OK; + } + + /* No message in the queue, waiting for a message to become available.*/ + rdymsg = chThdEnqueueTimeoutS(&mbp->qr, timeout); + } while (rdymsg == MSG_OK); + + return rdymsg; +} + +/** + * @brief Retrieves a message from a mailbox. + * @details This variant is non-blocking, the function returns a timeout + * condition if the queue is empty. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[out] msgp pointer to a message variable for the received message + * @return The operation status. + * @retval MSG_OK if a message has been correctly fetched. + * @retval MSG_RESET if the mailbox has been reset. + * @retval MSG_TIMEOUT if the mailbox is empty and a message cannot be + * fetched. + * + * @iclass + */ +msg_t chMBFetchI(mailbox_t *mbp, msg_t *msgp) { + + chDbgCheckClassI(); + chDbgCheck((mbp != NULL) && (msgp != NULL)); + + /* If the mailbox is in reset state then returns immediately.*/ + if (mbp->reset) { + return MSG_RESET; + } + + /* Is there a message in queue? if so then fetch.*/ + if (chMBGetUsedCountI(mbp) > (size_t)0) { + *msgp = *mbp->rdptr++; + if (mbp->rdptr >= mbp->top) { + mbp->rdptr = mbp->buffer; + } + mbp->cnt--; + + /* If there is a writer waiting then makes it ready.*/ + chThdDequeueNextI(&mbp->qw, MSG_OK); + + return MSG_OK; + } + + /* No message, immediate timeout.*/ + return MSG_TIMEOUT; +} +#endif /* CH_CFG_USE_MAILBOXES == TRUE */ + +/** @} */ diff --git a/os/oslib/src/chmemcore.c b/os/oslib/src/chmemcore.c new file mode 100644 index 000000000..5dc3ce446 --- /dev/null +++ b/os/oslib/src/chmemcore.c @@ -0,0 +1,175 @@ +/* + 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 chmemcore.c + * @brief Core memory manager code. + * + * @addtogroup oslib_memcore + * @details Core Memory Manager related APIs and services. + *

Operation mode

+ * The core memory manager is a simplified allocator that only + * allows to allocate memory blocks without the possibility to + * free them.
+ * This allocator is meant as a memory blocks provider for the + * other allocators such as: + * - C-Runtime allocator (through a compiler specific adapter module). + * - Heap allocator (see @ref oslib_memheaps). + * - Memory pools allocator (see @ref oslib_mempools). + * . + * By having a centralized memory provider the various allocators + * can coexist and share the main memory.
+ * This allocator, alone, is also useful for very simple + * applications that just require a simple way to get memory + * blocks. + * @pre In order to use the core memory manager APIs the @p CH_CFG_USE_MEMCORE + * option must be enabled in @p chconf.h. + * @note Compatible with RT and NIL. + * @{ + */ + +#include "ch.h" + +#if (CH_CFG_USE_MEMCORE == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/** + * @brief Memory core descriptor. + */ +memcore_t ch_memcore; + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level memory manager initialization. + * + * @notapi + */ +void _core_init(void) { +#if CH_CFG_MEMCORE_SIZE == 0 + extern uint8_t __heap_base__[]; + extern uint8_t __heap_end__[]; + + /*lint -save -e9033 [10.8] Required cast operations.*/ + ch_memcore.nextmem = __heap_base__; + ch_memcore.endmem = __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]; +#endif +} + +/** + * @brief Allocates a memory block. + * @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 *chCoreAllocAlignedWithOffsetI(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); + next = p + size; + + /* Considering also the case where there is numeric overflow.*/ + if ((next > ch_memcore.endmem) || (next < ch_memcore.nextmem)) { + return NULL; + } + + ch_memcore.nextmem = next; + + return p; +} + +/** + * @brief Allocates a memory block. + * @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 *chCoreAllocAlignedWithOffset(size_t size, + unsigned align, + size_t offset) { + void *p; + + chSysLock(); + p = chCoreAllocAlignedWithOffsetI(size, align, offset); + chSysUnlock(); + + return p; +} + +/** + * @brief Core memory status. + * + * @return The size, in bytes, of the free core memory. + * + * @xclass + */ +size_t chCoreGetStatusX(void) { + + /*lint -save -e9033 [10.8] The cast is safe.*/ + return (size_t)(ch_memcore.endmem - ch_memcore.nextmem); + /*lint -restore*/ +} +#endif /* CH_CFG_USE_MEMCORE == TRUE */ + +/** @} */ diff --git a/os/oslib/src/chmemheaps.c b/os/oslib/src/chmemheaps.c new file mode 100644 index 000000000..a03bde2e7 --- /dev/null +++ b/os/oslib/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 oslib_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 * 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 @p NULL + * @param[in] largestp pointer to a variable that will receive the largest + * free free block found space or @p 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/oslib/src/chmempools.c b/os/oslib/src/chmempools.c new file mode 100644 index 000000000..996b66329 --- /dev/null +++ b/os/oslib/src/chmempools.c @@ -0,0 +1,336 @@ +/* + 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 chmempools.c + * @brief Memory Pools code. + * + * @addtogroup oslib_mempools + * @details Memory Pools related APIs and services. + *

Operation mode

+ * The Memory Pools APIs allow to allocate/free fixed size objects in + * constant time and reliably without memory fragmentation + * problems.
+ * Memory Pools do not enforce any alignment constraint on the + * contained object however the objects must be properly aligned + * to contain a pointer to void. + * @pre In order to use the memory pools APIs the @p CH_CFG_USE_MEMPOOLS option + * must be enabled in @p chconf.h. + * @note Compatible with RT and NIL. + * @{ + */ + +#include "ch.h" + +#if (CH_CFG_USE_MEMPOOLS == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes an empty memory pool. + * + * @param[out] mp pointer to a @p memory_pool_t structure + * @param[in] size the size of the objects contained in this memory pool, + * the minimum accepted size is the size of a pointer to + * void. + * @param[in] align required memory alignment + * @param[in] provider memory provider function for the memory pool or + * @p NULL if the pool is not allowed to grow + * automatically + * + * @init + */ +void chPoolObjectInitAligned(memory_pool_t *mp, size_t size, + unsigned align, memgetfunc_t provider) { + + chDbgCheck((mp != NULL) && + (size >= sizeof(void *)) && + (align >= PORT_NATURAL_ALIGN) && + MEM_IS_VALID_ALIGNMENT(align)); + + mp->next = NULL; + mp->object_size = size; + mp->align = align; + mp->provider = provider; +} + +/** + * @brief Loads a memory pool with an array of static objects. + * @pre The memory pool must already be initialized. + * @pre The array elements must be of the right size for the specified + * memory pool. + * @pre The array elements size must be a multiple of the alignment + * requirement for the pool. + * @post The memory pool contains the elements of the input array. + * + * @param[in] mp pointer to a @p memory_pool_t structure + * @param[in] p pointer to the array first element + * @param[in] n number of elements in the array + * + * @api + */ +void chPoolLoadArray(memory_pool_t *mp, void *p, size_t n) { + + chDbgCheck((mp != NULL) && (n != 0U)); + + while (n != 0U) { + chPoolAdd(mp, p); + /*lint -save -e9087 [11.3] Safe cast.*/ + p = (void *)(((uint8_t *)p) + mp->object_size); + /*lint -restore*/ + n--; + } +} + +/** + * @brief Allocates an object from a memory pool. + * @pre The memory pool must already be initialized. + * + * @param[in] mp pointer to a @p memory_pool_t structure + * @return The pointer to the allocated object. + * @retval NULL if pool is empty. + * + * @iclass + */ +void *chPoolAllocI(memory_pool_t *mp) { + void *objp; + + chDbgCheckClassI(); + chDbgCheck(mp != NULL); + + objp = mp->next; + /*lint -save -e9013 [15.7] There is no else because it is not needed.*/ + if (objp != NULL) { + mp->next = mp->next->next; + } + else if (mp->provider != NULL) { + objp = mp->provider(mp->object_size, mp->align); + + chDbgAssert(MEM_IS_ALIGNED(objp, mp->align), + "returned object not aligned"); + } + /*lint -restore*/ + + return objp; +} + +/** + * @brief Allocates an object from a memory pool. + * @pre The memory pool must already be initialized. + * + * @param[in] mp pointer to a @p memory_pool_t structure + * @return The pointer to the allocated object. + * @retval NULL if pool is empty. + * + * @api + */ +void *chPoolAlloc(memory_pool_t *mp) { + void *objp; + + chSysLock(); + objp = chPoolAllocI(mp); + chSysUnlock(); + + return objp; +} + +/** + * @brief Releases an object into a memory pool. + * @pre The memory pool must already be initialized. + * @pre The freed object must be of the right size for the specified + * memory pool. + * @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 + * + * @iclass + */ +void chPoolFreeI(memory_pool_t *mp, void *objp) { + struct pool_header *php = objp; + + chDbgCheckClassI(); + chDbgCheck((mp != NULL) && + (objp != NULL) && + MEM_IS_ALIGNED(objp, mp->align)); + + php->next = mp->next; + mp->next = php; +} + +/** + * @brief Releases an object into a memory pool. + * @pre The memory pool must already be initialized. + * @pre The freed object must be of the right size for the specified + * memory pool. + * @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 + * + * @api + */ +void chPoolFree(memory_pool_t *mp, void *objp) { + + chSysLock(); + chPoolFreeI(mp, objp); + chSysUnlock(); +} + +#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__) +/** + * @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. + * @param[in] align required memory alignment + * + * @init + */ +void chGuardedPoolObjectInitAligned(guarded_memory_pool_t *gmp, + size_t size, + unsigned align) { + + chPoolObjectInitAligned(&gmp->pool, size, align, 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 already be 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 already be 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, + sysinterval_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 already be 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, + sysinterval_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 already be 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 */ + +/** @} */ diff --git a/os/oslib/src/chpipes.c b/os/oslib/src/chpipes.c new file mode 100644 index 000000000..6f6e8a30f --- /dev/null +++ b/os/oslib/src/chpipes.c @@ -0,0 +1,388 @@ +/* + 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 chpipes.c + * @brief Pipes code. + * @details Byte pipes. + *

Operation mode

+ * A pipe is an asynchronous communication mechanism.
+ * Operations defined for mailboxes: + * - Write: Writes a buffer of data in the pipe in FIFO order. + * - Read: A buffer of data is read from the read and removed. + * - Reset: The pipe is emptied and all the stored data + * is lost. + * . + * @pre In order to use the pipes APIs the @p CH_CFG_USE_PIPES + * option must be enabled in @p chconf.h. + * @note Compatible with RT and NIL. + * + * @addtogroup oslib_pipes + * @{ + */ + +#include + +#include "ch.h" + +#if (CH_CFG_USE_PIPES == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/* + * Defaults on the best synchronization mechanism available. + */ +#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) +#define PC_INIT(p) chMtxObjectInit(&(p)->cmtx) +#define PC_LOCK(p) chMtxLock(&(p)->cmtx) +#define PC_UNLOCK(p) chMtxUnlock(&(p)->cmtx) +#define PW_INIT(p) chMtxObjectInit(&(p)->wmtx) +#define PW_LOCK(p) chMtxLock(&(p)->wmtx) +#define PW_UNLOCK(p) chMtxUnlock(&(p)->wmtx) +#define PR_INIT(p) chMtxObjectInit(&(p)->rmtx) +#define PR_LOCK(p) chMtxLock(&(p)->rmtx) +#define PR_UNLOCK(p) chMtxUnlock(&(p)->rmtx) +#else +#define PC_INIT(p) chSemObjectInit(&(p)->csem, (cnt_t)1) +#define PC_LOCK(p) (void) chSemWait(&(p)->csem) +#define PC_UNLOCK(p) chSemSignal(&(p)->csem) +#define PW_INIT(p) chSemObjectInit(&(p)->wsem, (cnt_t)1) +#define PW_LOCK(p) (void) chSemWait(&(p)->wsem) +#define PW_UNLOCK(p) chSemSignal(&(p)->wsem) +#define PR_INIT(p) chSemObjectInit(&(p)->rsem, (cnt_t)1) +#define PR_LOCK(p) (void) chSemWait(&(p)->rsem) +#define PR_UNLOCK(p) chSemSignal(&(p)->rsem) +#endif + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/** + * @brief Non-blocking pipe write. + * @details The function writes data from a buffer to a pipe. The + * operation completes when the specified amount of data has been + * transferred or when the pipe buffer has been filled. + * + * @param[in] pp the pointer to an initialized @p pipe_t object + * @param[in] bp pointer to the data buffer + * @param[in] n the maximum amount of data to be transferred, the + * value 0 is reserved + * @return The number of bytes effectively transferred. + * + * @notapi + */ +static size_t pipe_write(pipe_t *pp, const uint8_t *bp, size_t n) { + size_t s1, s2; + + PC_LOCK(pp); + + /* Number of bytes that can be written in a single atomic operation.*/ + if (n > chPipeGetFreeCount(pp)) { + n = chPipeGetFreeCount(pp); + } + pp->cnt += n; + + /* Number of bytes before buffer limit.*/ + /*lint -save -e9033 [10.8] Checked to be safe.*/ + s1 = (size_t)(pp->top - pp->wrptr); + /*lint -restore*/ + + if (n < s1) { + memcpy((void *)pp->wrptr, (const void *)bp, n); + pp->wrptr += n; + } + else if (n > s1) { + memcpy((void *)pp->wrptr, (const void *)bp, s1); + bp += s1; + s2 = n - s1; + memcpy((void *)pp->buffer, (const void *)bp, s2); + pp->wrptr = pp->buffer + s2; + } + else { /* n == s1 */ + memcpy((void *)pp->wrptr, (const void *)bp, n); + pp->wrptr = pp->buffer; + } + + PC_UNLOCK(pp); + + return n; +} + +/** + * @brief Non-blocking pipe read. + * @details The function reads data from a pipe into a buffer. The + * operation completes when the specified amount of data has been + * transferred or when the pipe buffer has been emptied. + * + * @param[in] pp the pointer to an initialized @p pipe_t object + * @param[out] bp pointer to the data buffer + * @param[in] n the maximum amount of data to be transferred, the + * value 0 is reserved + * @return The number of bytes effectively transferred. + * + * @notapi + */ +static size_t pipe_read(pipe_t *pp, uint8_t *bp, size_t n) { + size_t s1, s2; + + PC_LOCK(pp); + + /* Number of bytes that can be read in a single atomic operation.*/ + if (n > chPipeGetUsedCount(pp)) { + n = chPipeGetUsedCount(pp); + } + pp->cnt -= n; + + /* Number of bytes before buffer limit.*/ + /*lint -save -e9033 [10.8] Checked to be safe.*/ + s1 = (size_t)(pp->top - pp->rdptr); + /*lint -restore*/ + + if (n < s1) { + memcpy((void *)bp, (void *)pp->rdptr, n); + pp->rdptr += n; + } + else if (n > s1) { + memcpy((void *)bp, (void *)pp->rdptr, s1); + bp += s1; + s2 = n - s1; + memcpy((void *)bp, (void *)pp->buffer, s2); + pp->rdptr = pp->buffer + s2; + } + else { /* n == s1 */ + memcpy((void *)bp, (void *)pp->rdptr, n); + pp->rdptr = pp->buffer; + } + + PC_UNLOCK(pp); + + return n; +} + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes a @p mailbox_t object. + * + * @param[out] pp the pointer to the @p pipe_t structure to be + * initialized + * @param[in] buf pointer to the pipe buffer as an array of @p uint8_t + * @param[in] n number of elements in the buffer array + * + * @init + */ +void chPipeObjectInit(pipe_t *pp, uint8_t *buf, size_t n) { + + chDbgCheck((pp != NULL) && (buf != NULL) && (n > (size_t)0)); + + pp->buffer = buf; + pp->rdptr = buf; + pp->wrptr = buf; + pp->top = &buf[n]; + pp->cnt = (size_t)0; + pp->reset = false; + pp->wtr = NULL; + pp->rtr = NULL; + PC_INIT(pp); + PW_INIT(pp); + PR_INIT(pp); +} + +/** + * @brief Resets a @p pipe_t object. + * @details All the waiting threads are resumed with status @p MSG_RESET and + * the queued data is lost. + * @post The pipe is in reset state, all operations will fail and + * return @p MSG_RESET until the mailbox is enabled again using + * @p chPipeResumeX(). + * + * @param[in] pp the pointer to an initialized @p pipe_t object + * + * @api + */ +void chPipeReset(pipe_t *pp) { + + chDbgCheck(pp != NULL); + + PC_LOCK(pp); + + pp->wrptr = pp->buffer; + pp->rdptr = pp->buffer; + pp->cnt = (size_t)0; + pp->reset = true; + + chSysLock(); + chThdResumeI(&pp->wtr, MSG_RESET); + chThdResumeI(&pp->rtr, MSG_RESET); + chSchRescheduleS(); + chSysUnlock(); + + PC_UNLOCK(pp); +} + +/** + * @brief Pipe write with timeout. + * @details The function writes data from a buffer to a pipe. The + * operation completes when the specified amount of data has been + * transferred or after the specified timeout or if the pipe has + * been reset. + * + * @param[in] pp the pointer to an initialized @p pipe_t object + * @param[in] bp pointer to the data buffer + * @param[in] n the number of bytes to be written, the value 0 is + * reserved + * @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 number of bytes effectively transferred. A number + * lower than @p n means that a timeout occurred or the + * pipe went in reset state. + * + * @api + */ +size_t chPipeWriteTimeout(pipe_t *pp, const uint8_t *bp, + size_t n, sysinterval_t timeout) { + size_t max = n; + + chDbgCheck(n > 0U); + + /* If the pipe is in reset state then returns immediately.*/ + if (pp->reset) { + return (size_t)0; + } + + PW_LOCK(pp); + + while (n > 0U) { + size_t done; + + done = pipe_write(pp, bp, n); + if (done == (size_t)0) { + msg_t msg; + + chSysLock(); + msg = chThdSuspendTimeoutS(&pp->wtr, timeout); + chSysUnlock(); + + /* Anything except MSG_OK causes the operation to stop.*/ + if (msg != MSG_OK) { + break; + } + } + else { + n -= done; + bp += done; + + /* Resuming the reader, if present.*/ + chThdResume(&pp->rtr, MSG_OK); + } + } + + PW_UNLOCK(pp); + + return max - n; +} + +/** + * @brief Pipe read with timeout. + * @details The function reads data from a pipe into a buffer. The + * operation completes when the specified amount of data has been + * transferred or after the specified timeout or if the pipe has + * been reset. + * + * @param[in] pp the pointer to an initialized @p pipe_t object + * @param[out] bp pointer to the data buffer + * @param[in] n the number of bytes to be read, the value 0 is + * reserved + * @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 number of bytes effectively transferred. A number + * lower than @p n means that a timeout occurred or the + * pipe went in reset state. + * + * @api + */ +size_t chPipeReadTimeout(pipe_t *pp, uint8_t *bp, + size_t n, sysinterval_t timeout) { + size_t max = n; + + chDbgCheck(n > 0U); + + /* If the pipe is in reset state then returns immediately.*/ + if (pp->reset) { + return (size_t)0; + } + + PR_LOCK(pp); + + while (n > 0U) { + size_t done; + + done = pipe_read(pp, bp, n); + if (done == (size_t)0) { + msg_t msg; + + chSysLock(); + msg = chThdSuspendTimeoutS(&pp->rtr, timeout); + chSysUnlock(); + + /* Anything except MSG_OK causes the operation to stop.*/ + if (msg != MSG_OK) { + break; + } + } + else { + n -= done; + bp += done; + + /* Resuming the writer, if present.*/ + chThdResume(&pp->wtr, MSG_OK); + } + } + + PR_UNLOCK(pp); + + return max - n; +} + +#endif /* CH_CFG_USE_MAILBOXES == TRUE */ + +/** @} */ diff --git a/os/rt/rt.mk b/os/rt/rt.mk index 14a4d3cc0..3294ce896 100644 --- a/os/rt/rt.mk +++ b/os/rt/rt.mk @@ -72,4 +72,4 @@ ALLCSRC += $(KERNSRC) ALLINC += $(KERNINC) # OS Library -include $(CHIBIOS)/os/lib/lib.mk +include $(CHIBIOS)/os/oslib/oslib.mk -- cgit v1.2.3