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); }
/** * \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); }