aboutsummaryrefslogtreecommitdiffstats
path: root/os/common
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2017-09-26 08:03:05 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2017-09-26 08:03:05 +0000
commit9f30d457c02f514d4d60112ba4ffeb367ce3bee6 (patch)
treeecd38bae3f9055dd1dcd389f05abfecbbbe7a5bb /os/common
parent0a24112ccdf69df68f478a8b84998052aba68a8b (diff)
downloadChibiOS-9f30d457c02f514d4d60112ba4ffeb367ce3bee6.tar.gz
ChibiOS-9f30d457c02f514d4d60112ba4ffeb367ce3bee6.tar.bz2
ChibiOS-9f30d457c02f514d4d60112ba4ffeb367ce3bee6.zip
More factory code.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10714 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/common')
-rw-r--r--os/common/oslib/include/chfactory.h20
-rw-r--r--os/common/oslib/src/chfactory.c194
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 */