mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-11-16 20:44:05 +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
|
ret->slot[i].caps = NULL
|
||||||
return ret
|
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 *kMemory::alloc_message (kReceiver *target):
|
||||||
kMessage *ret = (kMessage *)search_free (sizeof (kMessage) + sizeof (kCapability), (void **)&target->messages)
|
kMessage *ret = (kMessage *)search_free (sizeof (kMessage) + sizeof (kCapability), (void **)&target->messages)
|
||||||
if !ret:
|
if !ret:
|
||||||
return NULL
|
return NULL
|
||||||
ret->caps.size = 2
|
ret->caps.init (2)
|
||||||
if !ret->next:
|
if !ret->next:
|
||||||
target->last_message = ret
|
target->last_message = ret
|
||||||
return 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 *kMemory::alloc_receiver ():
|
||||||
kReceiver *ret = (kReceiver *)search_free (sizeof (kReceiver), (void **)&receivers)
|
kReceiver *ret = (kReceiver *)search_free (sizeof (kReceiver), (void **)&receivers)
|
||||||
if !ret:
|
if !ret:
|
||||||
@ -223,16 +255,6 @@ kReceiver *kMemory::alloc_receiver ():
|
|||||||
ret->queue_limit = ~0
|
ret->queue_limit = ~0
|
||||||
return ret
|
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 *kMemory::alloc_memory ():
|
||||||
kMemory *ret = (kMemory *)search_free (sizeof (kMemory), (void **)&memories)
|
kMemory *ret = (kMemory *)search_free (sizeof (kMemory), (void **)&memories)
|
||||||
if !ret:
|
if !ret:
|
||||||
@ -377,6 +399,50 @@ void kMemory::free_caps (kCaps *c):
|
|||||||
c->first_slot.thread->unset_slot (c->first_slot.index)
|
c->first_slot.thread->unset_slot (c->first_slot.index)
|
||||||
free_obj (c, (void **)&capses)
|
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):
|
void kMemory::free_memory (kMemory *mem):
|
||||||
while mem->pages:
|
while mem->pages:
|
||||||
free_page (mem->pages)
|
free_page (mem->pages)
|
||||||
@ -388,6 +454,10 @@ void kMemory::free_memory (kMemory *mem):
|
|||||||
free_memory (mem->memories)
|
free_memory (mem->memories)
|
||||||
while mem->receivers:
|
while mem->receivers:
|
||||||
free_receiver (mem->receivers)
|
free_receiver (mem->receivers)
|
||||||
|
while mem->lists:
|
||||||
|
free_list (mem->lists)
|
||||||
|
while mem->listitems:
|
||||||
|
free_listitem (mem->listitems)
|
||||||
kMemory_arch_free (mem)
|
kMemory_arch_free (mem)
|
||||||
if mem->frees:
|
if mem->frees:
|
||||||
panic (0, "kernel memory leak: memory still in use")
|
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)
|
reply_num (Kernel::ERR_INVALID_OPERATION)
|
||||||
return
|
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):
|
static void kill_reply (kReceiver *r):
|
||||||
kCapRef cap = r->refs
|
kCapRef cap = r->refs
|
||||||
while cap.valid ():
|
while cap.valid ():
|
||||||
@ -854,6 +943,12 @@ static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapabil
|
|||||||
case CAPTYPE_CAPS:
|
case CAPTYPE_CAPS:
|
||||||
caps_invoke (cmd, target, protected_data, c)
|
caps_invoke (cmd, target, protected_data, c)
|
||||||
break
|
break
|
||||||
|
case CAPTYPE_LIST:
|
||||||
|
list_invoke (cmd, target, protected_data, c)
|
||||||
|
break
|
||||||
|
case CAPTYPE_LISTITEM:
|
||||||
|
listitem_invoke (cmd, target, protected_data, c)
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
panic (0x99337744, "invalid capability type invoked")
|
panic (0x99337744, "invalid capability type invoked")
|
||||||
return
|
return
|
||||||
|
20
iris.hhp
20
iris.hhp
@ -432,33 +432,33 @@ namespace Kernel:
|
|||||||
struct Listitem : public Cap:
|
struct Listitem : public Cap:
|
||||||
Listitem (Cap c = Cap ()) : Cap (c):
|
Listitem (Cap c = Cap ()) : Cap (c):
|
||||||
enum request:
|
enum request:
|
||||||
REMOVE = CAPTYPE_LISTITEM + 1
|
CLEAR = CAPTYPE_LISTITEM + 1
|
||||||
CLEAR
|
|
||||||
SET_CAP
|
SET_CAP
|
||||||
ADD
|
ADD
|
||||||
void remove ():
|
LIST
|
||||||
call (CAP_MASTER_DIRECT | REMOVE)
|
// Remove the listitem from its list.
|
||||||
void clear ():
|
void clear ():
|
||||||
call (CAP_MASTER_DIRECT | CLEAR)
|
call (CAP_MASTER_DIRECT | CLEAR)
|
||||||
|
// Set the capability of an item.
|
||||||
void set_cap (Cap c):
|
void set_cap (Cap c):
|
||||||
call (CAP_MASTER_DIRECT | SET_CAP, c.code)
|
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.
|
// To add a listitem to a list, the listitem capability must be of type ADD or MASTER.
|
||||||
// Also, 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:
|
struct List : public Cap:
|
||||||
List (Cap c = Cap ()) : Cap (c):
|
List (Cap c = Cap ()) : Cap (c):
|
||||||
enum request:
|
enum request:
|
||||||
GET_NEXT = CAPTYPE_LIST + 1
|
GET_NEXT = CAPTYPE_LIST + 1
|
||||||
SET_EMPTY_CB
|
SET_CB
|
||||||
ADD_ITEM
|
ADD_ITEM
|
||||||
GET_INFO
|
GET_INFO
|
||||||
SET_INFO
|
SET_INFO
|
||||||
GET_CAP
|
GET_CAP
|
||||||
Listitem get_next (Listitem current = Listitem ()):
|
Listitem get_next (Listitem current = Listitem ()):
|
||||||
icall (current, CAP_MASTER_DIRECT | GET_NEXT)
|
iocall (current, CAP_MASTER_DIRECT | GET_NEXT)
|
||||||
return get_arg ()
|
return get_arg ()
|
||||||
void set_empty_cb (Cap cb):
|
void set_cb (Cap cb):
|
||||||
ocall (cb, CAP_MASTER_DIRECT | SET_EMPTY_CB)
|
ocall (cb, CAP_MASTER_DIRECT | SET_CB)
|
||||||
void add_item (Listitem item):
|
void add_item (Listitem item):
|
||||||
ocall (item, CAP_MASTER_DIRECT | ADD_ITEM)
|
ocall (item, CAP_MASTER_DIRECT | ADD_ITEM)
|
||||||
Num get_info (Listitem item):
|
Num get_info (Listitem item):
|
||||||
|
25
kernel.hhp
25
kernel.hhp
@ -180,6 +180,7 @@ struct kCaps : public kObject:
|
|||||||
return &caps[idx]
|
return &caps[idx]
|
||||||
void set (unsigned index, kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr = NULL)
|
void set (unsigned index, kReceiver *target, Kernel::Num pdata, kCapRef parent, kCapRef *parent_ptr = NULL)
|
||||||
void clone (unsigned index, kCapRef source, bool copy)
|
void clone (unsigned index, kCapRef source, bool copy)
|
||||||
|
void init (unsigned size)
|
||||||
|
|
||||||
struct kMessage : public kObject:
|
struct kMessage : public kObject:
|
||||||
Kernel::Num protected_data
|
Kernel::Num protected_data
|
||||||
@ -187,16 +188,18 @@ struct kMessage : public kObject:
|
|||||||
// This is a real Caps of two elements, not a link.
|
// This is a real Caps of two elements, not a link.
|
||||||
kCaps caps
|
kCaps caps
|
||||||
|
|
||||||
struct kListitem : public kObject:
|
|
||||||
kListitemP prev_item, next_item
|
|
||||||
kThreadP owner
|
|
||||||
unsigned cap
|
|
||||||
Kernel::Num info
|
|
||||||
|
|
||||||
struct kList : public kObject:
|
struct kList : public kObject:
|
||||||
kListitemP first_item
|
kListitemP first_listitem
|
||||||
kThreadP owner
|
// This is a real Caps of one element, not a link.
|
||||||
unsigned cb
|
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:
|
struct kMemory : public kObject:
|
||||||
kFree *frees
|
kFree *frees
|
||||||
@ -229,6 +232,8 @@ struct kMemory : public kObject:
|
|||||||
kMessage *alloc_message (kReceiver *target)
|
kMessage *alloc_message (kReceiver *target)
|
||||||
kReceiver *alloc_receiver ()
|
kReceiver *alloc_receiver ()
|
||||||
kCaps *alloc_caps (unsigned size)
|
kCaps *alloc_caps (unsigned size)
|
||||||
|
kList *alloc_list ()
|
||||||
|
kListitem *alloc_listitem ()
|
||||||
kMemory *alloc_memory ()
|
kMemory *alloc_memory ()
|
||||||
|
|
||||||
void free_page (kPage *page)
|
void free_page (kPage *page)
|
||||||
@ -236,6 +241,8 @@ struct kMemory : public kObject:
|
|||||||
void free_message (kReceiver *owner, kMessage *message)
|
void free_message (kReceiver *owner, kMessage *message)
|
||||||
void free_receiver (kReceiver *receiver)
|
void free_receiver (kReceiver *receiver)
|
||||||
void free_caps (kCaps *page)
|
void free_caps (kCaps *page)
|
||||||
|
void free_list (kList *list)
|
||||||
|
void free_listitem (kListitem *listitem)
|
||||||
void free_memory (kMemory *mem)
|
void free_memory (kMemory *mem)
|
||||||
|
|
||||||
void free_obj (kObject *obj, void **first)
|
void free_obj (kObject *obj, void **first)
|
||||||
|
Loading…
Reference in New Issue
Block a user