BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / blob / master / lib / object / manager.c

// Related

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);
}