mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-02-28 22:47:56 +02:00
implement reference counting for slots
This commit is contained in:
parent
1e6f089025
commit
589ffa3d01
24
alloc.ccp
24
alloc.ccp
@ -179,7 +179,7 @@ kPage *kMemory::alloc_page ():
|
||||
return ret
|
||||
|
||||
kThread *kMemory::alloc_thread (unsigned size):
|
||||
kThread *ret = (kThread *)search_free (sizeof (kThread) + (size - 1) * sizeof (kCapsP), (void **)&threads)
|
||||
kThread *ret = (kThread *)search_free (sizeof (kThread) + (size - 1) * sizeof (kThread::caps_store), (void **)&threads)
|
||||
if !ret:
|
||||
return NULL
|
||||
ret->receivers = NULL
|
||||
@ -191,7 +191,9 @@ kThread *kMemory::alloc_thread (unsigned size):
|
||||
ret->schedule_next = NULL
|
||||
ret->slots = size
|
||||
for unsigned i = 0; i < size; ++i:
|
||||
ret->caps[i] = NULL
|
||||
ret->slot[i].prev.thread = NULL
|
||||
ret->slot[i].next.thread = NULL
|
||||
ret->slot[i].caps = NULL
|
||||
return ret
|
||||
|
||||
kMessage *kMemory::alloc_message (kReceiver *target):
|
||||
@ -224,6 +226,7 @@ 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)
|
||||
@ -283,10 +286,25 @@ void kMemory::free_page (kPage *page):
|
||||
pfree (page->frame)
|
||||
free_obj (page, (kPointer *)&pages)
|
||||
|
||||
void kThread::unset_slot (unsigned s):
|
||||
if !slot[s].caps:
|
||||
return
|
||||
if slot[s].prev.thread:
|
||||
slot[s].prev.thread->slot[slot[s].prev.index].next = slot[s].next
|
||||
else:
|
||||
slot[s].caps->first_slot = slot[s].next
|
||||
if slot[s].next.thread:
|
||||
slot[s].next.thread->slot[slot[s].next.index].prev = slot[s].prev
|
||||
slot[s].prev.thread = NULL
|
||||
slot[s].next.thread = NULL
|
||||
slot[s].caps = NULL
|
||||
|
||||
void kMemory::free_thread (kThread *thread):
|
||||
thread->unrun ()
|
||||
while thread->receivers:
|
||||
thread->receivers->orphan ()
|
||||
for unsigned i = 0; i < thread->slots; ++i:
|
||||
thread->unset_slot (i)
|
||||
free_obj (thread, (void **)&threads)
|
||||
|
||||
void kMemory::free_message (kReceiver *owner, kMessage *message):
|
||||
@ -352,6 +370,8 @@ void kCapability::invalidate ():
|
||||
void kMemory::free_caps (kCaps *c):
|
||||
for unsigned i = 0; i < c->size; ++i:
|
||||
c->caps[i].invalidate ()
|
||||
while c->first_slot.thread:
|
||||
c->first_slot.thread->unset_slot (c->first_slot.index)
|
||||
free_obj (c, (void **)&capses)
|
||||
|
||||
void kMemory::free_memory (kMemory *mem):
|
||||
|
28
invoke.ccp
28
invoke.ccp
@ -63,19 +63,19 @@ void kThread::raise (unsigned code, unsigned data):
|
||||
dbg_log_num (data)
|
||||
dbg_log_char ('\n')
|
||||
unrun ()
|
||||
if slots < 1 || !caps[0] || !caps[0]->cap (0)->target:
|
||||
if slots < 1 || !slot[0].caps || !slot[0].caps->cap (0)->target:
|
||||
return
|
||||
kCapability::Context c
|
||||
c.data[0] = Kernel::Num (code, data)
|
||||
caps[0]->cap (0)->invoke (&c)
|
||||
slot[0].caps->cap (0)->invoke (&c)
|
||||
|
||||
// From user-provided, thus untrusted, data, find a capability.
|
||||
kCapRef kThread::find_capability (unsigned code, bool *copy):
|
||||
*copy = code & CAP_COPY
|
||||
unsigned c = code & ~CAP_COPY
|
||||
unsigned slot = c >> 16
|
||||
unsigned s = c >> 16
|
||||
unsigned num = c & 0xffff
|
||||
if slot >= slots || !caps[slot] || num >= caps[slot]->size:
|
||||
if s >= slots || !slot[s].caps || num >= slot[s].caps->size:
|
||||
if c != CAP_NONE:
|
||||
dpanic (code, "debug")
|
||||
dbg_log_num ((unsigned)old_current)
|
||||
@ -84,15 +84,15 @@ kCapRef kThread::find_capability (unsigned code, bool *copy):
|
||||
dbg_log_char ('\n')
|
||||
dbg_log_num (num)
|
||||
dbg_log_char (':')
|
||||
dbg_log_num (slot)
|
||||
dbg_log_num (s)
|
||||
dbg_log (" > ")
|
||||
if caps[slot]:
|
||||
dbg_log_num (caps[slot]->size)
|
||||
if slot[s].caps:
|
||||
dbg_log_num (slot[s].caps->size)
|
||||
else:
|
||||
dbg_log ("no caps")
|
||||
dbg_log_char ('\n')
|
||||
return kCapRef ()
|
||||
return kCapRef (caps[slot], num)
|
||||
return kCapRef (slot[s].caps, num)
|
||||
|
||||
// Try to deliver a message.
|
||||
bool kReceiver::try_deliver ():
|
||||
@ -428,16 +428,18 @@ static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
|
||||
if slot >= thread->slots:
|
||||
dpanic (0, "using invalid slot")
|
||||
return
|
||||
if thread->caps[slot]:
|
||||
// TODO: invalidate slot.
|
||||
thread->caps[slot] = new_caps
|
||||
thread->unset_slot (slot)
|
||||
thread->slot[slot].caps = new_caps
|
||||
if new_caps:
|
||||
// TODO: link it into a list.
|
||||
thread->slot[slot].next = new_caps->first_slot
|
||||
thread->slot[slot].caps = new_caps
|
||||
new_caps->first_slot.thread = thread
|
||||
new_caps->first_slot.index = slot
|
||||
break
|
||||
case Kernel::Thread::GET_CAPS & REQUEST_MASK:
|
||||
unsigned slot = c->data[1].l
|
||||
if slot < thread->slots:
|
||||
reply_cap (CAPTYPE_CAPS | CAP_MASTER, (unsigned)thread->caps[slot], &thread->caps[slot]->refs, thread->slots)
|
||||
reply_cap (CAPTYPE_CAPS | CAP_MASTER, (unsigned)thread->slot[slot].caps, &thread->slot[slot].caps->refs, thread->slots)
|
||||
else:
|
||||
reply_num (thread->slots)
|
||||
return
|
||||
|
12
kernel.hhp
12
kernel.hhp
@ -94,6 +94,10 @@ struct kCapability : public kObject:
|
||||
inline void invoke (kCapability::Context *c)
|
||||
void invalidate ()
|
||||
|
||||
struct _slot_data:
|
||||
kThreadP thread
|
||||
unsigned index
|
||||
|
||||
struct kThread : public kObject:
|
||||
kReceiverP receivers
|
||||
unsigned pc, sp
|
||||
@ -103,8 +107,11 @@ struct kThread : public kObject:
|
||||
unsigned recv_reply, recv_arg
|
||||
// caps is an array of slots pointers to kCapses.
|
||||
unsigned slots
|
||||
// TODO: handle freeing of capses which are in use.
|
||||
kCapsP caps[1]
|
||||
struct caps_store:
|
||||
_slot_data prev, next
|
||||
kCapsP caps
|
||||
caps_store slot[1]
|
||||
void unset_slot (unsigned s)
|
||||
void raise (unsigned code, unsigned data)
|
||||
void run ()
|
||||
void unrun ()
|
||||
@ -145,6 +152,7 @@ struct kPage : public kObject:
|
||||
void forget ()
|
||||
|
||||
struct kCaps : public kObject:
|
||||
_slot_data first_slot
|
||||
unsigned size
|
||||
kCapability caps[1]
|
||||
kCapability *cap (unsigned idx):
|
||||
|
@ -201,22 +201,24 @@ static void init_threads ():
|
||||
if !stackpage || !mem->map (stackpage, 0x7ffff000):
|
||||
panic (0x13151719, "unable to map initial stack page")
|
||||
return
|
||||
thread->caps[0] = mem->alloc_caps (NUM_CAPS)
|
||||
thread->slot[0].caps = mem->alloc_caps (NUM_CAPS)
|
||||
thread->slot[0].caps->first_slot.thread = thread
|
||||
thread->slot[0].caps->first_slot.index = 0
|
||||
thread->arch.a[0] = NUM_SLOTS
|
||||
thread->arch.a[1] = NUM_CAPS
|
||||
kReceiver *recv = mem->alloc_receiver ()
|
||||
recv->owner = thread
|
||||
thread->receivers = recv
|
||||
thread->caps[0]->set (__receiver_num, (kReceiverP)(CAPTYPE_RECEIVER | CAP_MASTER), Kernel::Num ((unsigned)recv), kCapRef (), &recv->refs)
|
||||
thread->caps[0]->set (__thread_num, (kReceiverP)(CAPTYPE_THREAD | CAP_MASTER), Kernel::Num ((unsigned)thread), kCapRef (), &thread->refs)
|
||||
thread->caps[0]->set (__memory_num, (kReceiverP)(CAPTYPE_MEMORY | CAP_MASTER), Kernel::Num ((unsigned)mem), kCapRef (), &mem->refs)
|
||||
thread->caps[0]->set (__call_num, (kReceiverP)(CAPTYPE_RECEIVER | Kernel::Receiver::CALL), Kernel::Num ((unsigned)recv), kCapRef (), &recv->refs)
|
||||
thread->slot[0].caps->set (__receiver_num, (kReceiverP)(CAPTYPE_RECEIVER | CAP_MASTER), Kernel::Num ((unsigned)recv), kCapRef (), &recv->refs)
|
||||
thread->slot[0].caps->set (__thread_num, (kReceiverP)(CAPTYPE_THREAD | CAP_MASTER), Kernel::Num ((unsigned)thread), kCapRef (), &thread->refs)
|
||||
thread->slot[0].caps->set (__memory_num, (kReceiverP)(CAPTYPE_MEMORY | CAP_MASTER), Kernel::Num ((unsigned)mem), kCapRef (), &mem->refs)
|
||||
thread->slot[0].caps->set (__call_num, (kReceiverP)(CAPTYPE_RECEIVER | Kernel::Receiver::CALL), Kernel::Num ((unsigned)recv), kCapRef (), &recv->refs)
|
||||
thread->flags = Kernel::Thread::RUNNING | Kernel::Thread::PRIV
|
||||
if !i:
|
||||
first_scheduled = thread
|
||||
init_receiver = recv
|
||||
else:
|
||||
thread->caps[0]->set (__parent_num, init_receiver, i, kCapRef (), &init_receiver->capabilities)
|
||||
thread->slot[0].caps->set (__parent_num, init_receiver, i, kCapRef (), &init_receiver->capabilities)
|
||||
previous->schedule_next = thread
|
||||
thread->schedule_prev = previous
|
||||
thread->schedule_next = NULL
|
||||
|
Loading…
x
Reference in New Issue
Block a user