From 8a7c8a1ea91fa9058748e3a928bb3ca29593901d Mon Sep 17 00:00:00 2001 From: Bas Wijnen Date: Wed, 30 Dec 2009 14:00:37 +0100 Subject: [PATCH] add lists --- alloc.ccp | 92 +++++++++++++++++++++++++++++++++++++++++++++------- invoke.ccp | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ iris.hhp | 20 ++++++------ kernel.hhp | 25 ++++++++------ 4 files changed, 202 insertions(+), 30 deletions(-) diff --git a/alloc.ccp b/alloc.ccp index 010325a..8d32465 100644 --- a/alloc.ccp +++ b/alloc.ccp @@ -197,15 +197,47 @@ kThread *kMemory::alloc_thread (unsigned size): ret->slot[i].caps = NULL return ret +void kCaps::init (unsigned size): + first_slot.thread = NULL + size = size + for unsigned i = 0; i < size; ++i: + set (i, NULL, 0, kCapRef (), NULL) + +kCaps *kMemory::alloc_caps (unsigned size): + kCaps *ret = (kCaps *)search_free (sizeof (kCaps) + (size - 1) * sizeof (kCapability), (void **)&capses) + if !ret: + return NULL + ret->init (size) + return ret + kMessage *kMemory::alloc_message (kReceiver *target): kMessage *ret = (kMessage *)search_free (sizeof (kMessage) + sizeof (kCapability), (void **)&target->messages) if !ret: return NULL - ret->caps.size = 2 + ret->caps.init (2) if !ret->next: target->last_message = ret return ret +kList *kMemory::alloc_list (): + kList *ret = (kList *)search_free (sizeof (kList), (void **)&lists) + if !ret: + return NULL + ret->owner.init (1) + ret->first_listitem = NULL + return ret + +kListitem *kMemory::alloc_listitem (): + kListitem *ret = (kListitem *)search_free (sizeof (kListitem), (void **)&listitems) + if !ret: + return NULL + ret->target.init (1) + ret->list = NULL + ret->prev_item = NULL + ret->next_item = NULL + ret->info = 0 + return ret + kReceiver *kMemory::alloc_receiver (): kReceiver *ret = (kReceiver *)search_free (sizeof (kReceiver), (void **)&receivers) if !ret: @@ -223,16 +255,6 @@ kReceiver *kMemory::alloc_receiver (): ret->queue_limit = ~0 return ret -kCaps *kMemory::alloc_caps (unsigned size): - kCaps *ret = (kCaps *)search_free (sizeof (kCaps) + (size - 1) * sizeof (kCapability), (void **)&capses) - if !ret: - return NULL - ret->first_slot.thread = NULL - ret->size = size - for unsigned i = 0; i < size; ++i: - ret->set (i, NULL, 0, kCapRef (), NULL) - return ret - kMemory *kMemory::alloc_memory (): kMemory *ret = (kMemory *)search_free (sizeof (kMemory), (void **)&memories) if !ret: @@ -377,6 +399,50 @@ void kMemory::free_caps (kCaps *c): c->first_slot.thread->unset_slot (c->first_slot.index) free_obj (c, (void **)&capses) +void kListitem::add (kList *l): + // Remove item from list. + if list: + if prev_item: + prev_item->next_item = next_item + else: + list->first_listitem = next_item + if next_item: + next_item->prev_item = prev_item + // Notify list owner. + if list->owner.cap (0): + kCapability::Context context + context.data[0] = list->first_listitem != NULL + context.data[1] = info + list->owner.cap (0)->invoke (&context) + // Don't leak info to new owner. + info = 0 + list = l + prev_item = NULL + if !l: + next_item = NULL + return + next_item = l->first_listitem + l->first_listitem = this + if next_item: + next_item->prev_item = this + +void kMemory::free_listitem (kListitem *i): + // Unset target. + i->target.cap (0)->invalidate () + // Remove item from its list. + i->add (NULL) + // Remove item from its address space. + free_obj (i, (void **)&listitems) + +void kMemory::free_list (kList *l): + // Unset callback. + l->owner.cap (0)->invalidate () + // Clear list. + while l->first_listitem: + l->first_listitem->add (NULL) + // Remove list from address space. + free_obj (l, (void **)&lists) + void kMemory::free_memory (kMemory *mem): while mem->pages: free_page (mem->pages) @@ -388,6 +454,10 @@ void kMemory::free_memory (kMemory *mem): free_memory (mem->memories) while mem->receivers: free_receiver (mem->receivers) + while mem->lists: + free_list (mem->lists) + while mem->listitems: + free_listitem (mem->listitems) kMemory_arch_free (mem) if mem->frees: panic (0, "kernel memory leak: memory still in use") diff --git a/invoke.ccp b/invoke.ccp index 8a7395a..b8e377b 100644 --- a/invoke.ccp +++ b/invoke.ccp @@ -774,6 +774,95 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da reply_num (Kernel::ERR_INVALID_OPERATION) return +static void list_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c): + kList *list = (kListP)protected_data.l + if cmd == Kernel::List::SET_CB & REQUEST_MASK: + list->owner.clone (0, c->arg, c->copy[1]) + return + kListitem *item + if !c->arg.valid (): + item = NULL + else: + if ((unsigned)c->arg->target & ~REQUEST_MASK) != CAPTYPE_LISTITEM: + dpanic (0, "invalid request for list: arg is no listitem") + reply_num (~0) + return + item = (kListitem *)c->arg->protected_data.l + if item->list != list: + dpanic (0, "item list is not equal to called object") + reply_num (~0) + return + switch cmd: + case Kernel::List::GET_NEXT & REQUEST_MASK: + if !item: + item = list->first_listitem + else: + if ((unsigned)c->arg->target & REQUEST_MASK) != CAP_MASTER && ((unsigned)c->arg->target & REQUEST_MASK) != Kernel::Listitem::LIST: + dpanic (0, "trying to get next listitem with insufficient rights") + reply_num (~0) + return + item = item->next_item + if !item: + reply_num (0) + return + reply_cap (CAPTYPE_LISTITEM | Kernel::Listitem::LIST, (unsigned)item, &item->refs) + return + case Kernel::List::ADD_ITEM & REQUEST_MASK: + if !item: + dpanic (0, "invalid request: no listitem for List::ADD_ITEM") + reply_num (~0) + return + if ((unsigned)c->arg->target & REQUEST_MASK) != CAP_MASTER && ((unsigned)c->arg->target & REQUEST_MASK) != Kernel::Listitem::ADD: + dpanic (0, "trying to add listitem with insufficient rights") + reply_num (~0) + return + ((kListitem *)c->arg->protected_data.l)->add (list) + break + case Kernel::List::GET_INFO & REQUEST_MASK: + if !item: + dpanic (0, "no item for List::GET_INFO") + reply_num (~0, ~0, ~0) + return + reply_num (item->info) + return + case Kernel::List::SET_INFO & REQUEST_MASK: + if !item: + dpanic (0, "no item for List::SET_INFO") + reply_num (~0) + return + item->info = c->data[1] + break + case Kernel::List::GET_CAP & REQUEST_MASK: + if !item: + dpanic (0, "no item for List::GET_CAP") + reply_num (~0) + return + kCapability *cap = item->target.cap (0) + reply_cap ((unsigned)cap->target, cap->protected_data, ((unsigned)cap->target & ~KERNEL_MASK) == 0 ? &((kObject *)cap->target)->refs : &cap->target->capabilities) + return + default: + dpanic (0, "invalid list operation") + reply_num (Kernel::ERR_INVALID_OPERATION) + return + reply_num (0) + +static void listitem_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c): + kListitem *item = (kListitemP)protected_data.l + switch cmd: + case Kernel::Listitem::CLEAR & REQUEST_MASK: + // Disable linked capability. + item->add (NULL) + break + case Kernel::Listitem::SET_CAP & REQUEST_MASK: + // Set linked capability. + item->target.clone (0, c->arg, c->copy[1]) + break + default: + dpanic (0, "invalid listitem operation") + reply_num (Kernel::ERR_INVALID_OPERATION) + return + reply_num (0) + static void kill_reply (kReceiver *r): kCapRef cap = r->refs while cap.valid (): @@ -854,6 +943,12 @@ static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapabil case CAPTYPE_CAPS: caps_invoke (cmd, target, protected_data, c) break + case CAPTYPE_LIST: + list_invoke (cmd, target, protected_data, c) + break + case CAPTYPE_LISTITEM: + listitem_invoke (cmd, target, protected_data, c) + break default: panic (0x99337744, "invalid capability type invoked") return diff --git a/iris.hhp b/iris.hhp index 2e578c3..4a63138 100644 --- a/iris.hhp +++ b/iris.hhp @@ -432,33 +432,33 @@ namespace Kernel: struct Listitem : public Cap: Listitem (Cap c = Cap ()) : Cap (c): enum request: - REMOVE = CAPTYPE_LISTITEM + 1 - CLEAR + CLEAR = CAPTYPE_LISTITEM + 1 SET_CAP ADD - void remove (): - call (CAP_MASTER_DIRECT | REMOVE) + LIST + // Remove the listitem from its list. void clear (): call (CAP_MASTER_DIRECT | CLEAR) + // Set the capability of an item. void set_cap (Cap c): call (CAP_MASTER_DIRECT | SET_CAP, c.code) - // ADD is called by the kernel on non-listitem objects which are added to a list, to allow virtualization. - // Also, to add a listitem to a list, the listitem capability must be of type ADD or MASTER. + // To add a listitem to a list, the listitem capability must be of type ADD or MASTER. + // A list iterator must be of type LIST or MASTER struct List : public Cap: List (Cap c = Cap ()) : Cap (c): enum request: GET_NEXT = CAPTYPE_LIST + 1 - SET_EMPTY_CB + SET_CB ADD_ITEM GET_INFO SET_INFO GET_CAP Listitem get_next (Listitem current = Listitem ()): - icall (current, CAP_MASTER_DIRECT | GET_NEXT) + iocall (current, CAP_MASTER_DIRECT | GET_NEXT) return get_arg () - void set_empty_cb (Cap cb): - ocall (cb, CAP_MASTER_DIRECT | SET_EMPTY_CB) + void set_cb (Cap cb): + ocall (cb, CAP_MASTER_DIRECT | SET_CB) void add_item (Listitem item): ocall (item, CAP_MASTER_DIRECT | ADD_ITEM) Num get_info (Listitem item): diff --git a/kernel.hhp b/kernel.hhp index da51729..4235eff 100644 --- a/kernel.hhp +++ b/kernel.hhp @@ -180,6 +180,7 @@ struct kCaps : public kObject: return &caps[idx] void set (unsigned index, kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr = NULL) void clone (unsigned index, kCapRef source, bool copy) + void init (unsigned size) struct kMessage : public kObject: Kernel::Num protected_data @@ -187,16 +188,18 @@ struct kMessage : public kObject: // This is a real Caps of two elements, not a link. kCaps caps -struct kListitem : public kObject: - kListitemP prev_item, next_item - kThreadP owner - unsigned cap - Kernel::Num info - struct kList : public kObject: - kListitemP first_item - kThreadP owner - unsigned cb + kListitemP first_listitem + // This is a real Caps of one element, not a link. + kCaps owner + +struct kListitem : public kObject: + kListP list + kListitemP prev_item, next_item + Kernel::Num info + // This is a real Caps of one element, not a link. + kCaps target + void add (kList *l) struct kMemory : public kObject: kFree *frees @@ -229,6 +232,8 @@ struct kMemory : public kObject: kMessage *alloc_message (kReceiver *target) kReceiver *alloc_receiver () kCaps *alloc_caps (unsigned size) + kList *alloc_list () + kListitem *alloc_listitem () kMemory *alloc_memory () void free_page (kPage *page) @@ -236,6 +241,8 @@ struct kMemory : public kObject: void free_message (kReceiver *owner, kMessage *message) void free_receiver (kReceiver *receiver) void free_caps (kCaps *page) + void free_list (kList *list) + void free_listitem (kListitem *listitem) void free_memory (kMemory *mem) void free_obj (kObject *obj, void **first)