/* * 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 *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; 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); }