diff --git a/paw/stos/head/ob/cache.h b/paw/stos/head/ob/cache.h new file mode 100644 index 0000000..d93c4d1 --- /dev/null +++ b/paw/stos/head/ob/cache.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2026, Chloe M. + * Provided under the BSD-3 clause. + * + * Description: Object manager cache + * Author: Chloe M. + */ + +#ifndef _OB_CACHE_H_ +#define _OB_CACHE_H_ 1 + +#include +#include + +/* + * An object cache allows deallocated objects to be recycled without + * the overhead of true deallocation and reallocation. + * + * @First: First cache entry + * @Last: Last cache entry + * @EntryCount: Number of entires in the cache + */ +typedef struct { + ST_OBJECT *First; + ST_OBJECT *Last; + USIZE EntryCount; +} OBJECT_CACHE; + +extern OBJECT_CACHE gObCache; + +/* + * Initialize object cache + * + * @Cache: Object cache to initialize + */ +VOID ObInitCache(OBJECT_CACHE *Cache); + +/* + * Reclaim object to cache if the reference count is + * zero. + * + * @Cache: Cache to reclaim to + * @Object: Object to reclaim + */ +VOID ObReclaimToCache(OBJECT_CACHE *Cache, ST_OBJECT *Object); + +/* + * Pop an entry for a zeroed object from the cache + * + * @Cache: Cache to pop from + * + * Returns an entry on success, otherwise NULL on + * failure + */ +ST_OBJECT *ObPopFromCache(OBJECT_CACHE *Cache); + +#endif /* !_OB_CACHE_H_ */ diff --git a/paw/stos/head/ob/object.h b/paw/stos/head/ob/object.h index 9143f88..786c624 100644 --- a/paw/stos/head/ob/object.h +++ b/paw/stos/head/ob/object.h @@ -34,12 +34,14 @@ typedef enum { * @RefCount: Object reference count * @Type: Object type * @Data: Object data + * @CacheNext: Used when reclaiming object */ -typedef struct { +typedef struct _ST_OBJECT { CHAR Name[OBJECT_NAMESZ]; ULONG RefCount; OBJECT_TYPE Type; VOID *Data; + struct _ST_OBJECT *CacheNext; } ST_OBJECT; /* @@ -82,4 +84,12 @@ ST_STATUS ObCreateObject( */ VOID ObInitManager(VOID); +/* + * Reclaim an object after use, if its reference count is > 1, simply + * bump it down. Once it hits zero, the object is returned to the cache. + * + * @Object: Object to reclaim + */ +VOID ObReclaimObject(ST_OBJECT *Object); + #endif /* !_OB_OBJECT_H_ */ diff --git a/paw/stos/ob/cache.c b/paw/stos/ob/cache.c new file mode 100644 index 0000000..74658ad --- /dev/null +++ b/paw/stos/ob/cache.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2026, Chloe M. + * Provided under the BSD-3 clause. + * + * Description: Object manager cache + * Author: Chloe M. + */ + +#include +#include + +VOID +ObReclaimToCache(OBJECT_CACHE *Cache, ST_OBJECT *Object) +{ + ST_OBJECT *Last; + + if (Cache == NULL || Object == NULL) { + return; + } + + /* Can only reclaim when refcount hits zero */ + if (Object->RefCount != 0) { + return; + } + + /* Insert the object */ + Object->CacheNext = NULL; + if (Cache->First == NULL || Cache->Last == NULL) { + Cache->First = Object; + Cache->Last = Object; + } else { + Last = Cache->Last; + Last->CacheNext = Object; + Cache->Last = Object; + } + + ++Cache->EntryCount; +} + +VOID +ObInitCache(OBJECT_CACHE *Cache) +{ + if (Cache == NULL) { + return; + } + + Cache->EntryCount = 0; + Cache->First = NULL; + Cache->Last = NULL; +} + +ST_OBJECT * +ObPopFromCache(OBJECT_CACHE *Cache) +{ + ST_OBJECT *First; + + if (Cache == NULL) { + return NULL; + } + + First = Cache->First; + if (First == NULL) { + return NULL; + } + + Cache->First = First->CacheNext; + RtlMemSet(First, 0, sizeof(*First)); + return First; +} diff --git a/paw/stos/ob/init.c b/paw/stos/ob/init.c index 5f13132..6d0a550 100644 --- a/paw/stos/ob/init.c +++ b/paw/stos/ob/init.c @@ -7,6 +7,7 @@ */ #include +#include #include #include @@ -15,12 +16,14 @@ /* Globals */ static ST_OBJECT *RootDirectory; +OBJECT_CACHE gObCache; VOID ObInitManager(VOID) { ST_STATUS Status; + ObInitCache(&gObCache); Status = ObCreateDirectory( "/", &RootDirectory diff --git a/paw/stos/ob/ob.c b/paw/stos/ob/ob.c index 3deb169..07b6b67 100644 --- a/paw/stos/ob/ob.c +++ b/paw/stos/ob/ob.c @@ -8,6 +8,7 @@ #include #include +#include #include ST_STATUS @@ -84,3 +85,17 @@ ObCreateObject(const CHAR *Name, OBJECT_TYPE Type, VOID *Data, ST_OBJECT **Resul *Result = Object; return STATUS_SUCCESS; } + +VOID +ObReclaimObject(ST_OBJECT *Object) +{ + if (Object == NULL) { + return; + } + + /* TODO: Decrement this atomically */ + Object->RefCount -= 1; + if (Object->RefCount == 0) { + ObReclaimToCache(&gObCache, Object); + } +}