/* * 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 #include /* Structure for a List Entry */ struct ListEntry { struct ListEntry *prev, *next; Object *obj; }; /* Structure for an Object List */ struct ObjectList { struct ListEntry *start, *end; size_t entries; ObjectType *type; Spinlock lock; }; void init_lock(Spinlock *lock); void acquire(Spinlock *lock); void release(Spinlock *lock); /* Create an Object List */ ObjectList * create_list(ObjectType *type) { ObjectList *list = kmalloc(sizeof(ObjectList)); init_lock(&list->lock); 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; entry->prev = list->end; 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); /* Search for object */ struct ListEntry *entry; for (entry = list->start; entry && entry->obj != obj; entry = entry->next); if (!entry) { release(&list->lock); return; } /* 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); 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, iterate_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); } /* 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; }