1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-07-01 01:29:31 +03:00

implement reference counting for slots

This commit is contained in:
Bas Wijnen 2009-09-08 21:20:30 +02:00
parent 1e6f089025
commit 589ffa3d01
4 changed files with 55 additions and 23 deletions

View File

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

View File

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

View File

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

View File

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