1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-12-29 03:12:04 +02:00

add lists

This commit is contained in:
Bas Wijnen 2009-12-30 14:00:37 +01:00
parent 7bda3ba03f
commit 8a7c8a1ea9
4 changed files with 202 additions and 30 deletions

View File

@ -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")

View File

@ -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

View File

@ -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):

View File

@ -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)