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