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