You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
812 lines
25 KiB
C
812 lines
25 KiB
C
4 years ago
|
/*
|
||
|
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 <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @file oslib/src/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.<br>
|
||
|
* @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 <string.h>
|
||
|
|
||
|
#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 + 1), 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, (msg_t *)(dmp + 1), 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) {
|
||
|
msg_t *msgbuf = (msg_t *)(dofp + 1);
|
||
|
|
||
|
/* Initializing mailbox object data.*/
|
||
|
chFifoObjectInitAligned(&dofp->fifo, objsize, objn, objalign,
|
||
|
(void *)&msgbuf[objn], 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, (uint8_t *)(dpp + 1), 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 */
|
||
|
|
||
|
/** @} */
|