static void averageLocalBF(void) { struct thread** threads = malloc(arraySize * sizeof(struct thread*)); struct averageLocalArgs* args; int i; for(i = 0; i<arraySize; i++){ args = malloc(sizeof(struct averageLocalArgs)); args->arraySize = arraySize; args->loops = loops; args->id = i; float* arrayCopy = malloc(arraySize * sizeof(float)); memcpy(arrayCopy, globalArray, arraySize * sizeof(float)); args->array = arrayCopy; domain_thread_create_on(rrPlacement(), averageLocalWorkBF, args, &threads[i]); } for(i = 0; i<arraySize; i++){ int result; domain_thread_join(threads[i], &result); globalArray[i] = result; } free(threads); }
int main(int argc, char *argv[]) { errval_t err; if (argc != 2) { printf("Usage %s: <Num additional threads>\n", argv[0]); exit(-1); } //printf("main running on %d\n", disp_get_core_id()); int cores = strtol(argv[1], NULL, 10) + 1; NPROC = cores -1; BARINIT(barrier, NPROC); uint64_t before = rdtsc(); times[0] = before; trace_event(TRACE_SUBSYS_BENCH, TRACE_EVENT_BENCH_PCBENCH, 1); for (int i = 1; i < cores; i++) { err = domain_new_dispatcher(i + disp_get_core_id(), domain_spanned_callback, (void*)(uintptr_t)i); if (err_is_fail(err)) { USER_PANIC_ERR(err, "domain_new_dispatcher failed"); } } while (ndispatchers < cores) { thread_yield(); } uint64_t finish = rdtsc(); trace_event(TRACE_SUBSYS_BENCH, TRACE_EVENT_BENCH_PCBENCH, 0); //sys_print("\nDone\n", 6); printf("spantest: Done in %"PRIu64" cycles\n", finish-before); //trace_dump(); for(int i = 1; i < cores; i++) { err = domain_thread_create_on(i, remote, NULL); assert(err_is_ok(err)); } messages_handler_loop(); return 0; }
static void averageSharedBF(void) { struct thread** threads = malloc(arraySize * sizeof(struct thread*)); struct averageSharedArgs* args; int i; for(i = 0; i<arraySize; i++){ args = malloc(sizeof(struct averageSharedArgs)); args->id = i; if(i > 0) { args->left = globalArray[i-1];} if(i < arraySize - 1) { args->right = globalArray[i+1];} domain_thread_create_on(rrPlacement(), averageSharedWorkBF, args, &threads[i]); } for(i = 0; i<arraySize; i++){ domain_thread_join(threads[i], NULL); } free(threads); }
/** * \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; }
/** Initialise the tweed library - must be called before any other * tweed calls */ int init_tweed(int workers_requested, int(*main_func)(struct generic_task_desc *,void*), void* main_args) { int i, err; if (workers_requested < 1) { fprintf(stderr, "Error initalizing tweed - requested less than 1 worker\n"); return -1; } num_workers = workers_requested; workers = (struct worker_desc *) malloc ( num_workers * sizeof(struct worker_desc)); // alloc task stack space for all workers, leave space for alignment task_stack_space = malloc (TWEED_TASK_STACK_SIZE * (num_workers + 1)); char * curr_stack_space = (char*)(((unsigned long)task_stack_space + TWEED_TASK_STACK_SIZE) & ~TWEED_TASK_STACK_MASK); // Initialize worker data-structures for (i=0; i<num_workers; i++) { init_worker(i, curr_stack_space); curr_stack_space += TWEED_TASK_STACK_SIZE; } // create dispatchers on all other cores required for num_workers for (i=1; i<num_workers; i++) { err = domain_new_dispatcher(i + disp_get_core_id(), domain_spanned_callback, (void*)(uintptr_t)i); if (err_is_fail(err)) { DEBUG_ERR(err, "domain_new_dispatcher failed"); printf("%d failed\n", i); } } // wait for all dispatchers to come up while (num_dispatchers < num_workers) { messages_wait_and_handle_next(); } num_dispatchers = 1; // reset // start work stealing threads on newly created domains for (i = 1; i < num_workers; i++) { struct worker_args * args = (struct worker_args *) malloc ( sizeof(struct worker_args)); args->id = i; args->origin = disp_get_core_id(); err = domain_thread_create_on(i + disp_get_core_id(), start_worker_thread, args); if (err_is_fail(err)) { DEBUG_ERR(err, "Failed to run a function on remote core"); } } // wait for all dispatchers to come up while (num_dispatchers < num_workers) { messages_wait_and_handle_next(); } // now start the main worker on the current dispatcher return main_worker(0, main_func, main_args); }