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 --- 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 ----------------------- 6 files changed, 2630 deletions(-) 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 (limited to 'os/lib/src') 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 */ - -/** @} */ -- cgit v1.2.3