From c8f7b1c678b3737d89101afd5b77a3c2ddba73b1 Mon Sep 17 00:00:00 2001 From: Bas Wijnen Date: Mon, 3 May 2010 16:46:14 +0200 Subject: [PATCH] improve init; make destroy simpler --- alloc.ccp | 4 - boot-programs/bootinit.ccp | 2 +- init.config | 18 ++-- invoke.ccp | 17 ++-- memory.ccp | 9 +- source/init.ccp | 168 ++++++++++++++++++++++++++----------- 6 files changed, 138 insertions(+), 80 deletions(-) diff --git a/alloc.ccp b/alloc.ccp index 88fc14a..cef1e81 100644 --- a/alloc.ccp +++ b/alloc.ccp @@ -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: diff --git a/boot-programs/bootinit.ccp b/boot-programs/bootinit.ccp index cbd0943..43bc64a 100644 --- a/boot-programs/bootinit.ccp +++ b/boot-programs/bootinit.ccp @@ -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 () diff --git a/init.config b/init.config index 928cd14..bafca63 100644 --- a/init.config +++ b/init.config @@ -1,8 +1,8 @@ # load = '' 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 / [, ] = 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 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 include a loaded file as another config file. - include session + #include session diff --git a/invoke.ccp b/invoke.ccp index 850be16..0cbeac9 100644 --- a/invoke.ccp +++ b/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 diff --git a/memory.ccp b/memory.ccp index cc2f43e..6b5c00a 100644 --- a/memory.ccp +++ b/memory.ccp @@ -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") diff --git a/source/init.ccp b/source/init.ccp index dc02c6a..d78d6aa 100644 --- a/source/init.ccp +++ b/source/init.ccp @@ -115,11 +115,14 @@ struct Program: Iris::Memory memory Iris::Thread thread List devices + Iris::Cap waiter static Iris::Memory top_memory static Iris::Directory root static Iris::Elfrun elfrun static List 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 ::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 ::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 ::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 ::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 ::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 ::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 () elfrun = Iris::my_parent.get_device () 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") +