Example #1
0
/*
 * 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));
}
Example #2
0
/**
 * \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));
    }

}
Example #3
0
/**
 * \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));
}
Example #4
0
/// 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));
}
Example #5
0
/**
 * \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;
}
Example #6
0
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));
}
Example #7
0
/**
 * \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);
}