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:
parent
5b0a0fe5b0
commit
107296cd78
|
@ -381,6 +381,17 @@
|
|||
#define CH_CFG_USE_PIPES TRUE
|
||||
#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.
|
||||
* @details If enabled then the dynamic threads creation APIs are included
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
/**
|
||||
* @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.
|
||||
|
@ -62,7 +62,7 @@
|
|||
/**
|
||||
* @brief OS Library version minor number.
|
||||
*/
|
||||
#define CH_OSLIB_MINOR 1
|
||||
#define CH_OSLIB_MINOR 2
|
||||
|
||||
/**
|
||||
* @brief OS Library version patch number.
|
||||
|
@ -108,6 +108,11 @@
|
|||
#error "CH_CFG_USE_PIPES not defined in chconf.h"
|
||||
#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.*/
|
||||
#if !defined(CH_CFG_USE_FACTORY)
|
||||
#error "CH_CFG_USE_FACTORY not defined in chconf.h"
|
||||
|
@ -210,6 +215,7 @@
|
|||
#include "chmempools.h"
|
||||
#include "chobjfifos.h"
|
||||
#include "chpipes.h"
|
||||
#include "chobjcaches.h"
|
||||
#include "chfactory.h"
|
||||
|
||||
/*===========================================================================*/
|
||||
|
|
|
@ -41,16 +41,11 @@
|
|||
#define OC_FLAG_INLRU 0x00000001U
|
||||
#define OC_FLAG_INHASH 0x00000002U
|
||||
#define OC_FLAG_SHARED 0x00000004U
|
||||
#define OC_FLAG_NOTREAD 0x00000008U
|
||||
#define OC_FLAG_NOTSYNC 0x00000008U
|
||||
#define OC_FLAG_LAZYWRITE 0x00000010U
|
||||
#define OC_FLAG_FORGET 0x00000020U
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Identifier for an invalid group.
|
||||
*/
|
||||
#define OC_NO_GROUP 0xFFFFFFFFU
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
@ -185,11 +180,15 @@ struct ch_oc_object {
|
|||
*/
|
||||
oc_flags_t obj_flags;
|
||||
/**
|
||||
* @brief Pointer to the data part of the object.
|
||||
* @note This pointer must be initialized outside this module after
|
||||
* calling @p chCacheObjectInit() which sets it to @p NULL.
|
||||
* @brief User pointer.
|
||||
* @note This pointer can be used to refer to external buffers,
|
||||
* @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.
|
||||
*/
|
||||
size_t hashn;
|
||||
ucnt_t hashn;
|
||||
/**
|
||||
* @brief Pointer to the hash table.
|
||||
*/
|
||||
|
@ -207,11 +206,15 @@ struct ch_objects_cache {
|
|||
/**
|
||||
* @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.
|
||||
*/
|
||||
oc_object_t *objp;
|
||||
void *objvp;
|
||||
/**
|
||||
* @brief LRU list header.
|
||||
*/
|
||||
|
@ -249,7 +252,8 @@ extern "C" {
|
|||
ucnt_t hashn,
|
||||
oc_hash_header_t *hashp,
|
||||
ucnt_t objn,
|
||||
oc_object_t *objp,
|
||||
size_t objsz,
|
||||
void *objvp,
|
||||
oc_readf_t readf,
|
||||
oc_writef_t writef);
|
||||
oc_object_t *chCacheGetObject(objects_cache_t *ocp,
|
||||
|
|
|
@ -29,6 +29,9 @@ endif
|
|||
ifneq ($(findstring CH_CFG_USE_PIPES TRUE,$(CHLIBCONF)),)
|
||||
LIBSRC += $(CHIBIOS)/os/oslib/src/chpipes.c
|
||||
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)),)
|
||||
LIBSRC += $(CHIBIOS)/os/oslib/src/chfactory.c
|
||||
endif
|
||||
|
@ -38,6 +41,7 @@ LIBSRC := $(CHIBIOS)/os/oslib/src/chmboxes.c \
|
|||
$(CHIBIOS)/os/oslib/src/chmemheaps.c \
|
||||
$(CHIBIOS)/os/oslib/src/chmempools.c \
|
||||
$(CHIBIOS)/os/oslib/src/chpipes.c \
|
||||
$(CHIBIOS)/os/oslib/src/chobjcaches.c \
|
||||
$(CHIBIOS)/os/oslib/src/chfactory.c
|
||||
endif
|
||||
|
||||
|
|
|
@ -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
|
||||
* @p oc_hash_header_t
|
||||
* @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
|
||||
* @p oc_object_t
|
||||
* @param[in] readf pointer to an object reader 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
|
||||
*/
|
||||
void chCacheObjectInit(objects_cache_t *ocp,
|
||||
ucnt_t hashn,
|
||||
oc_hash_header_t *hashp,
|
||||
ucnt_t objn,
|
||||
oc_object_t *objp,
|
||||
size_t objsz,
|
||||
void *objvp,
|
||||
oc_readf_t readf,
|
||||
oc_writef_t writef) {
|
||||
|
||||
chDbgCheck((ocp != NULL) && (hashp != NULL) && (objp != NULL) &&
|
||||
chDbgCheck((ocp != NULL) && (hashp != NULL) && (objvp != NULL) &&
|
||||
((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->lru_sem, (cnt_t)objn);
|
||||
ocp->hashn = hashn;
|
||||
ocp->hashp = hashp;
|
||||
ocp->objn = objn;
|
||||
ocp->objp = objp;
|
||||
ocp->objvp = objvp;
|
||||
ocp->readf = readf;
|
||||
ocp->writef = writef;
|
||||
ocp->lru.hash_next = NULL;
|
||||
|
@ -272,34 +267,37 @@ void chCacheObjectInit(objects_cache_t *ocp,
|
|||
ocp->lru.lru_prev = (oc_object_t *)&ocp->lru;
|
||||
|
||||
/* Hash headers initialization.*/
|
||||
while (hashp < &ocp->hashp[ocp->hashn]) {
|
||||
do {
|
||||
hashp->hash_next = (oc_object_t *)hashp;
|
||||
hashp->hash_prev = (oc_object_t *)hashp;
|
||||
}
|
||||
hashp++;
|
||||
} while (hashp < &ocp->hashp[ocp->hashn]);
|
||||
|
||||
/* 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);
|
||||
LRU_INSERT_HEAD(ocp, objp);
|
||||
objp->obj_group = 0U;
|
||||
objp->obj_key = 0U;
|
||||
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.
|
||||
* @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.
|
||||
*
|
||||
* @param[in] ocp pointer to the @p objects_cache_t structure
|
||||
* @param[in] group object group identifier or @p OC_NO_GROUP if
|
||||
* requesting a generic object buffer
|
||||
* @param[in] group object group identifier
|
||||
* @param[in] key object identifier within the group
|
||||
* @return The pointer to the retrieved object.
|
||||
* @retval NULL is a reserved value.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
|
@ -311,12 +309,6 @@ oc_object_t *chCacheGetObject(objects_cache_t *ocp,
|
|||
/* Critical section enter, the hash check operation is fast.*/
|
||||
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.*/
|
||||
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.*/
|
||||
objp->obj_group = group;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Out of critical section and returning the object.*/
|
||||
chSysUnlock();
|
||||
|
@ -374,7 +365,7 @@ oc_object_t *chCacheGetObject(objects_cache_t *ocp,
|
|||
* - @p OC_FLAG_INLRU must be cleared.
|
||||
* - @p OC_FLAG_INHASH must be set.
|
||||
* - @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.
|
||||
* - @p OC_FLAG_LAZYWRITE is ignored and kept, a write will occur
|
||||
* 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.*/
|
||||
if (chSemGetCounterI(&objp->obj_sem) < (cnt_t)0) {
|
||||
/* 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.*/
|
||||
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);
|
||||
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.*/
|
||||
if ((objp->obj_flags & OC_FLAG_NOTREAD) != 0U) {
|
||||
if ((objp->obj_flags & OC_FLAG_NOTSYNC) != 0U) {
|
||||
HASH_REMOVE(objp);
|
||||
LRU_INSERT_TAIL(ocp, objp);
|
||||
objp->obj_group = OC_NO_GROUP;
|
||||
objp->obj_group = 0U;
|
||||
objp->obj_key = 0U;
|
||||
objp->obj_flags = OC_FLAG_INLRU;
|
||||
}
|
||||
|
@ -458,10 +449,10 @@ bool chCacheReadObject(objects_cache_t *ocp,
|
|||
oc_object_t *objp,
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue