Пример #1
0
/**
 * \brief Register an event handler to be notified when messages can be sent
 *
 * In the future, call the closure on the given waitset when it is likely that
 * a message can be sent on the channel. A channel may only be registered
 * with a single send event handler on a single waitset at any one time.
 *
 * \param lc LMP channel
 * \param ws Waitset
 * \param closure Event handler
 */
errval_t lmp_chan_register_send(struct lmp_chan *lc, struct waitset *ws,
                                 struct event_closure closure)
{
    assert(lc != NULL);
    assert(ws != NULL);

    errval_t err = waitset_chan_register(ws, &lc->send_waitset, closure);
    if (err_is_fail(err)) {
        return err;
    }

    // enqueue in list of channels with a registered event to retry sending
    assert(lc->next == NULL && lc->prev == NULL);
    dispatcher_handle_t handle = disp_disable();
    struct dispatcher_generic *dp = get_dispatcher_generic(handle);
    if (dp->lmp_send_events_list == NULL) {
        dp->lmp_send_events_list = lc;
        lc->next = lc->prev = lc;
    } else {
        lc->prev = dp->lmp_send_events_list->prev;
        lc->next = dp->lmp_send_events_list;
        lc->prev->next = lc;
        lc->next->prev = lc;
    }
    disp_enable(handle);

    return err;
}
Пример #2
0
static errval_t mp_create(struct descq_binding* b, uint32_t slots,
        struct capref rx, struct capref tx, bool notifications, uint8_t role,
        errval_t *err, uint64_t *queue_id) {
    
    struct descq* q = (struct descq*) b->st;
    DESCQ_DEBUG("start %p\n",q);
    
    // switch RX/TX for correct setup
    *err = vspace_map_one_frame_attr((void**) &(q->rx_descs),
                                    slots*DESCQ_ALIGNMENT, tx,
                                    VREGION_FLAGS_READ_WRITE, NULL, NULL);
    if (err_is_fail(*err)) {
        goto end2;
    }

    *err = vspace_map_one_frame_attr((void**) &(q->tx_descs),
                                    slots*DESCQ_ALIGNMENT, rx,
                                    VREGION_FLAGS_READ_WRITE, NULL, NULL);
    if (err_is_fail(*err)) {
        goto end1;
    }
 
    q->tx_seq_ack = (void*)q->tx_descs;
    q->rx_seq_ack = (void*)q->rx_descs;
    q->tx_descs++;
    q->rx_descs++;
    q->slots = slots-1;
    q->rx_seq = 1;
    q->tx_seq = 1;

    devq_init(&q->q, true);

    q->q.f.enq = descq_enqueue;
    q->q.f.deq = descq_dequeue;
    q->q.f.notify = descq_notify;
    q->q.f.reg = descq_register;
    q->q.f.dereg = descq_deregister;
    q->q.f.ctrl = descq_control;
    q->q.f.destroy = descq_destroy;

    notificator_init(&q->notificator, q, descq_can_read, descq_can_write);
    *err = waitset_chan_register(get_default_waitset(), &q->notificator.ready_to_read, MKCLOSURE(mp_notify, q));
    assert(err_is_ok(*err));

    *err = q->f.create(q, notifications, role, queue_id);
    if (err_is_ok(*err)) {
        goto end2;
    }

end1:
    *err = vspace_unmap(q->rx_descs);
    assert(err_is_ok(*err));
end2:
    DESCQ_DEBUG("end \n");
    return SYS_ERR_OK;
}
Пример #3
0
errval_t flounder_support_register(struct waitset *ws,
                                   struct waitset_chanstate *wc,
                                   struct event_closure ec,
                                   bool trigger_now)
{
    if (trigger_now) {
        return waitset_chan_trigger_closure(ws, wc, ec);
    } else {
        return waitset_chan_register(ws, wc, ec);
    }
}
Пример #4
0
/**
 * @brief initialized a descriptor queue
 */
errval_t descq_create(struct descq** q,
                      size_t slots,
                      char* name,
                      bool exp,
                      bool notifications,
                      uint8_t role,
                      uint64_t *queue_id,
                      struct descq_func_pointer* f)
{
    DESCQ_DEBUG("create start\n");
    errval_t err;
    struct descq* tmp;
    struct capref rx;
    struct capref tx;

    // Init basic struct fields
    tmp = malloc(sizeof(struct descq));
    assert(tmp != NULL);
    tmp->name = strdup(name);
    assert(tmp->name != NULL);

