Cache almost complete, tests to be created.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12957 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2019-08-25 13:27:36 +00:00
parent 5b0a0fe5b0
commit 107296cd78
5 changed files with 103 additions and 87 deletions

View File

@ -381,6 +381,17 @@
#define CH_CFG_USE_PIPES TRUE #define CH_CFG_USE_PIPES TRUE
#endif #endif
/**
* @brief Objects Caches APIs.
* @details If enabled then the objects caches APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_OBJ_CACHES)
#define CH_CFG_USE_OBJ_CACHES TRUE
#endif
/** /**
* @brief Dynamic Threads APIs. * @brief Dynamic Threads APIs.
* @details If enabled then the dynamic threads creation APIs are included * @details If enabled then the dynamic threads creation APIs are included

View File

@ -52,7 +52,7 @@
/** /**
* @brief OS Library version string. * @brief OS Library version string.
*/ */
#define CH_OSLIB_VERSION "1.1.0" #define CH_OSLIB_VERSION "1.2.0"
/** /**
* @brief OS Library version major number. * @brief OS Library version major number.
@ -62,7 +62,7 @@
/** /**
* @brief OS Library version minor number. * @brief OS Library version minor number.
*/ */
#define CH_OSLIB_MINOR 1 #define CH_OSLIB_MINOR 2
/** /**
* @brief OS Library version patch number. * @brief OS Library version patch number.
@ -108,6 +108,11 @@
#error "CH_CFG_USE_PIPES not defined in chconf.h" #error "CH_CFG_USE_PIPES not defined in chconf.h"
#endif #endif
#if !defined(CH_CFG_USE_OBJ_CACHES)
//#error "CH_CFG_USE_OBJ_CACHES not defined in chconf.h"
#define CH_CFG_USE_OBJ_CACHES 0
#endif
/* Objects factory options checks.*/ /* Objects factory options checks.*/
#if !defined(CH_CFG_USE_FACTORY) #if !defined(CH_CFG_USE_FACTORY)
#error "CH_CFG_USE_FACTORY not defined in chconf.h" #error "CH_CFG_USE_FACTORY not defined in chconf.h"
@ -210,6 +215,7 @@
#include "chmempools.h" #include "chmempools.h"
#include "chobjfifos.h" #include "chobjfifos.h"
#include "chpipes.h" #include "chpipes.h"
#include "chobjcaches.h"
#include "chfactory.h" #include "chfactory.h"
/*===========================================================================*/ /*===========================================================================*/

View File

