Exemple #1
0
static void execute__rx(struct bomp_binding *_binding,
                        uint64_t fn, uint64_t arg, uint32_t tid, uint64_t icv_task)
{


    struct bomp_thread *t = _binding->st;
    struct bomp_tls *tls = thread_get_tls();

    BOMP_DEBUG_THREAD("execute__rx: %p %p, %lx\n", t, tls, icv_task);

    assert(t == &tls->r.thread);

    struct omp_icv_task icvt;
    memcpy(&icvt, (void *)icv_task, sizeof(struct omp_icv_task));

    bomp_icv_set_task(&icvt);

    tls->thread_id = tid;

    bomp_thread_fn_t func= (bomp_thread_fn_t)fn;

    // calling the function
    func((void *)arg);

    bomp_icv_set_task(NULL);
    tls->thread_id = -1;

    struct txq_msg_st *msg_st = txq_msg_st_alloc(&t->txq);
    if (msg_st == NULL) {
        BOMP_ERROR("allocation of message state failed: %" PRIu32 "\n", tid);
        return;
    }

    msg_st->send = done__tx;
    msg_st->err = SYS_ERR_OK;

    txq_send(msg_st);
}
Exemple #2
0
/**
 * \brief initializes a thread on the given core
 *
 * \@param core         ID of the core on which to create the tread on
 * \param stack_size    size of the stack of the tread to be created
 * \param thread        pointer to the thread struct to create
 *
 * \returns SYS_ERR_OK on SUCCESS
 *          errval on FAILURE
 */
errval_t bomp_thread_init(coreid_t core,
                          size_t stack_size,
                          struct bomp_thread *thread)
{
    errval_t err;

    BOMP_DEBUG_THREAD("Creating thread on core %"PRIuCOREID " \n", core);

    uint32_t done;

    err = domain_new_dispatcher(core, bomp_thread_init_done, &done);
    if (err_is_fail(err)) {
        BOMP_ERROR("creating new dispatcher on core %" PRIuCOREID "failed\n",
                   core);
        return err;
    }

    while(!done) {
        thread_yield();
    }

    BOMP_DEBUG_THREAD("dispatcher ready. allocating memory for msg channel\n");

    size_t msg_frame_size;
    err = frame_alloc(&thread->msgframe, 2 * BOMP_CHANNEL_SIZE, &msg_frame_size);
    if (err_is_fail(err)) {
        return err;
    }

    err = vspace_map_one_frame(&thread->msgbuf, msg_frame_size, thread->msgframe,
                               NULL, NULL);
    if (err_is_fail(err)) {
        return err;
    }

    struct bomp_frameinfo fi = {
        .sendbase = (lpaddr_t)thread->msgbuf + BOMP_CHANNEL_SIZE,
        .inbuf = thread->msgbuf,
        .inbufsize = BOMP_CHANNEL_SIZE,
        .outbuf = ((uint8_t *) thread->msgbuf) + BOMP_CHANNEL_SIZE,
        .outbufsize = BOMP_CHANNEL_SIZE
    };

    BOMP_DEBUG_THREAD("creating channel on %p\n", thread->msgbuf);

    err = bomp_accept(&fi, thread, bomp_thread_accept_cb,
                      get_default_waitset(), IDC_EXPORT_FLAGS_DEFAULT);

    if (err_is_fail(err)) {
        // XXX> error handling
        return err;
    }

    BOMP_DEBUG_THREAD("creating thread on core %" PRIuCOREID "\n", core);
    err = domain_thread_create_on(core, bomp_thread_msg_handler, thread->msgbuf);
    if (err_is_fail(err)) {
        // XXX> error handling
        return err;
    }

    while (thread->ctrl == NULL) {
        err = event_dispatch(get_default_waitset());
        if (err_is_fail(err)) {
            USER_PANIC_ERR(err, "event dispatch\n");
        }
    }

    BOMP_DEBUG_THREAD("thread on core %" PRIuCOREID " connected \n", core);

    return thread->thread_err;
}

