Nucleus
Barry Ordered object lists 74ee43c (3 years, 2 months ago)
diff --git a/include/nucleus/object.h b/include/nucleus/object.h
index f7e9cf9..b86a86f 100644
--- a/include/nucleus/object.h
+++ b/include/nucleus/object.h
@@ -10,7 +10,7 @@ typedef struct ObjectType ObjectType;
typedef struct Object Object;
typedef struct ObjectList ObjectList;
typedef struct Iterator Iterator;
-
+typedef int (*compare_callback_t)(void *, void *);
typedef struct Task Task;
/* Spinlock */
@@ -45,6 +45,12 @@ struct Object {
};
#define OBJECT_MAGIC 0x10032004
+/* Object List modes */
+enum ListMode {
+ LIST_NORMAL,
+ LIST_ORDERED,
+};
+
void *get(void *addr);
void put(void *addr);
void *new(ObjectType *type);
@@ -53,7 +59,7 @@ refcount_t usage(void *addr);
void lock(void *addr);
void unlock(void *addr);
-ObjectList *create_list(ObjectType *type);
+ObjectList *create_list(ObjectType *type, enum ListMode mode, ...);
void destroy_list(ObjectList *list);
void add(ObjectList *list, void *addr);
void remove(ObjectList *list, void *addr);
diff --git a/memory/region.c b/memory/region.c
index 3cf9fa4..bea28ca 100644
--- a/memory/region.c
+++ b/memory/region.c
@@ -38,7 +38,7 @@ static void
vm_new(Object *obj)
{
VirtualMemory *vm = (void *) obj;
- vm->regions = create_list(&vmRegionType);
+ vm->regions = create_list(&vmRegionType, LIST_NORMAL);
}
/* Destroy a Virtual Memory object */
diff --git a/object/list.c b/object/list.c
index e1b2d08..914a303 100644
--- a/object/list.c
+++ b/object/list.c
@@ -6,6 +6,7 @@
* routines to be used on them.
*/
+#include <stdarg.h>
#include <nucleus/object.h>
#include <nucleus/memory.h>
#include <nucleus/panic.h>
@@ -20,6 +21,8 @@ struct ObjectList {
struct ListEntry *start, *end;
size_t entries;
ObjectType *type;
+ enum ListMode mode;
+ compare_callback_t compare;
Spinlock lock;
};
/* Iterator */
@@ -35,11 +38,20 @@ void release(Spinlock *lock);
/* Create an Object List */
ObjectList *
-create_list(ObjectType *type)
+create_list(ObjectType *type, enum ListMode mode, ...)
{
ObjectList *list = kmalloc(sizeof(ObjectList));
init_lock(&list->lock);
list->type = type;
+ list->mode = mode;
+
+ if (mode == LIST_ORDERED) {
+ va_list args;
+ va_start(args, mode);
+ list->compare = va_arg(args, compare_callback_t);
+ va_end(args);
+ }
+
return list;
}
@@ -61,15 +73,39 @@ add(ObjectList *list, void *addr)
return;
acquire(&list->lock);
- struct ListEntry *entry = kmalloc(sizeof(struct ListEntry));
- if (!list->start)
- list->start = entry;
- else
- list->end->next = entry;
- entry->prev = list->end;
- list->end = entry;
+
+ struct ListEntry *entry, *next;
+ entry = kmalloc(sizeof(struct ListEntry));
entry->obj = get(obj);
list->entries++;
+
+ if (!list->start) {
+ /* Only item in list */
+ list->start = list->end = entry;
+ } else if (list->compare) {
+ /* Find next item */
+ for (next = list->start; next; next = next->next) {
+ if (list->compare(next->obj, obj) > 0)
+ break;
+ }
+ if (!next)
+ goto end;
+ /* Add in */
+ entry->prev = next->prev;
+ entry->next = next;
+ next->prev = entry;
+ if (entry->prev)
+ entry->prev->next = entry;
+ else
+ list->start = entry;
+ } else {
+end:
+ /* Add to end of list */
+ list->end->next = entry;
+ entry->prev = list->end;
+ list->end = entry;
+ }
+
release(&list->lock);
}
@@ -172,7 +208,8 @@ get_nth_item(ObjectList *list, off_t n)
ObjectList *
copy_list(ObjectList *list)
{
- ObjectList *newlist = create_list(list->type);
+ ObjectList *newlist = create_list(list->type, list->mode,
+ list->compare);
acquire(&list->lock);
struct ListEntry *entry;
for (entry = list->start; entry; entry = entry->next)
diff --git a/object/manager.c b/object/manager.c
index 85f5360..a274408 100644
--- a/object/manager.c
+++ b/object/manager.c
@@ -58,7 +58,7 @@ new(ObjectType *type)
if (type->new)
type->new(obj);
if (!type->objects)
- type->objects = create_list(type);
+ type->objects = create_list(type, LIST_NORMAL);
add(type->objects, obj);
/* No need to get() since it's in the global list */
return obj;
diff --git a/task/scheduler.c b/task/scheduler.c
index 3a9605c..dc7551f 100644
--- a/task/scheduler.c
+++ b/task/scheduler.c
@@ -95,5 +95,5 @@ init_scheduler(void)
{
enum Priority p;
for (p = 0; p < PRIORITY_COUNT; p++)
- readyQueue[p] = create_list(&taskType);
+ readyQueue[p] = create_list(&taskType, LIST_NORMAL);
}
diff --git a/vfs/inode.c b/vfs/inode.c
index e4ed8a8..8197127 100644
--- a/vfs/inode.c
+++ b/vfs/inode.c
@@ -33,8 +33,8 @@ static void
inode_new(Object *obj)
{
Inode *inode = (void *) obj;
- inode->dirEntries = create_list(&dirEntryType);
- inode->pages = create_list(&pageType);
+ inode->dirEntries = create_list(&dirEntryType, LIST_NORMAL);
+ inode->pages = create_list(&pageType, LIST_NORMAL);
}
/* Destroy an Inode */
diff --git a/vfs/namespace.c b/vfs/namespace.c
index 638453f..1b102af 100644
--- a/vfs/namespace.c
+++ b/vfs/namespace.c
@@ -25,7 +25,7 @@ static void
file_system_new(Object *obj)
{
FileSystem *fs = (void *) obj;
- fs->cwdPath = create_list(&dirEntryType);
+ fs->cwdPath = create_list(&dirEntryType, LIST_NORMAL);
}
/* Destory a File System object */
diff --git a/vfs/open.c b/vfs/open.c
index ff7fd01..9dd8978 100644
--- a/vfs/open.c
+++ b/vfs/open.c
@@ -32,7 +32,7 @@ lookup(const char *path, ObjectList *newcustody)
if (*p == '/') {
inode = current->fs->root;
while (*++p == '/');
- custody = create_list(&dirEntryType);
+ custody = create_list(&dirEntryType, LIST_NORMAL);
} else {
inode = current->fs->cwd;
custody = copy_list(current->fs->cwdPath);
@@ -125,7 +125,7 @@ open(const char *name, int flags, ...)
return -EMFILE;
/* Find inode */
- ObjectList *custody = create_list(&dirEntryType);
+ ObjectList *custody = create_list(&dirEntryType, LIST_NORMAL);
Inode *inode = lookup(name, custody);
DirEntry *entry;
va_list args;
@@ -197,7 +197,7 @@ mkdir(const char *pathname, mode_t mode)
if (!verify_access(pathname, strnlen(pathname, PATH_MAX), PROT_READ))
return -EFAULT;
int err;
- ObjectList *custody = create_list(&dirEntryType);
+ ObjectList *custody = create_list(&dirEntryType, LIST_NORMAL);
Inode *inode = lookup(pathname, custody);
if (inode) {
err = -EEXIST;
@@ -235,7 +235,7 @@ mknod(const char *pathname, mode_t mode, dev_t dev)
if (!verify_access(pathname, strnlen(pathname, PATH_MAX), PROT_READ))
return -EFAULT;
int err;
- ObjectList *custody = create_list(&dirEntryType);
+ ObjectList *custody = create_list(&dirEntryType, LIST_NORMAL);
Inode *inode = lookup(pathname, custody);
if (inode) {
err = -EEXIST;
diff --git a/vfs/superblock.c b/vfs/superblock.c
index 6c3776f..94100aa 100644
--- a/vfs/superblock.c
+++ b/vfs/superblock.c
@@ -25,7 +25,7 @@ static void
super_block_new(Object *obj)
{
SuperBlock *sb = (void *) obj;
- sb->inodes = create_list(&inodeType);
+ sb->inodes = create_list(&inodeType, LIST_NORMAL);
}
/* Destroy SuperBlock object */