    if (exp) {  // exporting
        struct descq_endpoint_state* state = malloc(sizeof(struct descq_endpoint_state));
        state->name = strdup(name);
        assert(state->name);

        state->f.notify = f->notify;
        state->f.dereg = f->dereg;
        state->f.reg = f->reg;
        state->f.create = f->create;
        state->f.destroy = f->destroy;
        state->f.control = f->control;

        err = descq_export(state, export_cb, connect_cb,
                                get_default_waitset(), IDC_BIND_FLAGS_DEFAULT);
        if (err_is_fail(err)) {
            goto cleanup1;
        }

        while(!state->exp_done) {
            event_dispatch(get_default_waitset());
        }
    
    } else {

        tmp->f.notify = f->notify;
        tmp->f.dereg = f->dereg;
        tmp->f.reg = f->reg;
        tmp->f.create = f->create;
        tmp->f.destroy = f->destroy;
        tmp->f.control = f->control;
        size_t bytes;

        err = frame_alloc(&rx, DESCQ_ALIGNMENT*slots, &bytes);
        if (err_is_fail(err)) {
            goto cleanup1;
        }

        assert(bytes >= DESCQ_ALIGNMENT*slots);

        err = frame_alloc(&tx, DESCQ_ALIGNMENT*slots, &bytes);
        if (err_is_fail(err)) {
            goto cleanup2;
        }

        assert(bytes >= DESCQ_ALIGNMENT*slots);

        err = vspace_map_one_frame_attr((void**) &(tmp->rx_descs),
                                        slots*DESCQ_ALIGNMENT, rx,
                                        VREGION_FLAGS_READ_WRITE, NULL, NULL);
        if (err_is_fail(err)) {
            goto cleanup3;
        }

        err = vspace_map_one_frame_attr((void**) &(tmp->tx_descs),
                                        slots*DESCQ_ALIGNMENT, tx,
                                        VREGION_FLAGS_READ_WRITE, NULL, NULL);
        if (err_is_fail(err)) {
            goto cleanup4;
        }

        memset(tmp->tx_descs, 0, slots*DESCQ_ALIGNMENT);
        memset(tmp->rx_descs, 0, slots*DESCQ_ALIGNMENT);

        tmp->bound_done = false;
        iref_t iref;

        err = nameservice_blocking_lookup(name, &iref);
        if (err_is_fail(err)) {
            goto cleanup5;
        }

        err = descq_bind(iref, bind_cb, tmp, get_default_waitset(),
                              IDC_BIND_FLAGS_DEFAULT);
        if (err_is_fail(err)) {
            goto cleanup5;
        }
 
        while(!tmp->bound_done) {
            event_dispatch(get_default_waitset());
        }

        tmp->local_bind = tmp->binding->local_binding != NULL;

        errval_t err2;
        err = tmp->binding->rpc_tx_vtbl.create_queue(tmp->binding, slots, rx, tx,
            notifications, role, &err2, queue_id);
        if (err_is_fail(err) || err_is_fail(err2)) {
            err = err_is_fail(err) ? err: err2;
            goto cleanup5;
        }

        tmp->tx_seq_ack = (void*)tmp->tx_descs;
        tmp->rx_seq_ack = (void*)tmp->rx_descs;
        tmp->tx_seq_ack->value = 0;
        tmp->rx_seq_ack->value = 0;
        tmp->tx_descs++;
        tmp->rx_descs++;
        tmp->slots = slots-1;
        tmp->rx_seq = 1;
        tmp->tx_seq = 1;

        devq_init(&tmp->q, false);

        tmp->q.f.enq = descq_enqueue;
        tmp->q.f.deq = descq_dequeue;
        tmp->q.f.notify = descq_notify;
        tmp->q.f.reg = descq_register;
        tmp->q.f.dereg = descq_deregister;
        tmp->q.f.ctrl = descq_control;

        tmp->notifications = notifications;

        notificator_init(&tmp->notificator, tmp, descq_can_read, descq_can_write);
        err = waitset_chan_register(get_default_waitset(), &tmp->notificator.ready_to_read, MKCLOSURE(mp_notify, tmp));
        assert(err_is_ok(err));
    }


    *q = tmp;

    DESCQ_DEBUG("create end %p \n", *q);
    return SYS_ERR_OK;

cleanup5:
    vspace_unmap(tmp->rx_descs);
cleanup4:
    vspace_unmap(tmp->rx_descs);
cleanup3:
    cap_destroy(tx);
cleanup2:
    cap_destroy(rx);
cleanup1:
    free(tmp->name);
    free(tmp);

    return err;

}