BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / commit / 08afe80d1ca157b9cddb31ee48ab0e6e1823f559 / lib / object / manager.c

// Related

Nucleus

Barry Object manager and heap in kernel library 08afe80 (3 years, 2 months ago)
diff --git a/lib/object/manager.c b/lib/object/manager.c
new file mode 100644
index 0000000..09d0b07
--- /dev/null
+++ b/lib/object/manager.c
@@ -0,0 +1,115 @@
+/*
+ * 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);
+}