errval_t bomp_thread_exec(struct bomp_thread *thread,
                          bomp_thread_fn_t fn, void *arg, uint32_t tid)
{
    debug_printf("bomp_thread_exec(%p, %p, %p, %u) %p\n", thread, fn, arg, tid, thread->icvt);
    struct txq_msg_st *msg_st = txq_msg_st_alloc(&thread->txq);
    if (msg_st == NULL) {
        return LIB_ERR_MALLOC_FAIL;
    }

    uint32_t msg_sent = 0;

    msg_st->send = execute__tx;
    msg_st->cleanup = (txq_cleanup_fn_t)txq_msg_sent_cb;

    struct bomp_msg_st *bomp_msg_st = (struct bomp_msg_st *)msg_st;

    bomp_msg_st->args.exec.arg = (uint64_t)arg;
    bomp_msg_st->args.exec.fn = (uint64_t)fn;
    bomp_msg_st->args.exec.tid = tid;
    bomp_msg_st->args.exec.icv = (uint64_t)thread->icvt;
    bomp_msg_st->message_sent = &msg_sent;

    txq_send(msg_st);

    while(msg_sent == 0) {
        event_dispatch(get_default_waitset());
    }

    //return event_dispatch_non_block(get_default_waitset());
    return SYS_ERR_OK;
}
static void add_memory_call_rx(struct xomp_binding *b,
                               struct capref frame,
                               uint64_t addr,
                               uint8_t type)
{
    XWI_DEBUG("add_memory_call_rx: addr:%lx, tyep: %u\n", addr, type);

    struct txq_msg_st *msg_st = txq_msg_st_alloc(&txq);
    assert(msg_st != NULL);

    msg_st->send = add_memory_response_tx;
    msg_st->cleanup = NULL;

    uint32_t map_flags = 0x0;

    switch ((xomp_frame_type_t) type) {
        case XOMP_FRAME_TYPE_MSG:
            map_flags = VREGION_FLAGS_READ_WRITE;
            break;
        case XOMP_FRAME_TYPE_SHARED_RW:
            map_flags = VREGION_FLAGS_READ_WRITE;
            break;
        case XOMP_FRAME_TYPE_SHARED_RO:
            map_flags = VREGION_FLAGS_READ;
            break;
        default:
            USER_PANIC("unknown type: %u", type)
            break;
    }
    struct frame_identity id;
    msg_st->err = invoke_frame_identify(frame, &id);
    if(err_is_fail(msg_st->err)) {
        txq_send(msg_st);
        return;
    }

#if XOMP_WORKER_ENABLE_DMA
    if (0) {
        // todo: replicate frame on the same node if needed..
        replicate_frame(addr, &frame);
    }
#endif

#if XOMP_BENCH_WORKER_EN
    cycles_t map_start = bench_tsc();
#endif
    if (addr) {
        msg_st->err = vspace_map_one_frame_fixed_attr(addr, (1UL << id.bits),
                                                      frame, map_flags, NULL, NULL);
    } else {
        void *map_addr;
        msg_st->err = vspace_map_one_frame_attr(&map_addr, (1UL << id.bits),
                                                frame, map_flags, NULL, NULL);
    }
#if XOMP_BENCH_WORKER_EN
    cycles_t timer_end = bench_tsc();
    debug_printf("%lx mem map %016lx took  %lu cycles, %lu ms\n", worker_id, addr,
                     timer_end - map_start, bench_tsc_to_ms(timer_end - map_start));
#endif

    txq_send(msg_st);
}
static void do_work_rx(struct xomp_binding *b,
                       uint64_t fn,
                       uint64_t arg,
                       uint64_t id,
                       uint64_t flags)
{
    errval_t err;

    XWP_DEBUG("do_work_rx: fn:%lx, id:%lx\n", fn, id);

#if XOMP_BENCH_WORKER_EN
    cycles_t work_timer = bench_tsc();
#endif

    struct txq_msg_st *msg_st = txq_msg_st_alloc(&txq);
    assert(msg_st != NULL);

    msg_st->err = SYS_ERR_OK;

    struct bomp_work *work = tls;

    XWP_DEBUG("do_work_rx: threadid = %u, nthreads = %u\n", work->thread_id,
              work->num_threads);

    g_bomp_state->num_threads = work->num_threads;

    struct xomp_msg_st *st = (struct xomp_msg_st *) msg_st;
    st->args.done_notify.id = id;

    if (arg) {
        msg_st->send = done_with_arg_tx;
        st->args.done_notify.arg = arg;
    } else {
        msg_st->send = done_notify_tx;
    }

    if (fn & XOMP_FN_INDEX_FLAG) {
        uint32_t idx = fn & ~XOMP_FN_INDEX_FLAG;
        char *fn_name;
        err = spawn_symval_lookup_idx(idx, &fn_name, &fn);
        if (err_is_fail(err)) {
            msg_st->err = err;
            txq_send(msg_st);
            return;
        }
        XWP_DEBUG("do_work_rx: function index %u -> %s\n", idx, fn_name);
    }

    xomp_worker_fn_t fnct = (xomp_worker_fn_t) fn;
    XWP_DEBUG("do_work_rx: calling fnct %p with argument %p\n", fnct, work->data);

    for (uint32_t i = 0; i < work->num_vtreads; ++i) {
        fnct(work->data);
        work->thread_id++;
    }



#if XOMP_BENCH_WORKER_EN
    work_timer = bench_tsc() - work_timer;
    debug_printf("%lx work took %lu cycles, %lu ms\n", worker_id, work_timer,
                 bench_tsc_to_ms(work_timer));
#endif

    txq_send(msg_st);
}
static void gw_req_memory_call_rx(struct xomp_binding *b,
                                  uint64_t addr,
                                  uint8_t type)
{
    XWI_DEBUG("gw_req_memory_call_rx: addr:%lx, tyep: %u\n", addr, type);

#if XOMP_BENCH_WORKER_EN
    cycles_t mem_timer = bench_tsc();
#endif

    struct txq_msg_st *msg_st = txq_msg_st_alloc(&txq);
    assert(msg_st != NULL);

    struct capref frame;
    if (type == XOMP_FRAME_TYPE_REPL_RW) {
        type = XOMP_FRAME_TYPE_SHARED_RW;
    }
    assert(!(worker_id & XOMP_WID_GATEWAY_FLAG));

    msg_st->send = gw_req_memory_response_tx;
    msg_st->cleanup = NULL;

    XWR_DEBUG("Requesting frame from gateway: [%016lx]\n", usrdata);

    msg_st->err = xomp_gateway_get_memory(addr, &frame);
    if (err_is_fail(msg_st->err)) {
        txq_send(msg_st);
        return;
    }

    vregion_flags_t map_flags;

    switch ((xomp_frame_type_t) type) {
        case XOMP_FRAME_TYPE_MSG:
            map_flags = VREGION_FLAGS_READ_WRITE;
            break;
        case XOMP_FRAME_TYPE_SHARED_RW:
        case XOMP_FRAME_TYPE_REPL_RW:
            map_flags = VREGION_FLAGS_READ_WRITE;
            break;
        case XOMP_FRAME_TYPE_SHARED_RO:
            map_flags = VREGION_FLAGS_READ;
            break;
        default:
            USER_PANIC("unknown type: %u", type)
            break;
    }

    struct frame_identity id;
    msg_st->err = invoke_frame_identify(frame, &id);
    if (err_is_fail(msg_st->err)) {
        txq_send(msg_st);
        return;
    }

    if (addr) {
        msg_st->err = vspace_map_one_frame_fixed_attr(addr, (1UL << id.bits),
                                                      frame, map_flags, NULL, NULL);
    } else {
        void *map_addr;
        msg_st->err = vspace_map_one_frame_attr(&map_addr, (1UL << id.bits),
                                                frame, map_flags, NULL, NULL);
    }

#if XOMP_BENCH_WORKER_EN
    mem_timer = bench_tsc() - mem_timer;
    debug_printf("%lx mem request %016lx took  %lu cycles, %lu ms\n", worker_id,
                 addr, mem_timer, bench_tsc_to_ms(mem_timer));
#endif

    txq_send(msg_st);
}