From 9f30d457c02f514d4d60112ba4ffeb367ce3bee6 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Tue, 26 Sep 2017 08:03:05 +0000 Subject: More factory code. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10714 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/common/oslib/include/chfactory.h | 20 +++- os/common/oslib/src/chfactory.c | 194 +++++++++++++++++++++++++++++++++++- 2 files changed, 208 insertions(+), 6 deletions(-) diff --git a/os/common/oslib/include/chfactory.h b/os/common/oslib/include/chfactory.h index d8cd20a22..2fe2765dd 100644 --- a/os/common/oslib/include/chfactory.h +++ b/os/common/oslib/include/chfactory.h @@ -131,7 +131,7 @@ typedef struct ch_dyn_object { /** * @brief List element of the dynamic object. */ - dyn_element_t list; + dyn_element_t element; /** * @brief Physical objects. * @note This requires C99. @@ -148,7 +148,7 @@ typedef struct ch_dyn_semaphore { /** * @brief List element of the dynamic semaphore. */ - dyn_element_t list; + dyn_element_t element; /** * @brief Physical semaphore. */ @@ -213,6 +213,22 @@ extern "C" { /* Module inline functions. */ /*===========================================================================*/ +/** + * @brief Duplicates an object reference. + * + * @param[in] dep pointer to the element field of the object + * + * @iclass + */ +static inline dyn_element_t *chFactoryDuplicateReferenceI(dyn_element_t *dep) { + + chDbgCheckClassI(); + + dep->refs++; + + return dep; +} + #endif /* CH_CFG_USE_FACTORY == TRUE */ #endif /* CHFACTORY_H */ diff --git a/os/common/oslib/src/chfactory.c b/os/common/oslib/src/chfactory.c index de16e813c..2f4c56d18 100644 --- a/os/common/oslib/src/chfactory.c +++ b/os/common/oslib/src/chfactory.c @@ -90,6 +90,24 @@ static dyn_element_t *dyn_list_find(dyn_list_t *dlp, const char *name) { return NULL; } +static dyn_element_t *dyn_list_unlink(dyn_list_t *dlp, dyn_element_t *element) { + 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; +} + /*===========================================================================*/ /* Module exported functions. */ /*===========================================================================*/ @@ -114,7 +132,7 @@ void _factory_init(void) { #if (CH_CFG_FACTORY_GENERIC == TRUE) || defined(__DOXIGEN__) /** - * @brief Allocates a generic dynamic object. + * @brief Creates a generic dynamic object. * @post A reference to the object is returned and the reference counter * is initialized to one. * @post The object is zero filled. @@ -125,10 +143,14 @@ void _factory_init(void) { * @return The reference to the created object. * @retval NULL if the object cannot be allocated or an object with * the same name exists. + * + * @api */ dyn_object_t *chFactoryCreateObject(const char *name, size_t size) { dyn_object_t *dop; + chDbgCheck(name != NULL); + chSysLock(); /* Checking if an object with this name has already been created.*/ @@ -139,6 +161,7 @@ dyn_object_t *chFactoryCreateObject(const char *name, size_t size) { return NULL; } + /* Allocating space for the new object.*/ dop = chHeapAlloc(NULL, size); if (dop == NULL) { chSysUnlock(); @@ -146,9 +169,9 @@ dyn_object_t *chFactoryCreateObject(const char *name, size_t size) { } /* Initializing object data and metadata.*/ - strncpy(dop->list.name, name, CH_CFG_FACTORY_MAX_NAMES_LENGHT); - dop->list.refs = 1; - dop->list.next = ch_factory.obj_list.next; + strncpy(dop->element.name, name, CH_CFG_FACTORY_MAX_NAMES_LENGHT); + dop->element.refs = 1; + dop->element.next = ch_factory.obj_list.next; memset((void *)dop->obj, 0, size); /* Updating factory list.*/ @@ -159,12 +182,70 @@ dyn_object_t *chFactoryCreateObject(const char *name, size_t size) { return dop; } +/** + * @brief Retrieves a generic dynamic object. + * @post A reference to the object is returned with the reference counter + * increased by one. + * + * @param[in] name name to be assigned to the new object + * + * @return The reference to the found object. + * @retval NULL if an object with the specified name name does + * not exist. + * + * @api + */ dyn_object_t *chFactoryFindObject(const char *name) { + dyn_object_t *dop; + + chDbgCheck(name != NULL); + + chSysLock(); + + /* Checking if an object with this name has already been created.*/ + dop = (dyn_object_t *)dyn_list_find(&ch_factory.obj_list, name); + if (dop == NULL) { + /* Object does not exists, error.*/ + chSysUnlock(); + return NULL; + } + + /* Increasing references counter.*/ + dop->element.refs += 1; + chSysUnlock(); + + return dop; } +/** + * @brief Releases a generic dynamic object. + * @details The reference counter of the object is decreased by one, if + * reaches zero then the object memory is freed. + * + * @param[in] dop generic object reference + * + * @api + */ void chFactoryReleaseObject(dyn_object_t *dop) { + chDbgCheck(dop != NULL); + + chSysLock(); + + chDbgAssert(dop->element.refs > 0U, "invalid references number"); + + dop = (dyn_object_t *)dyn_list_unlink(&ch_factory.obj_list, + &dop->element); + + chDbgAssert(dop != NULL, "invalid reference passed"); + + dop->element.refs--; + if (dop->element.refs == 0) { + chHeapFree((void *)dop); + } + + chSysUnlock(); } size_t chFactoryGetObjectSize(dyn_object_t *dop) { @@ -174,16 +255,121 @@ size_t chFactoryGetObjectSize(dyn_object_t *dop) { #endif /* CH_CFG_FACTORY_GENERIC = TRUE */ #if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXIGEN__) +/** + * @brief Creates a dynamic semaphore object. + * @post A reference to the semaphore is returned and the reference counter + * is initialized to one. + * @post The semaphore object is initialized and ready to use. + * + * @param[in] name name to be assigned to the new semaphore object + * @param[in] n semaphore counter initialization value + * + * @return The reference to the created semaphore object. + * @retval NULL if the semaphore cannot be allocated or an semaphore + * with the same name exists. + * + * @api + */ dyn_semaphore_t *chFactoryCreateSemaphore(const char *name, cnt_t n) { + dyn_semaphore_t *dsp; + + chDbgCheck(name != NULL); + + chSysLock(); + + /* Checking if an object with this name has already been created.*/ + dsp = (dyn_semaphore_t *)dyn_list_find(&ch_factory.sem_list, name); + if (dsp != NULL) { + /* Semaphore exists, error.*/ + chSysUnlock(); + return NULL; + } + + /* Allocating space for the new object.*/ + dsp = chCoreAlloc(sizeof (dyn_semaphore_t)); + if (dsp == NULL) { + chSysUnlock(); + return NULL; + } + + /* Initializing object data and metadata.*/ + strncpy(dsp->element.name, name, CH_CFG_FACTORY_MAX_NAMES_LENGHT); + dsp->element.refs = 1; + dsp->element.next = ch_factory.obj_list.next; + chSemObjectInit(&dsp->sem, n); + + /* Updating factory list.*/ + ch_factory.obj_list.next = (dyn_element_t *)dsp; + + chSysUnlock(); + return dsp; } +/** + * @brief Retrieves a generic dynamic semaphore object. + * @post A reference to the semaphore is returned with the reference counter + * increased by one. + * + * @param[in] name name to be assigned to the new semaphore object + * + * @return The reference to the found semaphore object. + * @retval NULL if a semaphore with the specified name name does + * not exist. + * + * @api + */ dyn_semaphore_t *chFactoryFindSemaphore(const char *name) { + dyn_semaphore_t *dsp; + chDbgCheck(name != NULL); + + chSysLock(); + + /* Checking if an object with this name has already been created.*/ + dsp = (dyn_semaphore_t *)dyn_list_find(&ch_factory.obj_list, name); + if (dsp == NULL) { + /* Object does not exists, error.*/ + chSysUnlock(); + return NULL; + } + + /* Increasing references counter.*/ + dsp->element.refs += 1; + + chSysUnlock(); + + return dsp; } +/** + * @brief Releases a semaphore dynamic object. + * @details The reference counter of the semaphore is decreased by one, if + * reaches zero then the semaphore memory is freed. + * + * @param[in] dsp semaphore object reference + * + * @api + */ void chFactoryReleaseSemaphore(dyn_semaphore_t *dsp) { + chDbgCheck(dsp != NULL); + + chSysLock(); + + chDbgAssert(dsp->element.refs > 0U, "invalid references number"); + + dsp = (dyn_semaphore_t *)dyn_list_unlink(&ch_factory.sem_list, + &dsp->element); + + chDbgAssert(dsp != NULL, "invalid reference passed"); + + dsp->element.refs--; + if (dsp->element.refs == 0) { + chPoolFree(&ch_factory.sem_pool, (void *)dsp); + } + + chSysUnlock(); } #endif /* CH_CFG_FACTORY_SEMAPHORES = TRUE */ -- cgit v1.2.3