OS objects factory, work in progress.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10711 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
Giovanni Di Sirio 2017-09-25 15:11:41 +00:00
parent eae327a32e
commit 590df48760
2 changed files with 412 additions and 0 deletions

View File

@ -0,0 +1,220 @@
/*
ChibiOS - Copyright (C) 2006..2016 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 chfactory.h
* @brief ChibiOS objects factory structures and macros.
*
* @addtogroup objects_factory
* @{
*/
#ifndef CHFACTORY_H
#define CHFACTORY_H
#if (CH_CFG_USE_FACTORY == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Maximum length for object names.
* @details If the specified length is zero then the name is stored by
* pointer but this could have unintended side effects.
*/
#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGHT) || defined(__DOXYGEN__)
#define CH_CFG_FACTORY_MAX_NAMES_LENGHT 8
#endif
/**
* @brief Enables factory for generic objects.
* @note Generic objects require the heap allocator.
*/
#if !defined(CH_CFG_FACTORY_GENERIC) || defined(__DOXYGEN__)
#define CH_CFG_FACTORY_GENERIC TRUE
#endif
/**
* @brief Enables factory for semaphores.
*/
#if !defined(CH_CFG_FACTORY_SEMAPHORES) || defined(__DOXYGEN__)
#define CH_CFG_FACTORY_SEMAPHORES TRUE
#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#define CH_FACTORY_REQUIRES_POOLS \
((CH_CFG_FACTORY_SEMAPHORES == TRUE))
#define CH_FACTORY_REQUIRES_HEAP \
((CH_CFG_FACTORY_GENERIC == TRUE))
#if (CH_CFG_FACTORY_MAX_NAMES_LENGHT < 0) || \
(CH_CFG_FACTORY_MAX_NAMES_LENGHT > 32)
#error "invalid CH_CFG_FACTORY_MAX_NAMES_LENGHT value"
#endif
#if CH_CFG_USE_MEMCORE == FALSE
#error "CH_CFG_USE_FACTORY requires CH_CFG_USE_MEMCORE"
#endif
#if (CH_FACTORY_REQUIRES_POOLS == TRUE) && (CH_CFG_USE_MEMPOOLS == FALSE)
#error "CH_CFG_USE_MEMPOOLS is required"
#endif
#if (CH_FACTORY_REQUIRES_HEAP == TRUE) && (CH_CFG_USE_HEAP == FALSE)
#error "CH_CFG_USE_HEAP is required"
#endif
#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) && (CH_CFG_USE_SEMAPHORES == FALSE)
#error "CH_CFG_FACTORY_SEMAPHORES requires CH_CFG_USE_SEMAPHORES"
#endif
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
/**
* @brief Type of a dynamic object list element.
*/
typedef struct ch_dyn_element {
/**
* @brief Next dynamic object in the list.
*/
struct ch_dyn_element *next;
/**
* @brief Number of references to this object.
*/
ucnt_t refs;
#if (CH_CFG_FACTORY_MAX_NAMES_LENGHT > 0) || defined(__DOXIGEN__)
char name[CH_CFG_FACTORY_MAX_NAMES_LENGHT];
#else
const char *name;
#endif
} dyn_element_t;
/**
* @brief Type of a dynamic object list.
*/
typedef struct ch_dyn_list {
dyn_element_t *next;
} dyn_list_t;
#if (CH_CFG_FACTORY_GENERIC == TRUE) || defined(__DOXIGEN__)
/**
* @brief Type of a dynamic semaphore.
*/
typedef struct ch_dyn_object {
/**
* @brief List element of the dynamic object.
*/
dyn_element_t list;
/**
* @brief Physical objects.
* @note This requires C99.
*/
uint8_t obj[];
} dyn_object_t;
#endif
#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXIGEN__)
/**
* @brief Type of a dynamic semaphore.
*/
typedef struct ch_dyn_semaphore {
/**
* @brief List element of the dynamic semaphore.
*/
dyn_element_t list;
/**
* @brief Physical semaphore.
*/
semaphore_t sem;
} dyn_semaphore_t;
#endif
/**
* @brief Type of the factory main object.
*/
typedef struct ch_objects_factory {
#if (CH_CFG_FACTORY_GENERIC == TRUE) || defined(__DOXIGEN__)
/**
* @brief List of the allocated objects.
*/
dyn_list_t obj_list;
#endif /* CH_CFG_FACTORY_GENERIC = TRUE */
#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXIGEN__)
/**
* @brief List of the allocated semaphores.
*/
dyn_list_t sem_list;
/**
* @brief Pool of the available semaphores.
*/
memory_pool_t sem_pool;
#endif /* CH_CFG_FACTORY_SEMAPHORES = TRUE */
} objects_factory_t;
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if !defined(__DOXYGEN__)
objects_factory_t ch_factory;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void _factory_init(void);
#if (CH_CFG_FACTORY_GENERIC == TRUE) || defined(__DOXIGEN__)
dyn_object_t *chFactoryCreateObject(const char *name, size_t size);
dyn_object_t *chFactoryFindObject(const char *name);
void chFactoryReleaseObject(dyn_object_t *dop);
size_t chFactoryGetObjectSize(dyn_object_t *dop);
#endif
#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXIGEN__)
dyn_semaphore_t *chFactoryCreateSemaphore(const char *name, cnt_t n);
dyn_semaphore_t *chFactoryFindSemaphore(const char *name);
void chFactoryReleaseSemaphore(dyn_semaphore_t *dsp);
#endif
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
#endif /* CH_CFG_USE_FACTORY == TRUE */
#endif /* CHFACTORY_H */
/** @} */

