Nucleus
Barry Object manager and heap in kernel library 08afe80 (3 years, 2 months ago)
/*
* This is the Object Manager. It implements the basic operations each object
* needs and leaves the rest up to the respective subsystem that implements that
* object. The object manager is a resource manager which should help improve
* memory safety within the kernel. It reference counts each object and
* controls their instantiation and deletion.
*/
#include <nucleus/kernel.h>
#include <nucleus/memory.h>
#include <nucleus/object.h>
void init_lock(Spinlock *lock);
void acquire(Spinlock *lock);
void release(Spinlock *lock);
/* Check the magic of an object */
int
check(void *addr)
{
Object *obj = addr;
return (obj && obj->magic == OBJECT_MAGIC);
}
/* Obtain a reference to an object */
void *
get(void *addr)
{
Object *obj = addr;
ASSERT(obj->magic == OBJECT_MAGIC);
__atomic_add_fetch(&obj->type->usage, 1, __ATOMIC_RELAXED);
__atomic_add_fetch(&obj->usage, 1, __ATOMIC_RELAXED);
return addr;
}
/* Release a reference to an object */
void
put(void *addr)
{
Object *obj = addr;
ASSERT(obj->magic == OBJECT_MAGIC);
__atomic_sub_fetch(&obj->type->usage, 1, __ATOMIC_RELAXED);
if (__atomic_sub_fetch(&obj->usage, 1, __ATOMIC_RELAXED))
return;
if (obj->type->delete)
obj->type->delete(obj);
remove(obj->type->objects, obj);
obj->magic = 0;
if (obj->type->free)
obj->type->free(obj);
else
kfree(obj);
}
/* Create a new instance of an object */
void *
new(ObjectType *type)
{
Object *obj;
if (type->alloc && type->free)
obj = type->alloc();
else
obj = kmalloc(type->size);
init_lock(&obj->lock);
obj->magic = OBJECT_MAGIC;
obj->type = type;
if (type->new)
type->new(obj);
if (!type->objects)
type->objects = create_list(type, LIST_NORMAL);
add(type->objects, obj);
/* No need to get() since it's in the global list */
return obj;
}
/* Copy an instance of an object */
void *
copy(void *addr)
{
Object *parent = addr;
Object *child = NULL;
ASSERT(parent->magic == OBJECT_MAGIC);
if (parent->type->copy) {
child = new(parent->type);
parent->type->copy(parent, child);
}
return child;
}
/* Check how many times an object is referenced */
refcount_t
usage(void *addr)
{
Object *obj = addr;
ASSERT(obj->magic == OBJECT_MAGIC);
return obj->usage;
}
/* Lock an object */
void
lock(void *addr)
{
Object *obj = addr;
ASSERT(obj->magic == OBJECT_MAGIC);
acquire(&obj->lock);
}
/* Unlock an object */
void
unlock(void *addr)
{
Object *obj = addr;
ASSERT(obj->magic == OBJECT_MAGIC);
release(&obj->lock);
}