@ -41,16 +41,11 @@
#define OC_FLAG_INLRU 0x00000001U #define OC_FLAG_INLRU 0x00000001U
#define OC_FLAG_INHASH 0x00000002U #define OC_FLAG_INHASH 0x00000002U
#define OC_FLAG_SHARED 0x00000004U #define OC_FLAG_SHARED 0x00000004U
#define OC_FLAG_NOTREAD 0x00000008U #define OC_FLAG_NOTSYNC 0x00000008U
#define OC_FLAG_LAZYWRITE 0x00000010U #define OC_FLAG_LAZYWRITE 0x00000010U
#define OC_FLAG_FORGET 0x00000020U #define OC_FLAG_FORGET 0x00000020U
/** @} */ /** @} */
/**
* @brief Identifier for an invalid group.
*/
#define OC_NO_GROUP 0xFFFFFFFFU
/*===========================================================================*/ /*===========================================================================*/
/* Module pre-compile time settings. */ /* Module pre-compile time settings. */
/*===========================================================================*/ /*===========================================================================*/
@ -185,11 +180,15 @@ struct ch_oc_object {
*/ */
oc_flags_t obj_flags; oc_flags_t obj_flags;
/** /**
* @brief Pointer to the data part of the object. * @brief User pointer.
* @note This pointer must be initialized outside this module after * @note This pointer can be used to refer to external buffers,
* calling @p chCacheObjectInit() which sets it to @p NULL. * @p chCacheObjectInit() initializes it to @p NULL.
*/ */
void *data; void *dptr;
/**
* @brief Embedded data as an open array.
*/
uint8_t dbuf[];
}; };
/** /**
@ -199,7 +198,7 @@ struct ch_objects_cache {
/** /**
* @brief Number of elements in the hash table. * @brief Number of elements in the hash table.
*/ */
size_t hashn; ucnt_t hashn;
/** /**
* @brief Pointer to the hash table. * @brief Pointer to the hash table.
*/ */
@ -207,11 +206,15 @@ struct ch_objects_cache {
/** /**
* @brief Number of elements in the objects table. * @brief Number of elements in the objects table.
*/ */
size_t objn; ucnt_t objn;
/**
* @brief Size of elements in the objects table.
*/
size_t objsz;
/** /**
* @brief Pointer to the objects table. * @brief Pointer to the objects table.
*/ */
oc_object_t *objp; void *objvp;
/** /**
* @brief LRU list header. * @brief LRU list header.
*/ */
@ -249,7 +252,8 @@ extern "C" {
ucnt_t hashn, ucnt_t hashn,
oc_hash_header_t *hashp, oc_hash_header_t *hashp,
ucnt_t objn, ucnt_t objn,
oc_object_t *objp, size_t objsz,
void *objvp,
oc_readf_t readf, oc_readf_t readf,
oc_writef_t writef); oc_writef_t writef);
oc_object_t *chCacheGetObject(objects_cache_t *ocp, oc_object_t *chCacheGetObject(objects_cache_t *ocp,

View File

@ -29,6 +29,9 @@ endif
ifneq ($(findstring CH_CFG_USE_PIPES TRUE,$(CHLIBCONF)),) ifneq ($(findstring CH_CFG_USE_PIPES TRUE,$(CHLIBCONF)),)
LIBSRC += $(CHIBIOS)/os/oslib/src/chpipes.c LIBSRC += $(CHIBIOS)/os/oslib/src/chpipes.c
endif endif
ifneq ($(findstring CH_CFG_USE_OBJ_CACHES TRUE,$(CHLIBCONF)),)
LIBSRC += $(CHIBIOS)/os/oslib/src/chobjcaches.c
endif
ifneq ($(findstring CH_CFG_USE_FACTORY TRUE,$(CHLIBCONF)),) ifneq ($(findstring CH_CFG_USE_FACTORY TRUE,$(CHLIBCONF)),)
LIBSRC += $(CHIBIOS)/os/oslib/src/chfactory.c LIBSRC += $(CHIBIOS)/os/oslib/src/chfactory.c
endif endif
@ -38,6 +41,7 @@ LIBSRC := $(CHIBIOS)/os/oslib/src/chmboxes.c \
$(CHIBIOS)/os/oslib/src/chmemheaps.c \ $(CHIBIOS)/os/oslib/src/chmemheaps.c \
$(CHIBIOS)/os/oslib/src/chmempools.c \ $(CHIBIOS)/os/oslib/src/chmempools.c \
$(CHIBIOS)/os/oslib/src/chpipes.c \ $(CHIBIOS)/os/oslib/src/chpipes.c \
$(CHIBIOS)/os/oslib/src/chobjcaches.c \
$(CHIBIOS)/os/oslib/src/chfactory.c $(CHIBIOS)/os/oslib/src/chfactory.c
endif endif

View File

@ -229,41 +229,36 @@ static oc_object_t *lru_get_last_s(objects_cache_t *ocp) {
* @param[in] hashp pointer to the hash table as an array of * @param[in] hashp pointer to the hash table as an array of
* @p oc_hash_header_t * @p oc_hash_header_t
* @param[in] objn number of elements in the objects table array * @param[in] objn number of elements in the objects table array
* @param[in] objsz size of elements in the objects table array, the
* minimum value is <tt>sizeof (oc_object_t)</tt>.
* @param[in] hashp pointer to the hash objects as an array of * @param[in] hashp pointer to the hash objects as an array of
* @p oc_object_t * @p oc_object_t
* @param[in] readf pointer to an object reader function * @param[in] readf pointer to an object reader function
* @param[in] writef pointer to an object writer function * @param[in] writef pointer to an object writer function
* *
* Object records states:
* - Invalid not owned:
* (OC_FLAG_INLRU, cnt==1).
* - Caching an object not owned:
* (OC_FLAG_INLRU, OC_FLAG_INHASH, OC_FLAG_CACHEHIT, cnt==1).
* - Representing an object owned:
* (OC_FLAG_INHASH, cnt<=0).
* - Caching an object owned:
* (OC_FLAG_INHASH, OC_FLAG_CACHEHIT, cnt<=0).
*
* @init * @init
*/ */
void chCacheObjectInit(objects_cache_t *ocp, void chCacheObjectInit(objects_cache_t *ocp,
ucnt_t hashn, ucnt_t hashn,
oc_hash_header_t *hashp, oc_hash_header_t *hashp,
ucnt_t objn, ucnt_t objn,
oc_object_t *objp, size_t objsz,
void *objvp,
oc_readf_t readf, oc_readf_t readf,
oc_writef_t writef) { oc_writef_t writef) {
chDbgCheck((ocp != NULL) && (hashp != NULL) && (objp != NULL) && chDbgCheck((ocp != NULL) && (hashp != NULL) && (objvp != NULL) &&
((hashn & (hashn - 1U)) == 0U) && ((hashn & (hashn - 1U)) == 0U) &&
(objn > (size_t)0) && (hashn >= objn)); (objn > (size_t)0) && (hashn >= objn) &&
(objsz >= sizeof (oc_object_t)) &&
((objsz & (PORT_NATURAL_ALIGN - 1U)) == 0U));
chSemObjectInit(&ocp->cache_sem, (cnt_t)1); chSemObjectInit(&ocp->cache_sem, (cnt_t)1);
chSemObjectInit(&ocp->lru_sem, (cnt_t)objn); chSemObjectInit(&ocp->lru_sem, (cnt_t)objn);
ocp->hashn = hashn; ocp->hashn = hashn;
ocp->hashp = hashp; ocp->hashp = hashp;
ocp->objn = objn; ocp->objn = objn;
ocp->objp = objp; ocp->objvp = objvp;
ocp->readf = readf; ocp->readf = readf;
ocp->writef = writef; ocp->writef = writef;
ocp->lru.hash_next = NULL; ocp->lru.hash_next = NULL;
@ -272,34 +267,37 @@ void chCacheObjectInit(objects_cache_t *ocp,
ocp->lru.lru_prev = (oc_object_t *)&ocp->lru; ocp->lru.lru_prev = (oc_object_t *)&ocp->lru;
/* Hash headers initialization.*/ /* Hash headers initialization.*/
while (hashp < &ocp->hashp[ocp->hashn]) { do {
hashp->hash_next = (oc_object_t *)hashp; hashp->hash_next = (oc_object_t *)hashp;
hashp->hash_prev = (oc_object_t *)hashp; hashp->hash_prev = (oc_object_t *)hashp;
} hashp++;
} while (hashp < &ocp->hashp[ocp->hashn]);
/* Object headers initialization.*/ /* Object headers initialization.*/
while (objp < &ocp->objp[ocp->objn]) { do {
oc_object_t *objp = (oc_object_t *)objvp;
chSemObjectInit(&objp->obj_sem, (cnt_t)1); chSemObjectInit(&objp->obj_sem, (cnt_t)1);
LRU_INSERT_HEAD(ocp, objp); LRU_INSERT_HEAD(ocp, objp);
objp->obj_group = 0U; objp->obj_group = 0U;
objp->obj_key = 0U; objp->obj_key = 0U;
objp->obj_flags = OC_FLAG_INLRU; objp->obj_flags = OC_FLAG_INLRU;
objp->data = NULL; objp->dptr = NULL;
} objvp += objsz;
objn--;
} while (objn > 0U);
} }
/** /**
* @brief Retrieves an object from the cache. * @brief Retrieves an object from the cache.
* @note If the object is not in cache then the returned object is marked * @note If the object is not in cache then the returned object is marked
* as @p OC_FLAG_NOTREAD meaning that its data contains garbage and * as @p OC_FLAG_NOTSYNC meaning that its data contains garbage and
* must be initialized. * must be initialized.
* *
* @param[in] ocp pointer to the @p objects_cache_t structure * @param[in] ocp pointer to the @p objects_cache_t structure
* @param[in] group object group identifier or @p OC_NO_GROUP if * @param[in] group object group identifier
* requesting a generic object buffer
* @param[in] key object identifier within the group * @param[in] key object identifier within the group
* @return The pointer to the retrieved object. * @return The pointer to the retrieved object.
* @retval NULL is a reserved value.
* *
* @api * @api
*/ */
@ -311,12 +309,6 @@ oc_object_t *chCacheGetObject(objects_cache_t *ocp,
/* Critical section enter, the hash check operation is fast.*/ /* Critical section enter, the hash check operation is fast.*/
chSysLock(); chSysLock();
/* If the requested object is not a generic one.*/
if (group == OC_NO_GROUP) {
/* Any buffer will do.*/
objp = NULL; /* TODO */
}
else {
/* Checking the cache for a hit.*/ /* Checking the cache for a hit.*/
objp = hash_get_s(ocp, group, key); objp = hash_get_s(ocp, group, key);
@ -357,10 +349,9 @@ oc_object_t *chCacheGetObject(objects_cache_t *ocp,
/* Naming this object and publishing it in the hash table.*/ /* Naming this object and publishing it in the hash table.*/
objp->obj_group = group; objp->obj_group = group;
objp->obj_key = key; objp->obj_key = key;
objp->obj_flags = OC_FLAG_INHASH | OC_FLAG_NOTREAD; objp->obj_flags = OC_FLAG_INHASH | OC_FLAG_NOTSYNC;
HASH_INSERT(ocp, objp, group, key); HASH_INSERT(ocp, objp, group, key);
} }
}
/* Out of critical section and returning the object.*/ /* Out of critical section and returning the object.*/
chSysUnlock(); chSysUnlock();
@ -374,7 +365,7 @@ oc_object_t *chCacheGetObject(objects_cache_t *ocp,
* - @p OC_FLAG_INLRU must be cleared. * - @p OC_FLAG_INLRU must be cleared.
* - @p OC_FLAG_INHASH must be set. * - @p OC_FLAG_INHASH must be set.
* - @p OC_FLAG_SHARED must be cleared. * - @p OC_FLAG_SHARED must be cleared.
* - @p OC_FLAG_NOTREAD invalidates the object and queues it on * - @p OC_FLAG_NOTSYNC invalidates the object and queues it on
* the LRU tail. * the LRU tail.
* - @p OC_FLAG_LAZYWRITE is ignored and kept, a write will occur * - @p OC_FLAG_LAZYWRITE is ignored and kept, a write will occur
* when the object is removed from the LRU list (lazy write). * when the object is removed from the LRU list (lazy write).
@ -400,19 +391,19 @@ void chCacheReleaseObjectI(objects_cache_t *ocp,
handed directly without going through the LRU.*/ handed directly without going through the LRU.*/
if (chSemGetCounterI(&objp->obj_sem) < (cnt_t)0) { if (chSemGetCounterI(&objp->obj_sem) < (cnt_t)0) {
/* Clearing all flags except those that are still meaningful, note, /* Clearing all flags except those that are still meaningful, note,
OC_FLAG_NOTREAD and OC_FLAG_LAZYWRITE are passed, the other thread OC_FLAG_NOTSYNC and OC_FLAG_LAZYWRITE are passed, the other thread
will handle them.*/ will handle them.*/
objp->obj_flags &= OC_FLAG_INHASH | OC_FLAG_NOTREAD | OC_FLAG_LAZYWRITE; objp->obj_flags &= OC_FLAG_INHASH | OC_FLAG_NOTSYNC | OC_FLAG_LAZYWRITE;
chSemSignalI(&objp->obj_sem); chSemSignalI(&objp->obj_sem);
return; return;
} }
/* If the object specifies OC_FLAG_NOTREAD then it must be invalidated /* If the object specifies OC_FLAG_NOTSYNC then it must be invalidated
and removed from the hash table.*/ and removed from the hash table.*/
if ((objp->obj_flags & OC_FLAG_NOTREAD) != 0U) { if ((objp->obj_flags & OC_FLAG_NOTSYNC) != 0U) {
HASH_REMOVE(objp); HASH_REMOVE(objp);
LRU_INSERT_TAIL(ocp, objp); LRU_INSERT_TAIL(ocp, objp);
objp->obj_group = OC_NO_GROUP; objp->obj_group = 0U;
objp->obj_key = 0U; objp->obj_key = 0U;
objp->obj_flags = OC_FLAG_INLRU; objp->obj_flags = OC_FLAG_INLRU;
} }
@ -458,10 +449,10 @@ bool chCacheReadObject(objects_cache_t *ocp,
oc_object_t *objp, oc_object_t *objp,
bool async) { bool async) {
/* Marking it as OC_FLAG_NOTREAD because the read operation is going /* Marking it as OC_FLAG_NOTSYNC because the read operation is going
to corrupt it in case of failure. It is responsibility of the read to corrupt it in case of failure. It is responsibility of the read
implementation to clear it if the operation succeeds.*/ implementation to clear it if the operation succeeds.*/
objp->obj_flags |= OC_FLAG_NOTREAD; objp->obj_flags |= OC_FLAG_NOTSYNC;
return ocp->readf(ocp, objp, async); return ocp->readf(ocp, objp, async);
} }