View File

@ -0,0 +1,192 @@
/*
ChibiOS - Copyright (C) 2006..2016 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 chfactory.c
* @brief ChibiOS objects factory code.
*
* @addtogroup objects_factory
* @details The object factory is a subsystem that allows to:
* - 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"
#include "chfactory.h"
#if (CH_CFG_USE_FACTORY == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Module local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* 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(dyn_list_t *dlp, const char *name) {
dyn_element_t *p = dlp->next;
while (p != (dyn_element_t *)dlp) {
if (strncmp(p->name, name, CH_CFG_FACTORY_MAX_NAMES_LENGHT) == 0) {
return p;
}
p = p->next;
}
return NULL;
}
/*===========================================================================*/
/* Module exported functions. */
/*===========================================================================*/
/**
* @brief Initializes the objects factory.
*
* @init
*/
void _factory_init(void) {
#if CH_CFG_FACTORY_GENERIC == TRUE
dyn_list_init(&ch_factory.obj_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_GENERIC == TRUE) || defined(__DOXIGEN__)
/**
* @brief Allocates 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.
*
* @param[in] name name to be assigned to the new object
* @param[in] size payload size of the object to be created
*
* @return The reference to the created object.
* @retval NULL if the object cannot be allocated or an object with
* the same name exists.
*/
dyn_object_t *chFactoryCreateObject(const char *name, size_t size) {
dyn_object_t *dop;
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 exists, error.*/
chSysUnlock();
return NULL;
}
dop = chHeapAlloc(NULL, size);
if (dop == NULL) {
chSysUnlock();
return NULL;
}
/* 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;
memset((void *)dop->obj, 0, size);
/* Updating factory list.*/
ch_factory.obj_list.next = dop;
chSysUnlock();
return dop;
}
dyn_object_t *chFactoryFindObject(const char *name) {
}
void chFactoryReleaseObject(dyn_object_t *dop) {
}
size_t chFactoryGetObjectSize(dyn_object_t *dop) {
return chHeapGetSize((void *)dop);
}
#endif /* CH_CFG_FACTORY_GENERIC = TRUE */
#if (CH_CFG_FACTORY_SEMAPHORES == TRUE) || defined(__DOXIGEN__)
dyn_semaphore_t *chFactoryCreateSemaphore(const char *name, cnt_t n) {
}
dyn_semaphore_t *chFactoryFindSemaphore(const char *name) {
}
void chFactoryReleaseSemaphore(dyn_semaphore_t *dsp) {
}
#endif /* CH_CFG_FACTORY_SEMAPHORES = TRUE */
#endif /* CH_CFG_USE_FACTORY == TRUE */
/** @} */