mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-11-16 18:03:08 +02:00
add lists
This commit is contained in:
parent
7bda3ba03f
commit
8a7c8a1ea9
92
alloc.ccp
92
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")
|
||||
|
95
invoke.ccp
95
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
|
||||
|
20
iris.hhp
20
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):
|
||||
|
25
kernel.hhp
25
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)
|
||||
|
Loading…
Reference in New Issue
Block a user