BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / commit / 4d3c382801026ca46da937de6d7261f1f6805d9e / object

// Related

Nucleus

Barry Object Lists + replacing Task Queues 4d3c382 (3 years, 3 months ago)
diff --git a/object/list.c b/object/list.c
new file mode 100644
index 0000000..75725e5
--- /dev/null
+++ b/object/list.c
@@ -0,0 +1,146 @@
+/*
+ * This file implements Object Lists.  Objects can be a part of multiple lists
+ * that can be managed automatically by the Object Manager.  This prevents
+ * subsystems having to implement their own object lists for sub-objects.  Each
+ * list is implemented as an Object itself, which allows the common object
+ * routines to be used on them.
+ */
+
+#include <nucleus/object.h>
+#include <nucleus/memory.h>
+
+/* Structure for a List Entry */
+struct ListEntry {
+	struct ListEntry *next;
+	Object *obj;
+};
+/* Structure for an Object List */
+struct ObjectList {
+	struct ListEntry *start, *end;
+	size_t entries;
+	ObjectType *type;
+	Spinlock lock;
+};
+
+void acquire(Spinlock *lock);
+void release(Spinlock *lock);
+
+/* Create an Object List */
+ObjectList *
+create_list(ObjectType *type)
+{
+	ObjectList *list = kmalloc(sizeof(ObjectList));
+	list->type = type;
+	return list;
+}
+
+/* Destroy an Object List */
+void
+destroy_list(ObjectList *list)
+{
+	while (list->start)
+		remove(list, list->start);
+}
+
+/* Add an Object to a List */
+void
+add(ObjectList *list, void *addr)
+{
+	Object *obj = addr;
+	if (list->type && obj->type != list->type)
+		return;
+
+	acquire(&list->lock);
+	struct ListEntry *entry = kmalloc(sizeof(struct ListEntry));
+	if (!list->start)
+		list->start = entry;
+	else
+		list->end->next = entry;
+	list->end = entry;
+	entry->obj = get(obj);
+	list->entries++;
+	release(&list->lock);
+}
+
+/* Remove an Object from a List */
+void
+remove(ObjectList *list, void *addr)
+{
+	Object *obj = addr;
+	if (!list->start)
+		return;
+	if (list->type && obj->type != list->type)
+		return;
+	acquire(&list->lock);
+
+	/* Start of list */
+	struct ListEntry *entry, *prev = NULL;
+	if (list->start->obj == obj) {
+		entry = list->start;
+		list->start = entry->next;
+		goto found;
+	}
+
+	/* Search for object */
+	for (prev = list->start; prev->next; prev = prev->next)
+		if (prev->next->obj == obj)
+			break;
+	if (!prev->next)
+		goto end;
+	entry = prev->next;
+	prev->next = entry->next;
+
+found:
+	if (list->end->obj == obj)
+		list->end = prev;
+	put(obj);
+	list->entries--;
+	kfree(entry);
+end:
+	release(&list->lock);
+}
+
+/* Pop the first Object in a List */
+void *
+pop_from_start(ObjectList *list)
+{
+	if (!list->start)
+		return NULL;
+	acquire(&list->lock);
+	Object *head = get(list->start->obj);
+	remove(list, head);
+	release(&list->lock);
+	return head;
+}
+
+/* Pop the last Object in a List */
+void *
+pop_from_end(ObjectList *list)
+{
+	if (!list->end)
+		return NULL;
+	acquire(&list->lock);
+	Object *tail = get(list->end->obj);
+	remove(list, tail);
+	release(&list->lock);
+	return tail;
+}
+
+/* Count the number of Objects in a List */
+size_t
+count(ObjectList *list)
+{
+	return list->entries;
+}
+
+/* Iterate a List with a callback */
+void
+iterate(ObjectList *list, callback_t callback, void *data)
+{
+	acquire(&list->lock);
+	struct ListEntry *entry;
+	for (entry = list->start; entry; entry = entry->next)
+		if (callback(entry->obj, data))
+			break;
+	release(&list->lock);
+}
diff --git a/object/manager.c b/object/manager.c
index a330d15..124ebbc 100644
--- a/object/manager.c
+++ b/object/manager.c
@@ -7,6 +7,8 @@
  */
 
 #include <nucleus/object.h>
+#include <nucleus/memory.h>
+#include <nucleus/panic.h>
 
 void acquire(Spinlock *lock);
 void release(Spinlock *lock);
@@ -30,14 +32,25 @@ put(void *addr)
 	if (__atomic_sub_fetch(&obj->usage, 1, __ATOMIC_RELAXED))
 		return;
 	__atomic_sub_fetch(&obj->type->count, 1, __ATOMIC_RELAXED);
-	obj->type->delete(obj);
+	if (obj->type->delete)
+		obj->type->delete(obj);
+	if (obj->type->free)
+		obj->type->free(obj);
+	else
+		kfree(obj);
 }
 
 /* Create a new instance of an object */
 void *
 new(ObjectType *type)
 {
-	Object *obj = type->new();
+	Object *obj;
+	if (type->alloc)
+		obj = type->alloc();
+	else
+		obj = kmalloc(type->size);
+	if (type->new)
+		type->new(obj);
 	obj->type = type;
 	__atomic_add_fetch(&type->count, 1, __ATOMIC_RELAXED);
 	return get(obj);