Nucleus
Barry Object Lists + replacing Task Queues 4d3c382 (3 years, 3 months ago)
/*
* 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);
}