static void alloc_monitor_ep(struct monitor_blocking_binding *b) { struct capref retcap = NULL_CAP; errval_t err, reterr = SYS_ERR_OK; struct monitor_lmp_binding *lmpb = malloc(sizeof(struct monitor_lmp_binding)); assert(lmpb != NULL); // setup our end of the binding err = monitor_client_lmp_accept(lmpb, get_default_waitset(), DEFAULT_LMP_BUF_WORDS); if (err_is_fail(err)) { free(lmpb); reterr = err_push(err, LIB_ERR_MONITOR_CLIENT_ACCEPT); goto out; } retcap = lmpb->chan.local_cap; monitor_server_init(&lmpb->b); out: err = b->tx_vtbl.alloc_monitor_ep_response(b, NOP_CONT, reterr, retcap); if (err_is_fail(err)) { USER_PANIC_ERR(err, "failed to send alloc_monitor_ep_reply"); } }
/** * \brief Setup a new idc channel between monitor and domain * * \bug on error send message back to domain */ static void new_monitor_binding_request(struct monitor_binding *b, uintptr_t st) { struct capref retcap = NULL_CAP; errval_t err, reterr = SYS_ERR_OK; struct monitor_lmp_binding *lmpb = malloc(sizeof(struct monitor_lmp_binding)); assert(lmpb != NULL); // setup our end of the binding err = monitor_client_lmp_accept(lmpb, get_default_waitset(), DEFAULT_LMP_BUF_WORDS); if (err_is_fail(err)) { free(lmpb); reterr = err_push(err, LIB_ERR_MONITOR_CLIENT_ACCEPT); goto out; } retcap = lmpb->chan.local_cap; monitor_server_init(&lmpb->b); out: new_monitor_binding_reply_cont(b, reterr, retcap, st); }
errval_t monitor_client_setup(struct spawninfo *si) { errval_t err; struct monitor_lmp_binding *b = malloc(sizeof(struct monitor_lmp_binding)); assert(b != NULL); // setup our end of the binding err = monitor_client_lmp_accept(b, get_default_waitset(), DEFAULT_LMP_BUF_WORDS); if (err_is_fail(err)) { free(b); return err_push(err, LIB_ERR_MONITOR_CLIENT_ACCEPT); } // copy the endpoint cap to the recipient struct capref dest = { .cnode = si->rootcn, .slot = ROOTCN_SLOT_MONITOREP, }; err = cap_copy(dest, b->chan.local_cap); if (err_is_fail(err)) { // TODO: destroy binding return err_push(err, LIB_ERR_CAP_COPY); } // Copy the performance monitoring cap to all spawned processes. struct capref src; dest.cnode = si->taskcn; dest.slot = TASKCN_SLOT_PERF_MON; src.cnode = cnode_task; src.slot = TASKCN_SLOT_PERF_MON; err = cap_copy(dest, src); if (err_is_fail(err)) { return err_push(err, INIT_ERR_COPY_PERF_MON); } // copy our receive vtable to the binding monitor_server_init(&b->b); return SYS_ERR_OK; } errval_t monitor_client_setup_mem_serv(void) { /* construct special-case LMP connection to mem_serv */ static struct monitor_lmp_binding mcb; struct waitset *ws = get_default_waitset(); errval_t err; err = monitor_client_lmp_accept(&mcb, ws, DEFAULT_LMP_BUF_WORDS); if(err_is_fail(err)) { USER_PANIC_ERR(err, "monitor_client_setup_mem_serv"); } assert(err_is_ok(err)); /* Send the cap for this endpoint to init, who will pass it to the monitor */ err = lmp_ep_send0(cap_initep, 0, mcb.chan.local_cap); if (err_is_fail(err)) { USER_PANIC_ERR(err, "lmp_ep_send0 failed"); } // copy our receive vtable to the binding monitor_server_init(&mcb.b); // XXX: handle messages (ie. block) until the monitor binding is ready while (capref_is_null(mcb.chan.remote_cap)) { err = event_dispatch(ws); if (err_is_fail(err)) { DEBUG_ERR(err, "in event_dispatch waiting for mem_serv binding"); return err_push(err, LIB_ERR_EVENT_DISPATCH); } } return SYS_ERR_OK; } /// Setup a dummy monitor binding that "sends" all requests to the local handlers errval_t monitor_client_setup_monitor(void) { monitor_loopback_init(&monitor_self_binding); monitor_server_init(&monitor_self_binding); set_monitor_binding(&monitor_self_binding); caplock_init(get_default_waitset()); idc_init(); // XXX: Need a waitset here or loopback won't work as expected // when binding to the ram_alloc service monitor_self_binding.mutex.equeue.waitset = get_default_waitset(); return SYS_ERR_OK; }