Nucleus
Barry Doubly-linked object lists and copying 7a0d3ef (3 years, 3 months ago)
diff --git a/include/nucleus/object.h b/include/nucleus/object.h
index 63ac2ac..7f9554c 100644
--- a/include/nucleus/object.h
+++ b/include/nucleus/object.h
@@ -10,9 +10,9 @@ typedef struct ObjectType ObjectType;
typedef struct Object Object;
typedef struct ObjectList ObjectList;
-typedef struct Task Task; /* Just a pointer, no need for full definition */
+typedef struct Task Task;
-typedef int (*callback_t)(void *object, void *data);
+typedef int (*iterate_callback_t)(void *object, void *data);
/* Spinlock */
struct Spinlock {
@@ -26,7 +26,6 @@ struct Spinlock {
/* Object Type */
struct ObjectType {
- unsigned int count;
refcount_t usage;
size_t size;
ObjectList *objects;
@@ -34,6 +33,7 @@ struct ObjectType {
void (*free)(Object *);
void (*new)(Object *);
void (*delete)(Object *);
+ void (*copy)(Object *, Object *);
};
/* Object */
@@ -46,6 +46,7 @@ struct Object {
void *get(void *addr);
void put(void *addr);
void *new(ObjectType *type);
+void *copy(void *addr);
void lock(void *addr);
void unlock(void *addr);
@@ -56,6 +57,7 @@ void remove(ObjectList *list, void *addr);
void *pop_from_start(ObjectList *list);
void *pop_from_end(ObjectList *list);
size_t count(ObjectList *list);
-void iterate(ObjectList *list, callback_t callback, void *data);
+void iterate(ObjectList *list, iterate_callback_t callback, void *data);
+ObjectList *copy_list(ObjectList *list);
#endif
diff --git a/object/list.c b/object/list.c
index 3e9b96b..8581330 100644
--- a/object/list.c
+++ b/object/list.c
@@ -11,7 +11,7 @@
/* Structure for a List Entry */
struct ListEntry {
- struct ListEntry *next;
+ struct ListEntry *prev, *next;
Object *obj;
};
/* Structure for an Object List */
@@ -58,6 +58,7 @@ add(ObjectList *list, void *addr)
list->start = entry;
else
list->end->next = entry;
+ entry->prev = list->end;
list->end = entry;
entry->obj = get(obj);
list->entries++;
@@ -75,30 +76,32 @@ remove(ObjectList *list, void *addr)
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 */
+ struct ListEntry *entry;
+ for (entry = list->start;
+ entry && entry->obj != obj;
+ entry = entry->next);
+ if (!entry) {
+ release(&list->lock);
+ return;
}
- /* 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;
+ /* Unlink list */
+ if (list->start == entry)
+ list->start = entry->next;
+ if (list->end == entry)
+ list->end == entry->prev;
+
+ /* Unlink neighbours */
+ if (entry->prev)
+ entry->prev->next = entry->next;
+ if (entry->next)
+ entry->next->prev = entry->prev;
+
+ /* Release resources */
put(obj);
list->entries--;
kfree(entry);
-end:
release(&list->lock);
}
@@ -137,7 +140,7 @@ count(ObjectList *list)
/* Iterate a List with a callback */
void
-iterate(ObjectList *list, callback_t callback, void *data)
+iterate(ObjectList *list, iterate_callback_t callback, void *data)
{
acquire(&list->lock);
struct ListEntry *entry;
@@ -146,3 +149,16 @@ iterate(ObjectList *list, callback_t callback, void *data)
break;
release(&list->lock);
}
+
+/* Copy list */
+ObjectList *
+copy_list(ObjectList *list)
+{
+ ObjectList *newlist = create_list(list->type);
+ acquire(&list->lock);
+ struct ListEntry *entry;
+ for (entry = list->start; entry; entry = entry->next)
+ add(newlist, entry->obj);
+ release(&list->lock);
+ return newlist;
+}
diff --git a/object/manager.c b/object/manager.c
index c50d45d..74b833d 100644
--- a/object/manager.c
+++ b/object/manager.c
@@ -32,7 +32,6 @@ put(void *addr)
__atomic_sub_fetch(&obj->type->usage, 1, __ATOMIC_RELAXED);
if (__atomic_sub_fetch(&obj->usage, 1, __ATOMIC_RELAXED))
return;
- __atomic_sub_fetch(&obj->type->count, 1, __ATOMIC_RELAXED);
if (obj->type->delete)
obj->type->delete(obj);
remove(obj->type->objects, obj);
@@ -47,19 +46,32 @@ void *
new(ObjectType *type)
{
Object *obj;
- if (type->alloc)
+ if (type->alloc && type->free)
obj = type->alloc();
else
obj = kmalloc(type->size);
+ init_lock(&obj->lock);
+ obj->type = type;
if (type->new)
type->new(obj);
if (!type->objects)
type->objects = create_list(type);
add(type->objects, obj);
- init_lock(&obj->lock);
- obj->type = type;
- __atomic_add_fetch(&type->count, 1, __ATOMIC_RELAXED);
- return get(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;
+ if (parent->type->copy) {
+ child = new(parent->type);
+ parent->type->copy(parent, child);
+ }
+ return child;
}
/* Lock an object */