mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-02-06 10:31:05 +02:00
improve init; make destroy simpler
This commit is contained in:
parent
12bfb320f7
commit
c8f7b1c678
@ -379,10 +379,6 @@ void kMemory::free_receiver (kReceiver *receiver):
|
||||
while receiver->messages:
|
||||
free_message (receiver, receiver->messages)
|
||||
free_obj (receiver, (void **)&receivers)
|
||||
if receiver == reply_target:
|
||||
reply_target = NULL
|
||||
// Signal that it is correct to not reply here.
|
||||
reply_protected.l = 1
|
||||
|
||||
void kReceiver::orphan ():
|
||||
if prev_owned:
|
||||
|
@ -295,7 +295,7 @@ Iris::Num start ():
|
||||
Iris::Elfrun elfrun_cap = elfrun.get (0)
|
||||
Iris::free_cap (elfrun)
|
||||
Iris::String init_string = find (root, INIT_NAME)
|
||||
Iris::Caps init_caps = elfrun_cap.run_string (top_memory.copy (), init_string.copy (), parent_cap.copy ())
|
||||
Iris::Caps init_caps = elfrun_cap.run_string (top_memory.copy (), init_string.copy (), parent_cap.copy (), 8, 63)
|
||||
|
||||
Iris::Thread init = init_caps.get (__thread_num)
|
||||
init.make_priv ()
|
||||
|
18
init.config
18
init.config
@ -1,8 +1,8 @@
|
||||
# load <name> = '<filename>' load a file into memory. Don't use this after killbootthreads.
|
||||
load session = "session.config"
|
||||
#load session = "session.config"
|
||||
load driver_lcd = "lcd.elf"
|
||||
load driver_buzzer = "buzzer.elf"
|
||||
load driver_gpio = "gpio.elf"
|
||||
#load driver_buzzer = "buzzer.elf"
|
||||
#load driver_gpio = "gpio.elf"
|
||||
# load driver_audio = "audio.elf"
|
||||
# load driver_udc = "udc.elf"
|
||||
# load driver_nand = "nand.elf"
|
||||
@ -19,17 +19,17 @@
|
||||
# receive <name> / <type> [, <index>] = <cap> prepare to accept a capability from a named program.
|
||||
receive driver_lcd / Display = display
|
||||
receive driver_lcd / Setting = display_bright
|
||||
receive driver_buzzer / Buzzer = buzzer
|
||||
receive driver_gpio / Keyboard , 0 = keyboard
|
||||
receive driver_gpio / Keyboard , 1 = sysreq
|
||||
#receive driver_buzzer / Buzzer = buzzer
|
||||
#receive driver_gpio / Keyboard , 0 = keyboard
|
||||
#receive driver_gpio / Keyboard , 1 = sysreq
|
||||
# receive driver_audio / Audio = audio
|
||||
# receive driver_udc / Udc = udc
|
||||
# receive driver_nand / WString = nand
|
||||
|
||||
# driver <name> run a previously loaded program priviledged.
|
||||
driver driver_lcd
|
||||
driver driver_buzzer
|
||||
driver driver_gpio
|
||||
#driver driver_buzzer
|
||||
#driver driver_gpio
|
||||
# driver driver_audio
|
||||
# driver driver_udc
|
||||
# driver driver_nand
|
||||
@ -56,4 +56,4 @@
|
||||
# run emu_udc
|
||||
|
||||
# include <name> include a loaded file as another config file.
|
||||
include session
|
||||
#include session
|
||||
|
17
invoke.ccp
17
invoke.ccp
@ -168,10 +168,8 @@ static void reply_num (Iris::Num num):
|
||||
c.data[1] = 0
|
||||
if reply_target:
|
||||
reply_target->send_message (reply_protected, &c)
|
||||
else if reply_protected.l == 0:
|
||||
else
|
||||
dpanic (0, "nothing to reply to")
|
||||
else:
|
||||
kdebug ("not replying, because receiver was destroyed in the operation\n")
|
||||
|
||||
static void reply_num (unsigned num1, unsigned num2 = 0, unsigned num3 = 0):
|
||||
kCapability::Context c
|
||||
@ -179,17 +177,12 @@ static void reply_num (unsigned num1, unsigned num2 = 0, unsigned num3 = 0):
|
||||
c.data[1] = num3
|
||||
if reply_target:
|
||||
reply_target->send_message (reply_protected, &c)
|
||||
else if reply_protected.l == 0:
|
||||
else
|
||||
dpanic (0, "nothing to reply to")
|
||||
else:
|
||||
kdebug ("not replying, because receiver was destroyed in the operation\n")
|
||||
|
||||
static void reply_cap (unsigned target, Iris::Num protected_data, kCapRef *ref, unsigned num = 0):
|
||||
if !reply_target:
|
||||
if reply_protected.l == 0:
|
||||
dpanic (0, "nothing to reply to")
|
||||
else:
|
||||
kdebug ("not replying, because receiver was destroyed in the operation\n")
|
||||
dpanic (0, "nothing to reply to")
|
||||
return
|
||||
replied_caps.set (0, (kReceiver *)target, protected_data, kCapRef (), ref)
|
||||
kCapability::Context c
|
||||
@ -333,6 +326,8 @@ static void memory_invoke (unsigned cmd, unsigned target, Iris::Num protected_da
|
||||
if !c->arg.valid () || (unsigned)c->arg->target & ~KERNEL_MASK || !c->arg->target || ((kObject *)c->arg->protected_data.l)->address_space != mem:
|
||||
reply_num (Iris::ERR_INVALID_ARGUMENT)
|
||||
return
|
||||
// Send the reply before destroying things, because the target may be destroyed.
|
||||
reply_num (0)
|
||||
switch (unsigned)c->arg->target & CAPTYPE_MASK:
|
||||
case CAPTYPE_RECEIVER:
|
||||
mem->free_receiver ((kReceiver *)c->arg->protected_data.l)
|
||||
@ -352,7 +347,7 @@ static void memory_invoke (unsigned cmd, unsigned target, Iris::Num protected_da
|
||||
default:
|
||||
panic (0x55228930, "invalid case")
|
||||
return
|
||||
break
|
||||
return
|
||||
case Iris::Memory::LIST & REQUEST_MASK:
|
||||
// TODO
|
||||
break
|
||||
|
@ -30,10 +30,11 @@ static void clear_page (unsigned page, unsigned num = 1):
|
||||
kdebug ('\n')
|
||||
#endif
|
||||
page = (page & ~0xc0000000) | 0xa0000000
|
||||
for unsigned i = 0; i < (num << (PAGE_BITS - 2)); ++i:
|
||||
arch_uncache_page (page - 0x20000000)
|
||||
// Clear page.
|
||||
((unsigned *)page)[i] = 0
|
||||
for unsigned p = 0; p < num; ++p:
|
||||
arch_uncache_page (page - 0x20000000 + (p << PAGE_BITS))
|
||||
for unsigned i = 0; i < (1 << (PAGE_BITS - 2)); ++i:
|
||||
// Clear page.
|
||||
((unsigned *)page)[i] = 0
|
||||
if *((unsigned *)page) != 0 || ((unsigned *)page)[(num << (PAGE_BITS - 2)) - 1] != 0:
|
||||
dpanic (0, "clear_page didn't work")
|
||||
|
||||
|
168
source/init.ccp
168
source/init.ccp
@ -115,11 +115,14 @@ struct Program:
|
||||
Iris::Memory memory
|
||||
Iris::Thread thread
|
||||
List <Device> devices
|
||||
Iris::Cap waiter
|
||||
|
||||
static Iris::Memory top_memory
|
||||
static Iris::Directory root
|
||||
static Iris::Elfrun elfrun
|
||||
static List <Program> programs
|
||||
static Iris::Cap sysreq
|
||||
static unsigned to_receive, progs
|
||||
|
||||
static bool name_match (char const *name, unsigned name_len, Iris::String n):
|
||||
char nm[16]
|
||||
@ -272,6 +275,52 @@ static void find_type (char *&line, unsigned &len, unsigned &type, unsigned &ind
|
||||
return
|
||||
Iris::panic (0, "no valid type found")
|
||||
|
||||
static void do_run (char *&start, unsigned &maxlen, bool priv):
|
||||
char *n
|
||||
unsigned l
|
||||
if !get_name (start, maxlen, n, l):
|
||||
Iris::panic (0, "syntax error in init.config (driver)")
|
||||
List <Program>::Item *p
|
||||
for p = programs.begin (); p; p = p->next:
|
||||
if string_match ((*p)->name, (*p)->name_len, n, l):
|
||||
break
|
||||
if !p:
|
||||
Iris::panic (0, "program not found for driver")
|
||||
Iris::Cap cap = Iris::my_receiver.create_capability ((unsigned)&**p)
|
||||
if priv:
|
||||
kdebug ("priv ")
|
||||
kdebug ("running ")
|
||||
for unsigned i = 0; i < (*p)->name_len; ++i:
|
||||
kdebug_char ((*p)->name[i])
|
||||
kdebug ("\n")
|
||||
Iris::Caps caps = elfrun.run_caps (top_memory, (*p)->pages, cap.copy (), ((*p)->size + PAGE_SIZE - 1) >> PAGE_BITS)
|
||||
Iris::free_cap (cap)
|
||||
(*p)->thread = caps.get (__thread_num)
|
||||
(*p)->memory = caps.get (__memory_num)
|
||||
if priv:
|
||||
(*p)->thread.make_priv ()
|
||||
(*p)->thread.run ()
|
||||
// TODO: pass arguments.
|
||||
start += maxlen
|
||||
maxlen = 0
|
||||
|
||||
static void parse_line (char *&line, unsigned maxlen)
|
||||
static void include_caps (Iris::Caps caps, unsigned size):
|
||||
unsigned pages = (size + PAGE_SIZE - 1) >> PAGE_BITS
|
||||
char *config = alloc_space (pages)
|
||||
unsigned pages_slot = caps.use ()
|
||||
for unsigned p = 0; p < pages; ++p:
|
||||
Iris::Page page (pages_slot, p)
|
||||
Iris::my_memory.map (page, (unsigned)&config[p << PAGE_BITS])
|
||||
char *ptr = config
|
||||
while ptr - config < size:
|
||||
parse_line (ptr, config + size - ptr)
|
||||
for unsigned p = 0; p < pages; ++p:
|
||||
Iris::my_memory.destroy (Iris::Cap (pages_slot, p))
|
||||
Iris::my_memory.destroy (caps)
|
||||
Iris::free_cap (caps)
|
||||
Iris::free_slot (pages_slot)
|
||||
|
||||
static void parse_line (char *&line, unsigned maxlen):
|
||||
char *start = line
|
||||
while maxlen && *line != '\n':
|
||||
@ -298,6 +347,7 @@ static void parse_line (char *&line, unsigned maxlen):
|
||||
if !maxlen:
|
||||
Iris::panic (0, "no closing quote in init.config")
|
||||
p->pages = load (start - len, len, p->size)
|
||||
p->waiter = Iris::Cap ()
|
||||
++start
|
||||
--maxlen
|
||||
else if match (start, maxlen, "killbootthreads"):
|
||||
@ -314,39 +364,58 @@ static void parse_line (char *&line, unsigned maxlen):
|
||||
break
|
||||
if !p:
|
||||
Iris::panic (0, "program not found for receive")
|
||||
if !(*p)->devices.begin ():
|
||||
++progs
|
||||
List <Device>::Item *dev = (*p)->devices.insert ()
|
||||
find_type (start, maxlen, (*dev)->type, (*dev)->index)
|
||||
if !match (start, maxlen, "=") || !get_name (start, maxlen, (*dev)->name, (*dev)->name_len):
|
||||
Iris::panic (1, "syntax error in init.config (receive)")
|
||||
(*dev)->server = &**p
|
||||
++to_receive
|
||||
else if match (start, maxlen, "driver"):
|
||||
char *n
|
||||
unsigned l
|
||||
if !get_name (start, maxlen, n, l):
|
||||
Iris::panic (0, "syntax error in init.config (driver)")
|
||||
List <Program>::Item *p
|
||||
for p = programs.begin (); p; p = p->next:
|
||||
if string_match ((*p)->name, (*p)->name_len, n, l):
|
||||
break
|
||||
if !p:
|
||||
Iris::panic (0, "program not found for driver")
|
||||
Iris::Cap cap = Iris::my_receiver.create_capability ((unsigned)&**p)
|
||||
kdebug ("running ")
|
||||
for unsigned i = 0; i < (*p)->name_len; ++i:
|
||||
kdebug_char ((*p)->name[i])
|
||||
kdebug ("\n")
|
||||
Iris::Caps caps = elfrun.run_caps (top_memory, (*p)->pages, cap.copy (), ((*p)->size + PAGE_SIZE - 1) >> PAGE_BITS)
|
||||
Iris::free_cap (cap)
|
||||
(*p)->thread = caps.get (__thread_num)
|
||||
(*p)->memory = caps.get (__memory_num)
|
||||
(*p)->thread.make_priv ()
|
||||
(*p)->thread.run ()
|
||||
// TODO: pass arguments.
|
||||
start += maxlen
|
||||
maxlen = 0
|
||||
do_run (start, maxlen, true)
|
||||
else if match (start, maxlen, "run"):
|
||||
do_run (start, maxlen, false)
|
||||
else if match (start, maxlen, "wait"):
|
||||
// TODO
|
||||
start += maxlen
|
||||
maxlen = 0
|
||||
kdebug ("waiting for device registration\n")
|
||||
while progs:
|
||||
Iris::wait ()
|
||||
Program *caller = (Program *)Iris::recv.protected_data.l
|
||||
if !caller:
|
||||
Iris::panic (0, "bug in init: no caller")
|
||||
switch Iris::recv.data[0].l:
|
||||
case Iris::Parent::PROVIDE_DEVICE:
|
||||
if Iris::recv.data[1].h != 0:
|
||||
kdebug ("init: too high device provided\n")
|
||||
continue
|
||||
unsigned type = Iris::recv.data[1].l
|
||||
unsigned index = Iris::recv.data[0].h
|
||||
List <Device>::Item *d
|
||||
for d = caller->devices.begin (); d; d = d->next:
|
||||
if (*d)->type == type && (*d)->index == index:
|
||||
break
|
||||
if !d:
|
||||
Iris::panic (0, "unregistered device provided")
|
||||
(*d)->cap = Iris::get_arg ()
|
||||
Iris::recv.reply.invoke ()
|
||||
--to_receive
|
||||
break
|
||||
case Iris::Parent::INIT_DONE:
|
||||
if caller->waiter.code != Iris::Cap ().code:
|
||||
Iris::panic (0, "caller was already waiting")
|
||||
caller->waiter = Iris::get_reply ()
|
||||
--progs
|
||||
break
|
||||
default:
|
||||
Iris::panic (0, "unexpected request to init")
|
||||
if to_receive:
|
||||
Iris::panic (to_receive, "not all expected devices were registered")
|
||||
for List <Program>::Item *p = programs.begin (); p; p = p->next:
|
||||
if (*p)->waiter.code != Iris::Cap ().code:
|
||||
(*p)->waiter.invoke ()
|
||||
Iris::free_cap ((*p)->waiter)
|
||||
(*p)->waiter = Iris::Cap ()
|
||||
kdebug ("got all devices\n")
|
||||
else if match (start, maxlen, "sysreq"):
|
||||
// TODO
|
||||
start += maxlen
|
||||
@ -355,14 +424,18 @@ static void parse_line (char *&line, unsigned maxlen):
|
||||
// TODO
|
||||
start += maxlen
|
||||
maxlen = 0
|
||||
else if match (start, maxlen, "run"):
|
||||
// TODO
|
||||
start += maxlen
|
||||
maxlen = 0
|
||||
else if match (start, maxlen, "include"):
|
||||
// TODO
|
||||
start += maxlen
|
||||
maxlen = 0
|
||||
char *n
|
||||
unsigned l
|
||||
if !get_name (start, maxlen, n, l):
|
||||
Iris::panic (0, "syntax error in init.config (include)")
|
||||
List <Program>::Item *p
|
||||
for p = programs.begin (); p; p = p->next:
|
||||
if string_match ((*p)->name, (*p)->name_len, n, l):
|
||||
break
|
||||
if !p:
|
||||
Iris::panic (0, "file not found for include")
|
||||
include_caps ((*p)->pages, (*p)->size)
|
||||
else:
|
||||
Iris::panic (0, "invalid line in init.config")
|
||||
delspace (start, maxlen)
|
||||
@ -379,24 +452,11 @@ Iris::Num start ():
|
||||
root = Iris::my_parent.get_device <Iris::Directory> ()
|
||||
elfrun = Iris::my_parent.get_device <Iris::Elfrun> ()
|
||||
top_memory = Iris::get_top_memory ()
|
||||
to_receive = 0
|
||||
progs = 0
|
||||
unsigned config_size
|
||||
Iris::Caps config_pages = load ("init.config", 12, config_size)
|
||||
unsigned pages = (config_size + PAGE_SIZE - 1) >> PAGE_BITS
|
||||
char *config = alloc_space (pages)
|
||||
unsigned pages_slot = config_pages.use ()
|
||||
for unsigned p = 0; p < pages; ++p:
|
||||
Iris::Page page (pages_slot, p)
|
||||
Iris::my_memory.map (page, (unsigned)&config[p << PAGE_BITS])
|
||||
char *ptr = config
|
||||
kdebug ("parsing config\n")
|
||||
while ptr - config < config_size:
|
||||
parse_line (ptr, config + config_size - ptr)
|
||||
kdebug ("destroying pages\n")
|
||||
for unsigned p = 0; p < pages; ++p:
|
||||
Iris::my_memory.destroy (Iris::Cap (pages_slot, p))
|
||||
Iris::my_memory.destroy (config_pages)
|
||||
Iris::free_cap (config_pages)
|
||||
Iris::free_slot (pages_slot)
|
||||
include_caps (config_pages, config_size)
|
||||
kdebug ("waiting for events.\n")
|
||||
while true:
|
||||
Iris::wait ()
|
||||
@ -409,4 +469,10 @@ Iris::Num start ():
|
||||
switch Iris::recv.data[0].l:
|
||||
default:
|
||||
// TODO.
|
||||
kdebug ("child request\n")
|
||||
kdebug ("child request: ")
|
||||
kdebug_num (Iris::recv.data[0].l)
|
||||
kdebug (" from ")
|
||||
for unsigned i = 0; i < caller->name_len; ++i:
|
||||
kdebug_char (caller->name[i])
|
||||
kdebug ("\n")
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user