mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-04-21 12:27:27 +03:00
improve init; make destroy simpler
This commit is contained in:
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")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user