More factory code.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10714 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
Giovanni Di Sirio 2017-09-26 08:03:05 +00:00
parent 0a24112ccd
commit 9f30d457c0
2 changed files with 208 additions and 6 deletions

View File

@ -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 */

View File

@ -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 */