Working Init Channel
This commit is contained in:
parent
24c9fa55a9
commit
50c75ed361
@ -17,10 +17,15 @@
|
||||
|
||||
#include <aos/aos.h>
|
||||
|
||||
// define some message types
|
||||
#define RPC_MTYPE_CHILD_ENDPOINT 0UL
|
||||
#define RPC_MTYPE_CHILD_ENDPOINT_OK 1UL
|
||||
|
||||
|
||||
/* An RPC binding, which may be transported over LMP or UMP. */
|
||||
struct aos_rpc {
|
||||
// TODO(M3): Add state
|
||||
struct lmp_chan *chan;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -56,6 +56,8 @@ struct spawninfo {
|
||||
struct capref cspace_cap_vspace; // < The frame capability used to store the serialized vspace
|
||||
|
||||
struct capref vspace_cap_l0_pagetable;
|
||||
|
||||
struct lmp_chan init_chan;
|
||||
};
|
||||
|
||||
// Start a child process using the multiboot command line. Fills in si.
|
||||
|
||||
@ -152,7 +152,6 @@ time_t mktime(struct tm *);
|
||||
size_t strftime(char * __restrict, size_t, const char * __restrict,
|
||||
const struct tm * __restrict);
|
||||
time_t time(time_t *);
|
||||
void time_wait_ms(unsigned long);
|
||||
long time_to_ms(struct timespec tt);
|
||||
#if __POSIX_VISIBLE >= 200112
|
||||
struct sigevent;
|
||||
|
||||
@ -81,7 +81,12 @@ aos_rpc_process_get_all_pids(struct aos_rpc *rpc, domainid_t **pids,
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
// We are allowed to change the signature for this one
|
||||
errval_t aos_rpc_init(struct aos_rpc *rpc)
|
||||
{
|
||||
// TODO!
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the RPC channel to init.
|
||||
|
||||
@ -28,9 +28,11 @@
|
||||
|
||||
#include "threads_priv.h"
|
||||
#include "init.h"
|
||||
#include <aos/aos_rpc.h>
|
||||
|
||||
/// Are we the init domain (and thus need to take some special paths)?
|
||||
static bool init_domain;
|
||||
static bool init_chan_initialized;
|
||||
|
||||
extern size_t (*_libc_terminal_read_func)(char *, size_t);
|
||||
extern size_t (*_libc_terminal_write_func)(const char *, size_t);
|
||||
@ -81,6 +83,56 @@ static size_t dummy_terminal_read(char *buf, size_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO rueegges: putting it here for now. Not sure how to do rcp abstraction yet
|
||||
static int event_init_dispatch_thread(void *arg)
|
||||
{
|
||||
errval_t err;
|
||||
while(true) {
|
||||
err = event_dispatch(get_default_waitset());
|
||||
if (err_is_fail(err)) {
|
||||
USER_PANIC_ERR(err_push(err, LIB_ERR_EVENT_DISPATCH), "Failed to dispatch events");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO rueegges: putting it here for now. Not sure how to do rcp abstraction yet
|
||||
static void handle_init_recv(void *arg)
|
||||
{
|
||||
errval_t err;
|
||||
struct lmp_chan *init_chan = (struct lmp_chan *)arg;
|
||||
|
||||
struct lmp_recv_msg msg = LMP_RECV_MSG_INIT;
|
||||
struct capref cap;
|
||||
|
||||
err = lmp_chan_recv(init_chan, &msg, &cap);
|
||||
if (err_is_fail(err)) {
|
||||
if (lmp_err_is_transient(err)) {
|
||||
err = lmp_endpoint_register(init_chan->endpoint, get_default_waitset(), MKCLOSURE(handle_init_recv, init_chan));
|
||||
if (err_is_fail(err)) {
|
||||
USER_PANIC_ERR(err, "Could not reregister after failed init_chan cap receive");
|
||||
}
|
||||
} else {
|
||||
USER_PANIC_ERR(err, "Failure in child channel");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch(msg.words[0]){
|
||||
case RPC_MTYPE_CHILD_ENDPOINT_OK:
|
||||
debug_printf("Received child init OK\n");
|
||||
init_chan_initialized = true;
|
||||
break;
|
||||
default:
|
||||
USER_PANIC("Unknown rpc message type.");
|
||||
break;
|
||||
}
|
||||
|
||||
err = lmp_endpoint_register(init_chan->endpoint, get_default_waitset(), MKCLOSURE(handle_init_recv, init_chan));
|
||||
if (err_is_fail(err)) {
|
||||
USER_PANIC_ERR(err, "Could not reregister after failed init_chan cap receive");
|
||||
}
|
||||
}
|
||||
|
||||
/* Set libc function pointers */
|
||||
void barrelfish_libc_glue_init(void)
|
||||
{
|
||||
@ -146,16 +198,48 @@ errval_t barrelfish_init_onthread(struct spawn_domain_params *params)
|
||||
lmp_endpoint_init();
|
||||
|
||||
// HINT: Use init_domain to check if we are the init domain.
|
||||
// early exit for the init process
|
||||
if(init_domain) {
|
||||
return SYS_ERR_OK;
|
||||
}
|
||||
|
||||
// TODO MILESTONE 3: register ourselves with init
|
||||
/* allocate lmp channel structure */
|
||||
struct lmp_chan *init_chan = malloc(sizeof(struct lmp_chan));
|
||||
/* create local endpoint */
|
||||
err = endpoint_create(DEFAULT_LMP_BUF_WORDS, &init_chan->local_cap, &init_chan->endpoint);
|
||||
if (err_is_fail(err)) {
|
||||
return err_push(err, LIB_ERR_ENDPOINT_CREATE);
|
||||
}
|
||||
/* set remote endpoint to init's endpoint */
|
||||
init_chan->remote_cap = cap_initep;
|
||||
/* set receive handler */
|
||||
init_chan_initialized = false;
|
||||
err = lmp_chan_register_recv(init_chan, get_default_waitset(), MKCLOSURE(handle_init_recv, init_chan));
|
||||
/* send local ep to init */
|
||||
err = lmp_chan_send0(init_chan, LMP_FLAG_YIELD | LMP_FLAG_SYNC, init_chan->local_cap);
|
||||
if (err_is_fail(err)) {
|
||||
// should never fail since init listens before invoking the dispatcher
|
||||
return err_push(err, LIB_ERR_LMP_CHAN_SEND);
|
||||
}
|
||||
/* wait for init to acknowledge receiving the endpoint */
|
||||
while(!init_chan_initialized) {
|
||||
err = event_dispatch(get_default_waitset());
|
||||
if (err_is_fail(err)) {
|
||||
return err_push(err, LIB_ERR_EVENT_DISPATCH);
|
||||
}
|
||||
}
|
||||
/* initialize init RPC client with lmp channel */
|
||||
struct aos_rpc *init_rpc = malloc(sizeof(struct aos_rpc));
|
||||
err = aos_rpc_init(init_rpc);
|
||||
if (err_is_fail(err)){
|
||||
return err_push(err, ERR_NOTIMP);
|
||||
}
|
||||
/* set init RPC client in our program state */
|
||||
set_init_rpc(init_rpc);
|
||||
|
||||
// create thread to dispatch events
|
||||
thread_create(event_init_dispatch_thread, NULL);
|
||||
|
||||
/* TODO MILESTONE 3: now we should have a channel with init set up and can
|
||||
* use it for the ram allocator */
|
||||
@ -176,7 +260,7 @@ errval_t barrelfish_init_onthread(struct spawn_domain_params *params)
|
||||
void barrelfish_init_disabled(dispatcher_handle_t handle, bool init_dom_arg);
|
||||
void barrelfish_init_disabled(dispatcher_handle_t handle, bool init_dom_arg)
|
||||
{
|
||||
init_domain = init_dom_arg;
|
||||
; init_domain = init_dom_arg;
|
||||
disp_init_disabled(handle);
|
||||
thread_init_disabled(handle, init_dom_arg);
|
||||
}
|
||||
|
||||
@ -330,7 +330,7 @@ errval_t paging_init_state_foreign(struct paging_state *st, lvaddr_t start_vaddr
|
||||
errval_t paging_init_params(struct spawn_domain_params *params)
|
||||
{
|
||||
errval_t err;
|
||||
debug_printf("paging_init\n");
|
||||
// debug_printf("paging_init\n");
|
||||
// (M2): Call paging_init_state for ¤t
|
||||
// TODO (M4): initialize self-paging handler
|
||||
// TIP: use thread_set_exception_handler() to setup a page fault handler
|
||||
@ -351,8 +351,8 @@ errval_t paging_init_params(struct spawn_domain_params *params)
|
||||
if(params != NULL && params->vspace_buf != NULL) {
|
||||
current.l0_pt = **(struct pt_t **)params->vspace_buf;
|
||||
current.vaddr_head = **(struct pt_vaddr_reg_t **)(params->vspace_buf + sizeof(struct pt_t *));
|
||||
debug_printf("Received initial paging state:\n");
|
||||
pt_print_state(¤t);
|
||||
// debug_printf("Received initial paging state:\n");
|
||||
// pt_print_state(¤t);
|
||||
}
|
||||
|
||||
set_current_paging_state(¤t);
|
||||
|
||||
@ -8,15 +8,24 @@
|
||||
void do_test_spawn(void) {
|
||||
// spawn multiple processes
|
||||
|
||||
struct spawninfo si[PROCESS_COUNT];
|
||||
domainid_t pid[PROCESS_COUNT];
|
||||
struct spawninfo *si = malloc(PROCESS_COUNT * sizeof(struct spawninfo));
|
||||
domainid_t *pid = malloc(PROCESS_COUNT * sizeof(domainid_t));
|
||||
for(uint i = 0; i < PROCESS_COUNT; ++i) {
|
||||
debug_printf("TEST_SPAWN: spawn %u\n", i);
|
||||
CHECK_ERR(spawn_load_by_name("hello", &(si[i]), &(pid[i])));
|
||||
}
|
||||
|
||||
// wait for 10 seconds before continuing
|
||||
time_wait_ms(10000);
|
||||
// wait for 10 seconds but handle events in the mean time
|
||||
struct waitset *default_ws = get_default_waitset();
|
||||
struct timespec tt;
|
||||
clock_gettime(CLOCK_REALTIME, &tt);
|
||||
long start = time_to_ms(tt);
|
||||
do {
|
||||
if(err_is_ok(check_for_event(default_ws))){
|
||||
CHECK_ERR(event_dispatch(default_ws));
|
||||
}
|
||||
clock_gettime(CLOCK_REALTIME, &tt);
|
||||
} while(time_to_ms(tt) - start < 10000);
|
||||
|
||||
for(uint i = 0; i < PROCESS_COUNT; ++i) {
|
||||
debug_printf("TEST_SPAWN: Killing %u\n", i);
|
||||
|
||||
@ -55,24 +55,3 @@ long
|
||||
time_to_ms(struct timespec tt) {
|
||||
return tt.tv_sec * 1000 + tt.tv_nsec / 1000 / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Wait for ms milliseconds before returning.
|
||||
*
|
||||
* \param ms Duration to wait
|
||||
*
|
||||
* Very ugly and approximate but useful
|
||||
*
|
||||
*/
|
||||
void
|
||||
time_wait_ms(unsigned long ms) {
|
||||
struct timespec tt;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &tt);
|
||||
long start = time_to_ms(tt);
|
||||
long now;
|
||||
do {
|
||||
clock_gettime(CLOCK_REALTIME, &tt);
|
||||
now = time_to_ms(tt);
|
||||
} while(start + ms > now);
|
||||
}
|
||||
@ -140,7 +140,7 @@ struct mem_region *multiboot_find_module(struct bootinfo *bi, const char *name)
|
||||
snprintf(pathname, len, "/armv8/sbin/%s", name);
|
||||
name = pathname;
|
||||
}
|
||||
DEBUG_PRINTF("name is: %s\n", name);
|
||||
// DEBUG_PRINTF("name is: %s\n", name);
|
||||
for(size_t i = 0; i < bi->regions_length; i++) {
|
||||
struct mem_region *region = &bi->regions[i];
|
||||
const char *modname = multiboot_module_name(region);
|
||||
|
||||
@ -47,9 +47,45 @@ static void armv8_set_registers(void *arch_load_info,
|
||||
disabled_area->regs[REG_OFFSET(PIC_REGISTER)] = got_base;
|
||||
}
|
||||
|
||||
static void handle_child_recv(void *arg) {
|
||||
errval_t err;
|
||||
struct lmp_chan *init_chan = (struct lmp_chan *)arg;
|
||||
|
||||
struct lmp_recv_msg msg = LMP_RECV_MSG_INIT;
|
||||
struct capref cap;
|
||||
|
||||
err = lmp_chan_recv(init_chan, &msg, &cap);
|
||||
if (err_is_fail(err)) {
|
||||
if (lmp_err_is_transient(err)) {
|
||||
err = lmp_endpoint_register(init_chan->endpoint, get_default_waitset(), MKCLOSURE(handle_child_recv, init_chan));
|
||||
if (err_is_fail(err)) {
|
||||
USER_PANIC_ERR(err, "Could not reregister after failed init_chan cap receive");
|
||||
}
|
||||
} else {
|
||||
USER_PANIC_ERR(err, "Failure in child channel");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch(msg.words[0]){
|
||||
case RPC_MTYPE_CHILD_ENDPOINT:
|
||||
debug_printf("SPAWN: Received child init_chan endpoint\n");
|
||||
init_chan->remote_cap = cap;
|
||||
err = lmp_chan_send1(init_chan, LMP_FLAG_YIELD | LMP_FLAG_SYNC, NULL_CAP, RPC_MTYPE_CHILD_ENDPOINT_OK);
|
||||
if (err_is_fail(err)) {
|
||||
USER_PANIC_ERR(err, "Failed to send RPC_MTYPE_CHILD_ENDPOINT_OK");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
USER_PANIC("Unknown rpc message type.");
|
||||
break;
|
||||
}
|
||||
|
||||
err = lmp_endpoint_register(init_chan->endpoint, get_default_waitset(), MKCLOSURE(handle_child_recv, init_chan));
|
||||
if (err_is_fail(err)) {
|
||||
USER_PANIC_ERR(err, "Could not reregister after failed init_chan cap receive");
|
||||
}
|
||||
}
|
||||
|
||||
struct temp_mapping {
|
||||
struct temp_mapping *next;
|
||||
@ -276,7 +312,7 @@ static errval_t spawn_serialize_vspace(struct spawninfo *si, struct paging_state
|
||||
|
||||
assert(curr_offset <= total_space);
|
||||
|
||||
debug_printf("SPAWN: Passing vspace info at 0x%lx\n", vspace_buf_child);
|
||||
// debug_printf("SPAWN: Passing vspace info at 0x%lx\n", vspace_buf_child);
|
||||
domain_params->vspace_buf = vspace_buf_child;
|
||||
domain_params->vspace_buf_len = total_space;
|
||||
|
||||
@ -315,11 +351,11 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si,
|
||||
// - Get the module from the multiboot image
|
||||
// and map it (take a look at multiboot.c)
|
||||
|
||||
debug_printf("[spawn_load_argv]: argc: %d, argv: ", argc);
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
printf("\"%s\", ", argv[i]);
|
||||
}
|
||||
printf("\n");
|
||||
// debug_printf("[spawn_load_argv]: argc: %d, argv: ", argc);
|
||||
// for (int i = 0; i < argc; ++i) {
|
||||
// printf("\"%s\", ", argv[i]);
|
||||
// }
|
||||
// printf("\n");
|
||||
|
||||
assert(argc > 0);
|
||||
assert(argc < MAX_CMDLINE_ARGS);
|
||||
@ -405,9 +441,15 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si,
|
||||
if (err_is_fail(err)) return err_push(err, LIB_ERR_CAP_COPY_FAIL);
|
||||
|
||||
err = cap_retype(si->cspace_cap_selfep, si->cspace_cap_dispatcher, 0, ObjType_EndPointLMP, 0, 1);
|
||||
if (err_is_fail(err)) return err;
|
||||
err = cap_copy(si->cspace_cap_initep, cap_selfep);
|
||||
if (err_is_fail(err)) return err_push(err, SPAWN_ERR_CREATE_SELFEP);
|
||||
|
||||
// give the child an endpoint to talk to init
|
||||
lmp_chan_init(&si->init_chan);
|
||||
err = endpoint_create(DEFAULT_LMP_BUF_WORDS, &si->init_chan.local_cap, &si->init_chan.endpoint);
|
||||
if (err_is_fail(err)) return err_push(err, LIB_ERR_ENDPOINT_CREATE);
|
||||
err = cap_copy(si->cspace_cap_initep, si->init_chan.local_cap);
|
||||
if (err_is_fail(err)) return err_push(err, LIB_ERR_CAP_COPY_FAIL);
|
||||
si->init_chan.remote_cap = NULL_CAP;
|
||||
|
||||
// - Setup the child's vspace
|
||||
// afeer: create level 0 page table
|
||||
@ -441,8 +483,8 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si,
|
||||
got_addr = got_shdr->sh_addr;
|
||||
}
|
||||
|
||||
debug_printf("SPAWN: self paging state after loading:\n");
|
||||
pt_print_state(get_current_paging_state());
|
||||
// debug_printf("SPAWN: self paging state after loading:\n");
|
||||
// pt_print_state(get_current_paging_state());
|
||||
|
||||
err = paging_unmap(get_current_paging_state(), elf_base);
|
||||
if (err_is_fail(err)) return err_push(err, LIB_ERR_PMAP_UNMAP);
|
||||
@ -454,8 +496,8 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si,
|
||||
free(tm);
|
||||
}
|
||||
|
||||
debug_printf("SPAWN: self paging state after unmapping:\n");
|
||||
pt_print_state(get_current_paging_state());
|
||||
// debug_printf("SPAWN: self paging state after unmapping:\n");
|
||||
// pt_print_state(get_current_paging_state());
|
||||
|
||||
// - Setup the dispatcher
|
||||
err = frame_create(si->cspace_cap_dispframe, DISPATCHER_FRAME_SIZE, NULL);
|
||||
@ -569,6 +611,11 @@ errval_t spawn_load_argv(int argc, char *argv[], struct spawninfo *si,
|
||||
err = paging_unmap(get_current_paging_state(), arguments_page_in_self);
|
||||
if (err_is_fail(err)) return err_push(err, LIB_ERR_PMAP_UNMAP);
|
||||
|
||||
// Receive the child's endpoint for the init channel
|
||||
lmp_chan_alloc_recv_slot(&si->init_chan);
|
||||
err = lmp_endpoint_register(si->init_chan.endpoint, get_default_waitset(), MKCLOSURE(handle_child_recv, &si->init_chan));
|
||||
if (err_is_fail(err)) return err;
|
||||
|
||||
// - Make the new dispatcher runnable
|
||||
err = invoke_dispatcher(
|
||||
si->dispatcher, cap_dispatcher,
|
||||
|
||||
@ -16,9 +16,9 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <aos/aos.h>
|
||||
#include <aos/deferred.h>
|
||||
|
||||
#define HELLO_CATCH_COMMAND "catch"
|
||||
|
||||
@ -37,7 +37,7 @@ int main(int argc, char *argv[])
|
||||
while(1) {
|
||||
printf("Catch me if you can! %d\n", iter);
|
||||
// wait for 1 second
|
||||
time_wait_ms(1000);
|
||||
barrelfish_usleep(1000000);
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,6 +53,9 @@ bsp_main(int argc, char *argv[]) {
|
||||
|
||||
// TODO: initialize mem allocator, vspace management here
|
||||
|
||||
err = cap_retype(cap_selfep, cap_dispatcher, 0, ObjType_EndPointLMP, 0, 1);
|
||||
if (err_is_fail(err)) return err;
|
||||
|
||||
// Grading
|
||||
grading_test_early();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user