/* * Call this method when bfscope is done with flushing and wants to notify * the initiator of the flush request. */ static void bfscope_send_flush_ack_to_monitor(void) { struct bfscope_ack_send_state *state = malloc(sizeof(struct bfscope_ack_send_state)); //memset(state, 0, sizeof(struct trace_broadcast_start_state)); state->monitor_binding = get_monitor_binding(); event_mutex_enqueue_lock(&state->monitor_binding->mutex, &state->qnode, MKCLOSURE(&bfscope_send_flush_ack_cont, state)); }
/** * \brief Send a reply back to the monitor. If the error code indicates success, this function * creates a new monitor binding and registers to receive messages. * \param multihop_chan * \param err error code to send back * \param vci my vci for ingoing messages * \param waitset waitset to use for the channel */ void multihop_chan_send_bind_reply(struct multihop_chan *mc, errval_t msgerr, multihop_vci_t vci, struct waitset *waitset) { errval_t err; struct bind_multihop_reply_state *reply_state = malloc( sizeof(struct bind_multihop_reply_state)); assert(reply_state != NULL); if (err_is_ok(msgerr)) { // make sure channel exists assert(mc != NULL); } else { // make sure channel is not created assert(mc == NULL); } reply_state->mc = mc; reply_state->args.err = msgerr; reply_state->args.receiver_vci = vci; if (err_is_ok(msgerr)) { // get a vci for this binding reply_state->mc->my_vci = multihop_chan_mapping_insert(mc); reply_state->args.sender_vci = reply_state->mc->my_vci; } else { reply_state->args.sender_vci = 0; } if (err_is_ok(msgerr)) { // create a new monitor binding err = monitor_client_new_binding( multihop_new_monitor_binding_continuation2, reply_state, waitset, DEFAULT_LMP_BUF_WORDS); if (err_is_fail(err)) { USER_PANIC_ERR( err, "Could not create a new monitor binding in the multi-hop interconnect driver"); } } else { reply_state->monitor_binding = get_monitor_binding(); // wait for the ability to use the monitor binding event_mutex_enqueue_lock(&reply_state->monitor_binding->mutex, &reply_state->qnode, MKCLOSURE(send_bind_reply, reply_state)); } }
/** * \brief Internal function that is called as soon as a new monitor binding is created */ static void multihop_new_monitor_binding_continuation2(void *st, errval_t err, struct monitor_binding *monitor_binding) { struct bind_multihop_reply_state *reply_state = st; if (err_is_fail(err)) { reply_state->args.err = err; } else { reply_state->monitor_binding = monitor_binding; reply_state->mc->monitor_binding = monitor_binding; reply_state->mc->direction = 2; reply_state->mc->unacked_received = 0; reply_state->mc->unacked_send = 0; reply_state->mc->connstate = MULTIHOP_CONNECTED; } // wait for the ability to use the monitor binding event_mutex_enqueue_lock(&reply_state->monitor_binding->mutex, &reply_state->qnode, MKCLOSURE(send_bind_reply, reply_state)); }
/// Handler for LMP bind request messages from the Monitor static void bind_lmp_service_request_handler(struct monitor_binding *b, uintptr_t service_id, uintptr_t mon_id, size_t buflen_words, struct capref endpoint) { struct idc_export *e = (void *)service_id; struct lmp_chan *lc = NULL; errval_t err; // call the binding's connect handler if (e->lmp_connect_callback != NULL) { err = e->lmp_connect_callback(e->connect_cb_st, buflen_words, endpoint, &lc); } else { err = LIB_ERR_NO_LMP_BIND_HANDLER; } if (err_is_ok(err)) { assert(lc != NULL); } // wait for the ability to use the monitor binding struct bind_lmp_reply_state *st = malloc(sizeof(struct bind_lmp_reply_state)); assert(st != NULL); st->b = b; st->lc = lc; st->args.err = err; st->args.mon_id = mon_id; if (err_is_ok(err)) { st->args.conn_id = (uintptr_t)lc; st->args.ep = lc->local_cap; } else { st->args.conn_id = 0; st->args.ep = NULL_CAP; } event_mutex_enqueue_lock(&b->mutex, &st->qnode, MKCLOSURE(send_bind_reply, st)); }
/** * \brief Initialise a new LMP channel and initiate a binding * * \param lc Storage for channel state * \param cont Continuation for bind completion/failure * \param qnode Storage for an event queue node (used for queuing bind request) * \param iref IREF to which to bind * \param buflen_words Size of incoming buffer, in number of words */ errval_t lmp_chan_bind(struct lmp_chan *lc, struct lmp_bind_continuation cont, struct event_queue_node *qnode, iref_t iref, size_t buflen_words) { errval_t err; lmp_chan_init(lc); /* store bind arguments */ lc->iref = iref; lc->buflen_words = buflen_words; lc->bind_continuation = cont; /* allocate a cap slot for the new endpoint cap */ err = slot_alloc(&lc->local_cap); if (err_is_fail(err)) { waitset_chanstate_destroy(&lc->send_waitset); return err_push(err, LIB_ERR_SLOT_ALLOC); } /* allocate a local endpoint */ err = lmp_endpoint_create_in_slot(buflen_words, lc->local_cap, &lc->endpoint); if (err_is_fail(err)) { slot_free(lc->local_cap); waitset_chanstate_destroy(&lc->send_waitset); return err_push(err, LIB_ERR_ENDPOINT_CREATE); } // wait for the ability to use the monitor binding lc->connstate = LMP_BIND_WAIT; struct monitor_binding *mb = lc->monitor_binding = get_monitor_binding(); event_mutex_enqueue_lock(&mb->mutex, qnode, MKCLOSURE(send_bind_cont, lc)); return SYS_ERR_OK; }
void ump_chan_send_bind_reply(struct monitor_binding *mb, struct ump_chan *uc, errval_t err, uintptr_t monitor_id, struct capref notify_cap) { struct bind_ump_reply_state *st = malloc(sizeof(struct bind_ump_reply_state)); assert(st != NULL); if (err_is_ok(err)) { assert(uc != NULL); } else { assert(uc == NULL); } st->b = mb; st->uc = uc; st->args.err = err; st->args.mon_id = monitor_id; st->args.conn_id = err_is_ok(err) ? (uintptr_t)uc : 0; st->args.notify = notify_cap; // wait for the ability to use the monitor binding event_mutex_enqueue_lock(&mb->mutex, &st->qnode, MKCLOSURE(send_bind_reply, st)); }
/** * \brief Initialise a new UMP channel and initiate a binding * * \param uc Storage for channel state * \param cont Continuation for bind completion/failure * \param qnode Storage for an event queue node (used for queuing bind request) * \param iref IREF to which to bind * \param monitor_binding Monitor binding to use * \param inchanlen Size of incoming channel, in bytes (rounded to #UMP_MSG_BYTES) * \param outchanlen Size of outgoing channel, in bytes (rounded to #UMP_MSG_BYTES) * \param notify_cap Capability to use for notifications, or #NULL_CAP */ errval_t ump_chan_bind(struct ump_chan *uc, struct ump_bind_continuation cont, struct event_queue_node *qnode, iref_t iref, struct monitor_binding *monitor_binding, size_t inchanlen, size_t outchanlen, struct capref notify_cap) { errval_t err; // round up channel sizes to message size inchanlen = ROUND_UP(inchanlen, UMP_MSG_BYTES); outchanlen = ROUND_UP(outchanlen, UMP_MSG_BYTES); // compute size of frame needed and allocate it size_t framesize = inchanlen + outchanlen; err = frame_alloc(&uc->frame, framesize, &framesize); if (err_is_fail(err)) { return err_push(err, LIB_ERR_FRAME_ALLOC); } // map it in void *buf; err = vspace_map_one_frame_attr(&buf, framesize, uc->frame, UMP_MAP_ATTR, NULL, &uc->vregion); if (err_is_fail(err)) { cap_destroy(uc->frame); return err_push(err, LIB_ERR_VSPACE_MAP); } // initialise channel state err = ump_chan_init(uc, buf, inchanlen, (char *)buf + inchanlen, outchanlen); if (err_is_fail(err)) { vregion_destroy(uc->vregion); cap_destroy(uc->frame); return err; } // Ids for tracing struct frame_identity id; err = invoke_frame_identify(uc->frame, &id); if (err_is_fail(err)) { vregion_destroy(uc->vregion); cap_destroy(uc->frame); return err_push(err, LIB_ERR_FRAME_IDENTIFY); } uc->recvid = (uintptr_t)id.base; uc->sendid = (uintptr_t)(id.base + inchanlen); // store bind args uc->bind_continuation = cont; uc->monitor_binding = monitor_binding; uc->iref = iref; uc->inchanlen = inchanlen; uc->outchanlen = outchanlen; uc->notify_cap = notify_cap; // wait for the ability to use the monitor binding uc->connstate = UMP_BIND_WAIT; event_mutex_enqueue_lock(&monitor_binding->mutex, qnode, MKCLOSURE(send_bind_cont, uc)); return SYS_ERR_OK; }
void flounder_support_monitor_mutex_enqueue(struct monitor_binding *mb, struct event_queue_node *qn, struct event_closure cl) { event_mutex_enqueue_lock(&mb->mutex, qn, cl); }