static void thread_hello(void *arg) { int old_rank, cur_rank; ABT_thread self; ABT_thread_id id; char *msg; ABT_xstream_self_rank(&cur_rank); ABT_thread_self(&self); ABT_thread_get_id(self, &id); ABT_thread_release(self); test_printf("[U%lu:E%d] Hello, world!\n", id, cur_rank); ABT_thread_yield(); old_rank = cur_rank; ABT_xstream_self_rank(&cur_rank); msg = (cur_rank == old_rank) ? "" : " (stolen)"; test_printf("[U%lu:E%d] Hello again #1.%s\n", id, cur_rank, msg); ABT_thread_yield(); old_rank = cur_rank; ABT_xstream_self_rank(&cur_rank); msg = (cur_rank == old_rank) ? "" : " (stolen)"; test_printf("[U%lu:E%d] Hello again #2.%s\n", id, cur_rank, msg); ABT_thread_yield(); old_rank = cur_rank; ABT_xstream_self_rank(&cur_rank); msg = (cur_rank == old_rank) ? "" : " (stolen)"; test_printf("[U%lu:E%d] Goodbye, world!%s\n", id, cur_rank, msg); }
void thread_func(void *arg) { thread_arg_t *t_arg = (thread_arg_t *)arg; ABT_thread_yield(); ABT_mutex_lock(t_arg->mutex); g_counter++; ABT_mutex_unlock(t_arg->mutex); ABT_test_printf(1, "[TH%d] increased\n", t_arg->id); ABT_thread_yield(); }
void ds_mgmt_hdlr_svc_rip(crt_rpc_t *rpc) { struct mgmt_svc_rip_in *murderer; int sig; bool force; d_rank_t rank = -1; murderer = crt_req_get(rpc); if (murderer == NULL) return; force = (murderer->rip_flags != 0); /* * the yield below is to workaround an ofi err msg at client-side - * fi_cq_readerr got err: 5(Input/output error) .. */ int i; for (i = 0; i < 200; i++) { ABT_thread_yield(); usleep(10); } /** ... adieu */ if (force) sig = SIGKILL; else sig = SIGTERM; crt_group_rank(NULL, &rank); D_PRINT("Service rank %d is being killed by signal %d... farewell\n", rank, sig); kill(getpid(), sig); }
void thread_func_migrate_to_xstream(void *arg) { arg_t *my_arg = (arg_t *)arg; int eid = my_arg->eid; ABT_xstream cur_xstream, tar_xstream; ABT_thread self; int i, next; ABT_thread_self(&self); for (i = 0; i < iter; i++) { next = (eid + 1) % num_xstreams; tar_xstream = g_xstreams[next]; ABT_thread_migrate_to_xstream(self, tar_xstream); while (1) { ABT_bool flag; ABT_xstream_self(&cur_xstream); ABT_xstream_equal(cur_xstream, tar_xstream, &flag); if (flag == ABT_TRUE) { break; } ABT_thread_yield(); } eid = next; } }
void thread_func_yield(void *arg) { ABT_TEST_UNUSED(arg); int i; for (i = 0; i < iter; i++) { ABT_thread_yield(); } }
void accalt_yield() { #ifdef ARGOBOTS ABT_thread_yield(); #endif #ifdef MASSIVETHREADS myth_yield(0); #endif #ifdef QTHREADS qthread_yield(); #endif }
int main(int argc, char *argv[]) { int ret; ABT_xstream xstream; /* init and thread creation */ ABT_test_init(argc, argv); ret = ABT_xstream_self(&xstream); ABT_TEST_ERROR(ret, "ABT_xstream_self"); /* Get the pools attached to an execution stream */ ABT_pool pool; ret = ABT_xstream_get_main_pools(xstream, 1, &pool); ABT_TEST_ERROR(ret, "ABT_xstream_get_main_pools"); ret = ABT_thread_create(pool, fn1, NULL, ABT_THREAD_ATTR_NULL, &th1); ABT_TEST_ERROR(ret, "ABT_thread_create"); ret = ABT_thread_create(pool, fn2, NULL, ABT_THREAD_ATTR_NULL, &th2); ABT_TEST_ERROR(ret, "ABT_thread_create"); ret = ABT_thread_create(pool, fn3, NULL, ABT_THREAD_ATTR_NULL, &th3); ABT_TEST_ERROR(ret, "ABT_thread_create"); ret = ABT_eventual_create(EVENTUAL_SIZE, &myeventual); ABT_TEST_ERROR(ret, "ABT_eventual_create"); ABT_test_printf(1, "START\n"); void *data; ABT_test_printf(1, "Thread main iteration %d waiting for eventual\n", 0); ABT_eventual_wait(myeventual,&data); ABT_test_printf(1, "Thread main continue iteration %d returning from " "eventual\n", 0); /* switch to other user-level threads */ ABT_thread_yield(); /* join other threads */ ret = ABT_thread_join(th1); ABT_TEST_ERROR(ret, "ABT_thread_join"); ret = ABT_thread_join(th2); ABT_TEST_ERROR(ret, "ABT_thread_join"); ret = ABT_thread_join(th3); ABT_TEST_ERROR(ret, "ABT_thread_join"); ABT_test_printf(1, "END\n"); ret = ABT_test_finalize(0); return ret; }
void test_create_unnamed(void *arg) { int eid = (int)(size_t)arg; ABT_pool my_pool = g_pools[eid]; int i, t; for (i = 0; i < iter; i++) { for (t = 0; t < num_threads; t++) { ABT_thread_create(my_pool, thread_func, NULL, ABT_THREAD_ATTR_NULL, NULL); } ABT_thread_yield(); } }
void thread_func_yield_to_overhead(void *arg) { arg_t *my_arg = (arg_t *)arg; int eid = my_arg->eid; int tid = my_arg->tid; int nid = (tid + 1) % num_threads; ABT_thread next = g_threads[eid][nid]; ABT_TEST_UNUSED(next); int i; for (i = 0; i < iter; i++) { } ABT_thread_yield(); }
static void thread_func(void *arg) { unit_arg_t *my_arg = (unit_arg_t *)arg; ABT_bool valid; valid = verify_exec_order(my_arg->es_id, my_arg->prio); assert(valid == ABT_TRUE); ABT_test_printf(1, "[E%d:U%d:P%d] before yield\n", my_arg->es_id, my_arg->my_id, my_arg->prio); ABT_thread_yield(); valid = verify_exec_order(my_arg->es_id, my_arg->prio); assert(valid == ABT_TRUE); ABT_test_printf(1, "[E%d:U%d:P%d] after yield\n", my_arg->es_id, my_arg->my_id, my_arg->prio); free(my_arg); }
/* Daemon ULT for processing RPC replies */ void rdb_recvd(void *arg) { struct rdb *db = arg; D_DEBUG(DB_MD, DF_DB": recvd starting\n", DP_DB(db)); for (;;) { struct rdb_raft_rpc *rrpc = NULL; bool stop; ABT_mutex_lock(db->d_mutex); for (;;) { stop = db->d_stop; if (!d_list_empty(&db->d_replies)) { rrpc = d_list_entry(db->d_replies.next, struct rdb_raft_rpc, drc_entry); d_list_del_init(&rrpc->drc_entry); break; } if (stop) break; ABT_cond_wait(db->d_replies_cv, db->d_mutex); } ABT_mutex_unlock(db->d_mutex); if (rrpc == NULL) { D_ASSERT(stop); /* The queue is empty and we are asked to stop. */ break; } /* * The queue has pending replies. If we are asked to stop, skip * the processing but still free the RPCs until the queue * become empty. */ if (!stop) rdb_raft_process_reply(db, rrpc->drc_rpc); rdb_raft_free_request(db, rrpc->drc_rpc); rdb_free_raft_rpc(rrpc); ABT_thread_yield(); }
static void thread_join_xstream(void *arg) { char send_buf[SEND_BUF_LEN]; int idx = num_xstreams - 1; int n; ABT_xstream_state state; g_signal[idx] = 1; while (1) { ABT_xstream_get_state(g_xstreams[idx], &state); if (state == ABT_XSTREAM_STATE_TERMINATED) break; ABT_thread_yield(); } ABT_xstream_free(&g_xstreams[idx]); num_xstreams--; if (abt_alive) { printf("# of ESs: %d\n", num_xstreams); sprintf(send_buf, "done (%d)", num_xstreams); n = write(abt_pfd.fd, send_buf, strlen(send_buf)); assert(n == strlen(send_buf)); } }
void rt1_finalize(void) { int i; while (rt1_data->num_xstreams > 0) { ABT_thread_yield(); } for (i = 0; i < rt1_data->max_xstreams; i++) { assert(rt1_data->xstreams[i] == ABT_XSTREAM_NULL); } /* Delete registered callbacks */ ABT_event_del_callback(ABT_EVENT_STOP_XSTREAM, rt1_data->stop_cb_id); ABT_event_del_callback(ABT_EVENT_ADD_XSTREAM, rt1_data->add_cb_id); ABT_mutex_lock(rt1_data->mutex); ABT_mutex_free(&rt1_data->mutex); ABT_barrier_free(&rt1_data->bar); free(rt1_data->xstreams); free(rt1_data->app_data); free(rt1_data); rt1_data = NULL; }
void rt1_launcher(void *arg) { int idx = (int)(intptr_t)arg; ABT_thread cur_thread; ABT_pool cur_pool; ABT_sched_config config; ABT_sched sched; size_t size; double t_start, t_end; ABT_sched_config_var cv_event_freq = { .idx = 0, .type = ABT_SCHED_CONFIG_INT }; ABT_sched_config_var cv_idx = { .idx = 1, .type = ABT_SCHED_CONFIG_INT }; ABT_sched_def sched_def = { .type = ABT_SCHED_TYPE_ULT, .init = sched_init, .run = sched_run, .free = sched_free, .get_migr_pool = NULL }; /* Create a scheduler */ ABT_sched_config_create(&config, cv_event_freq, 10, cv_idx, idx, ABT_sched_config_var_end); ABT_sched_create(&sched_def, 1, &rt1_data->pool, config, &sched); /* Push the scheduler to the current pool */ ABT_thread_self(&cur_thread); ABT_thread_get_last_pool(cur_thread, &cur_pool); ABT_pool_add_sched(cur_pool, sched); /* Free */ ABT_sched_config_free(&config); t_start = ABT_get_wtime(); while (1) { rt1_app(idx); ABT_pool_get_total_size(cur_pool, &size); if (size == 0) { ABT_sched_free(&sched); int rank; ABT_xstream_self_rank(&rank); printf("ES%d: finished\n", rank); ABT_mutex_lock(rt1_data->mutex); rt1_data->xstreams[rank] = ABT_XSTREAM_NULL; rt1_data->num_xstreams--; ABT_mutex_unlock(rt1_data->mutex); break; } t_end = ABT_get_wtime(); if ((t_end - t_start) > g_timeout) { ABT_sched_finish(sched); } } } static void rt1_app(int eid) { int i, num_comps; size_t size; ABT_thread cur_thread; ABT_pool cur_pool; ABT_thread_self(&cur_thread); ABT_thread_get_last_pool(cur_thread, &cur_pool); if (eid == 0) ABT_event_prof_start(); num_comps = rt1_data->num_comps; for (i = 0; i < num_comps * 2; i += 2) { ABT_thread_create(rt1_data->pool, rt1_app_compute, (void *)(intptr_t)(eid * num_comps * 2 + i), ABT_THREAD_ATTR_NULL, NULL); ABT_task_create(rt1_data->pool, rt1_app_compute, (void *)(intptr_t)(eid * num_comps * 2 + i + 1), NULL); } do { ABT_thread_yield(); /* If the size of cur_pool is zero, it means the stacked scheduler has * been terminated because of the shrinking event. */ ABT_pool_get_total_size(cur_pool, &size); if (size == 0) break; ABT_pool_get_total_size(rt1_data->pool, &size); } while (size > 0); if (eid == 0) { ABT_event_prof_stop(); int cnt = __atomic_exchange_n(&rt1_data->cnt, 0, __ATOMIC_SEQ_CST); double local_work = (double)(cnt * rt1_data->num_iters); ABT_event_prof_publish("ops", local_work, local_work); } } static void rt1_app_compute(void *arg) { int pos = (int)(intptr_t)arg; int i; rt1_data->app_data[pos] = 0; for (i = 0; i < rt1_data->num_iters; i++) { rt1_data->app_data[pos] += sin((double)pos); } __atomic_fetch_add(&rt1_data->cnt, 1, __ATOMIC_SEQ_CST); }
int main(int argc, char *argv[]) { int i, j; int ret; int num_xstreams = DEFAULT_NUM_XSTREAMS; int num_threads = DEFAULT_NUM_THREADS; if (argc > 1) num_xstreams = atoi(argv[1]); assert(num_xstreams >= 0); if (argc > 2) num_threads = atoi(argv[2]); assert(num_threads >= 0); ABT_xstream *xstreams; ABT_thread **threads; thread_arg_t **args; xstreams = (ABT_xstream *)malloc(sizeof(ABT_xstream) * num_xstreams); threads = (ABT_thread **)malloc(sizeof(ABT_thread *) * num_xstreams); args = (thread_arg_t **)malloc(sizeof(thread_arg_t *) * num_xstreams); for (i = 0; i < num_xstreams; i++) { threads[i] = (ABT_thread *)malloc(sizeof(ABT_thread) * num_threads); for (j = 0; j < num_threads; j++) { threads[i][j] = ABT_THREAD_NULL; } args[i] = (thread_arg_t *)malloc(sizeof(thread_arg_t) * num_threads); } /* Initialize */ ABT_test_init(argc, argv); /* Create Execution Streams */ ret = ABT_xstream_self(&xstreams[0]); ABT_TEST_ERROR(ret, "ABT_xstream_self"); for (i = 1; i < num_xstreams; i++) { ret = ABT_xstream_create(ABT_SCHED_NULL, &xstreams[i]); ABT_TEST_ERROR(ret, "ABT_xstream_create"); } /* Get the pools attached to an execution stream */ ABT_pool *pools; pools = (ABT_pool *)malloc(sizeof(ABT_pool) * num_xstreams); for (i = 0; i < num_xstreams; i++) { ret = ABT_xstream_get_main_pools(xstreams[i], 1, pools+i); ABT_TEST_ERROR(ret, "ABT_xstream_get_main_pools"); } /* Create threads */ for (i = 0; i < num_xstreams; i++) { for (j = 0; j < num_threads; j++) { int tid = i * num_threads + j + 1; args[i][j].id = tid; args[i][j].num_threads = num_threads; args[i][j].threads = &threads[i][0]; ret = ABT_thread_create(pools[i], thread_func, (void *)&args[i][j], ABT_THREAD_ATTR_NULL, &threads[i][j]); ABT_TEST_ERROR(ret, "ABT_thread_create"); } } /* Switch to other user level threads */ ABT_thread_yield(); /* Join Execution Streams */ for (i = 1; i < num_xstreams; i++) { ret = ABT_xstream_join(xstreams[i]); ABT_TEST_ERROR(ret, "ABT_xstream_join"); } /* Free threads and Execution Streams */ for (i = 0; i < num_xstreams; i++) { for (j = 0; j < num_threads; j++) { ret = ABT_thread_free(&threads[i][j]); ABT_TEST_ERROR(ret, "ABT_thread_free"); } if (i == 0) continue; ret = ABT_xstream_free(&xstreams[i]); ABT_TEST_ERROR(ret, "ABT_xstream_free"); } /* Finalize */ ret = ABT_test_finalize(0); for (i = 0; i < num_xstreams; i++) { free(args[i]); free(threads[i]); } free(args); free(threads); free(pools); free(xstreams); return ret; }
/* Main function */ int main(int argc, char *argv[]) { int n, i, result, expected; int num_xstreams; ABT_xstream *xstreams; ABT_thread thread; thread_args args_thread; ABT_task task; task_args *args_task; if (argc > 1 && strcmp(argv[1], "-h") == 0) { printf("Usage: %s [N=10] [num_ES=4]\n", argv[0]); return EXIT_SUCCESS; } n = argc > 1 ? atoi(argv[1]) : N; num_xstreams = argc > 2 ? atoi(argv[2]) : NUM_XSTREAMS; printf("# of ESs: %d\n", num_xstreams); if (n <= 2) { result = 1; goto fn_result; } /* initialization */ ABT_init(argc, argv); /* shared pool creation */ ABT_pool_create_basic(ABT_POOL_FIFO, ABT_POOL_ACCESS_MPMC, ABT_TRUE, &g_pool); /* ES creation */ xstreams = (ABT_xstream *)malloc(sizeof(ABT_xstream) * num_xstreams); ABT_xstream_self(&xstreams[0]); ABT_xstream_set_main_sched_basic(xstreams[0], ABT_SCHED_DEFAULT, 1, &g_pool); for (i = 1; i < num_xstreams; i++) { ABT_xstream_create_basic(ABT_SCHED_DEFAULT, 1, &g_pool, ABT_SCHED_CONFIG_NULL, &xstreams[i]); ABT_xstream_start(xstreams[i]); } /* creating thread */ args_thread.n = n - 1; args_thread.eventual = ABT_EVENTUAL_NULL; ABT_thread_create(g_pool, fibonacci_thread, &args_thread, ABT_THREAD_ATTR_NULL, &thread); /* creating task */ args_task = (task_args *)malloc(sizeof(task_args)); args_task->n = n - 2; args_task->result = 0; ABT_mutex_create(&args_task->mutex); args_task->parent = NULL; ABT_task_create(g_pool, fibonacci_task, args_task, &task); /* switch to other user-level threads */ ABT_thread_yield(); /* join other threads */ ABT_thread_join(thread); ABT_thread_free(&thread); /* join ESs */ for (i = 1; i < num_xstreams; i++) { ABT_xstream_join(xstreams[i]); ABT_xstream_free(&xstreams[i]); } result = args_thread.result + args_task->result; free(args_task); ABT_finalize(); free(xstreams); fn_result: printf("Fib(%d): %d\n", n, result); expected = verify(n); if (result != expected) { fprintf(stderr, "ERROR: expected=%d\n", expected); exit(EXIT_FAILURE); } return EXIT_SUCCESS; }
/* Create a work-stealing scheduler and push it to the pool */ static void thread_add_sched(void *arg) { int idx = (int)(intptr_t)arg; int i; ABT_thread cur_thread; ABT_pool cur_pool; ABT_pool *my_pools; ABT_sched_config config; ABT_sched sched; size_t size; double t_start, t_end; ABT_sched_config_var cv_event_freq = { .idx = 0, .type = ABT_SCHED_CONFIG_INT }; ABT_sched_config_var cv_idx = { .idx = 1, .type = ABT_SCHED_CONFIG_INT }; ABT_sched_def sched_def = { .type = ABT_SCHED_TYPE_ULT, .init = sched_init, .run = sched_run, .free = sched_free, .get_migr_pool = NULL }; /* Create a scheduler */ ABT_sched_config_create(&config, cv_event_freq, 10, cv_idx, idx, ABT_sched_config_var_end); my_pools = (ABT_pool *)malloc(sizeof(ABT_pool) * max_xstreams); for (i = 0; i < max_xstreams; i++) { my_pools[i] = g_pools[(idx + i) % max_xstreams]; } ABT_sched_create(&sched_def, max_xstreams, my_pools, config, &sched); /* Create a ULT for the new scheduler */ ABT_thread_create(my_pools[0], thread_work, arg, ABT_THREAD_ATTR_NULL, NULL); /* Push the scheduler to the current pool */ ABT_thread_self(&cur_thread); ABT_thread_get_last_pool(cur_thread, &cur_pool); ABT_pool_add_sched(cur_pool, sched); /* Free */ ABT_thread_release(cur_thread); ABT_sched_config_free(&config); free(my_pools); t_start = ABT_get_wtime(); while (1) { ABT_thread_yield(); ABT_pool_get_total_size(cur_pool, &size); if (size == 0) { ABT_sched_free(&sched); break; } t_end = ABT_get_wtime(); if ((t_end - t_start) > g_timeout) { ABT_sched_finish(sched); } } } static void thread_work(void *arg) { int idx = (int)(intptr_t)arg; int i; ABT_thread cur_thread; ABT_pool cur_pool; ABT_thread *threads; int num_threads; double t_start, t_end; ABT_thread_self(&cur_thread); ABT_thread_get_last_pool(cur_thread, &cur_pool); ABT_thread_release(cur_thread); t_start = ABT_get_wtime(); while (1) { num_threads = 2; threads = (ABT_thread *)malloc(sizeof(ABT_thread) * num_threads); for (i = 0; i < num_threads; i++) { ABT_thread_create(cur_pool, thread_hello, NULL, ABT_THREAD_ATTR_NULL, &threads[i]); } for (i = 0; i < num_threads; i++) { ABT_thread_free(&threads[i]); } free(threads); if (g_signal[idx]) { ABT_xstream xstream; ABT_xstream_self(&xstream); ABT_xstream_cancel(xstream); g_signal[idx] = 0; break; } t_end = ABT_get_wtime(); if ((t_end - t_start) > g_timeout) { break; } } } static void test_printf(const char *format, ...) { #if 0 va_start(list, format); vprintf(format, list); va_end(list); fflush(stdout); #endif }
/** * @ingroup COND * @brief Wait on the condition. * * The ULT calling \c ABT_cond_timedwait() waits on the condition variable * until it is signaled or the absolute time specified by \c abstime passes. * If system time equals or exceeds \c abstime before \c cond is signaled, * the error code \c ABT_ERR_COND_TIMEDOUT is returned. * * The user should call this routine while the mutex specified as \c mutex is * locked. The mutex will be automatically released while waiting. After signal * is received and the waiting ULT is awakened, the mutex will be * automatically locked for use by the ULT. The user is then responsible for * unlocking mutex when the ULT is finished with it. * * @param[in] cond handle to the condition variable * @param[in] mutex handle to the mutex * @param[in] abstime absolute time for timeout * @return Error code * @retval ABT_SUCCESS on success * @retval ABT_ERR_COND_TIMEDOUT timeout */ int ABT_cond_timedwait(ABT_cond cond, ABT_mutex mutex, const struct timespec *abstime) { int abt_errno = ABT_SUCCESS; ABTI_cond *p_cond = ABTI_cond_get_ptr(cond); ABTI_CHECK_NULL_COND_PTR(p_cond); ABTI_mutex *p_mutex = ABTI_mutex_get_ptr(mutex); ABTI_CHECK_NULL_MUTEX_PTR(p_mutex); double tar_time = convert_timespec_to_sec(abstime); ABTI_unit *p_unit; volatile int ext_signal = 0; p_unit = (ABTI_unit *)ABTU_calloc(1, sizeof(ABTI_unit)); p_unit->pool = (ABT_pool)&ext_signal; p_unit->type = ABT_UNIT_TYPE_EXT; ABTI_mutex_spinlock(&p_cond->mutex); if (p_cond->p_waiter_mutex == NULL) { p_cond->p_waiter_mutex = p_mutex; } else { ABT_bool result = ABTI_mutex_equal(p_cond->p_waiter_mutex, p_mutex); if (result == ABT_FALSE) { ABTI_mutex_unlock(&p_cond->mutex); abt_errno = ABT_ERR_INV_MUTEX; goto fn_fail; } } if (p_cond->num_waiters == 0) { p_unit->p_prev = p_unit; p_unit->p_next = p_unit; p_cond->p_head = p_unit; p_cond->p_tail = p_unit; } else { p_cond->p_tail->p_next = p_unit; p_cond->p_head->p_prev = p_unit; p_unit->p_prev = p_cond->p_tail; p_unit->p_next = p_cond->p_head; p_cond->p_tail = p_unit; } p_cond->num_waiters++; ABTI_mutex_unlock(&p_cond->mutex); /* Unlock the mutex that the calling ULT is holding */ ABTI_mutex_unlock(p_mutex); while (!ext_signal) { double cur_time = get_cur_time(); if (cur_time >= tar_time) { remove_unit(p_cond, p_unit); abt_errno = ABT_ERR_COND_TIMEDOUT; break; } ABT_thread_yield(); } ABTU_free(p_unit); /* Lock the mutex again */ ABTI_mutex_spinlock(p_mutex); fn_exit: return abt_errno; fn_fail: HANDLE_ERROR_FUNC_WITH_CODE(abt_errno); goto fn_exit; }
int main(int argc, char *argv[]) { int i, j; int ret, expected; int num_xstreams = DEFAULT_NUM_XSTREAMS; int num_threads = DEFAULT_NUM_THREADS; if (argc > 1) num_xstreams = atoi(argv[1]); assert(num_xstreams >= 0); if (argc > 2) num_threads = atoi(argv[2]); assert(num_threads >= 0); ABT_mutex mutex; ABT_xstream *xstreams; thread_arg_t **args; xstreams = (ABT_xstream *)malloc(sizeof(ABT_xstream) * num_xstreams); assert(xstreams != NULL); args = (thread_arg_t **)malloc(sizeof(thread_arg_t *) * num_xstreams); assert(args != NULL); for (i = 0; i < num_xstreams; i++) { args[i] = (thread_arg_t *)malloc(sizeof(thread_arg_t) * num_threads); } /* Initialize */ ABT_test_init(argc, argv); /* Create Execution Streams */ ret = ABT_xstream_self(&xstreams[0]); ABT_TEST_ERROR(ret, "ABT_xstream_self"); for (i = 1; i < num_xstreams; i++) { ret = ABT_xstream_create(ABT_SCHED_NULL, &xstreams[i]); ABT_TEST_ERROR(ret, "ABT_xstream_create"); } /* Get the pools attached to an execution stream */ ABT_pool *pools; pools = (ABT_pool *)malloc(sizeof(ABT_pool) * num_xstreams); for (i = 0; i < num_xstreams; i++) { ret = ABT_xstream_get_main_pools(xstreams[i], 1, pools+i); ABT_TEST_ERROR(ret, "ABT_xstream_get_main_pools"); } /* Create a mutex */ ret = ABT_mutex_create(&mutex); ABT_TEST_ERROR(ret, "ABT_mutex_create"); /* Create threads */ for (i = 0; i < num_xstreams; i++) { for (j = 0; j < num_threads; j++) { int tid = i * num_threads + j + 1; args[i][j].id = tid; args[i][j].mutex = mutex; ret = ABT_thread_create(pools[i], thread_func, (void *)&args[i][j], ABT_THREAD_ATTR_NULL, NULL); ABT_TEST_ERROR(ret, "ABT_thread_create"); } } /* Switch to other user level threads */ ABT_thread_yield(); /* Join Execution Streams */ for (i = 1; i < num_xstreams; i++) { ret = ABT_xstream_join(xstreams[i]); ABT_TEST_ERROR(ret, "ABT_xstream_join"); } /* Free the mutex */ ret = ABT_mutex_free(&mutex); ABT_TEST_ERROR(ret, "ABT_mutex_free"); /* Free Execution Streams */ for (i = 1; i < num_xstreams; i++) { ret = ABT_xstream_free(&xstreams[i]); ABT_TEST_ERROR(ret, "ABT_xstream_free"); } /* Validation */ expected = num_xstreams * num_threads; if (g_counter != expected) { printf("g_counter = %d\n", g_counter); } /* Finalize */ ret = ABT_test_finalize(g_counter != expected); for (i = 0; i < num_xstreams; i++) { free(args[i]); } free(args); free(xstreams); free(pools); return ret; }
int main(int argc, char *argv[]) { int i, j, ret; int num_xstreams = DEFAULT_NUM_XSTREAMS; int num_threads = DEFAULT_NUM_THREADS; int num_tasks = DEFAULT_NUM_TASKS; if (argc > 1) num_xstreams = atoi(argv[1]); assert(num_xstreams >= 0); if (argc > 2) num_threads = atoi(argv[2]); assert(num_threads >= 0); if (argc > 3) num_tasks = atoi(argv[3]); assert(num_tasks >= 0); ABT_xstream *xstreams; ABT_thread **threads; thread_arg_t **thread_args; ABT_task *tasks; task_arg_t *task_args; xstreams = (ABT_xstream *)malloc(sizeof(ABT_xstream) * num_xstreams); threads = (ABT_thread **)malloc(sizeof(ABT_thread *) * num_xstreams); thread_args = (thread_arg_t **)malloc(sizeof(thread_arg_t*) * num_xstreams); for (i = 0; i < num_xstreams; i++) { threads[i] = (ABT_thread *)malloc(sizeof(ABT_thread) * num_threads); for (j = 0; j < num_threads; j++) { threads[i][j] = ABT_THREAD_NULL; } thread_args[i] = (thread_arg_t *)malloc(sizeof(thread_arg_t) * num_threads); } tasks = (ABT_task *)malloc(sizeof(ABT_task) * num_tasks); task_args = (task_arg_t *)malloc(sizeof(task_arg_t) * num_tasks); /* Initialize */ ABT_test_init(argc, argv); /* Create Execution Streams */ ret = ABT_xstream_self(&xstreams[0]); ABT_TEST_ERROR(ret, "ABT_xstream_self"); for (i = 1; i < num_xstreams; i++) { ret = ABT_xstream_create(ABT_SCHED_NULL, &xstreams[i]); ABT_TEST_ERROR(ret, "ABT_xstream_create"); } /* Get the pools attached to an execution stream */ ABT_pool *pools; pools = (ABT_pool *)malloc(sizeof(ABT_pool) * num_xstreams); for (i = 0; i < num_xstreams; i++) { ret = ABT_xstream_get_main_pools(xstreams[i], 1, pools+i); ABT_TEST_ERROR(ret, "ABT_xstream_get_main_pools"); } /* Create threads */ for (i = 0; i < num_xstreams; i++) { for (j = 0; j < num_threads; j++) { int tid = i * num_threads + j + 1; thread_args[i][j].id = tid; thread_args[i][j].num_threads = num_threads; thread_args[i][j].threads = &threads[i][0]; ret = ABT_thread_create(pools[i], thread_func, (void *)&thread_args[i][j], ABT_THREAD_ATTR_NULL, &threads[i][j]); ABT_TEST_ERROR(ret, "ABT_thread_create"); } } /* Create tasks with task_func1 */ for (i = 0; i < num_tasks; i++) { size_t num = 100 + i; ret = ABT_task_create(pools[i % num_xstreams], task_func1, (void *)num, NULL); ABT_TEST_ERROR(ret, "ABT_task_create"); } /* Create tasks with task_func2 */ for (i = 0; i < num_tasks; i++) { task_args[i].num = 100 + i; ret = ABT_task_create(pools[i % num_xstreams], task_func2, (void *)&task_args[i], &tasks[i]); ABT_TEST_ERROR(ret, "ABT_task_create"); } /* Switch to other work units */ ABT_thread_yield(); /* Results of task_funcs2 */ for (i = 0; i < num_tasks; i++) { ABT_task_state state; do { ABT_task_get_state(tasks[i], &state); ABT_thread_yield(); } while (state != ABT_TASK_STATE_TERMINATED); ABT_test_printf(1, "task_func2: num=%lu result=%llu\n", task_args[i].num, task_args[i].result); /* Free named tasks */ ret = ABT_task_free(&tasks[i]); ABT_TEST_ERROR(ret, "ABT_task_free"); } /* Join Execution Streams */ for (i = 1; i < num_xstreams; i++) { ret = ABT_xstream_join(xstreams[i]); ABT_TEST_ERROR(ret, "ABT_xstream_join"); } /* Free Execution Streams */ for (i = 0; i < num_xstreams; i++) { for (j = 0; j < num_threads; j++) { ret = ABT_thread_free(&threads[i][j]); ABT_TEST_ERROR(ret, "ABT_thread_free"); } if (i == 0) continue; ret = ABT_xstream_free(&xstreams[i]); ABT_TEST_ERROR(ret, "ABT_xstream_free"); } /* Finalize */ ret = ABT_test_finalize(0); for (i = 0; i < num_xstreams; i++) { free(thread_args[i]); free(threads[i]); } free(thread_args); free(threads); free(task_args); free(tasks); free(pools); free(xstreams); return ret; }
int main(int argc, char *argv[]) { int i, j; int ntasks; int start, end; int num_xstreams; ABT_xstream *xstreams; vector_scal_task_args_t *args; struct timeval t_start, t_end, t_end2; char *str, *endptr; float *a; num_xstreams = argc > 1 ? atoi(argv[1]) : NUM_XSTREAMS; if (argc > 2) { str = argv[2]; } ntasks = argc > 2 ? strtoll(str, &endptr, 10) : NUM_TASKS; if (ntasks < num_xstreams) { ntasks = num_xstreams; } printf("# of ESs: %d\n", num_xstreams); xstreams = (ABT_xstream *)malloc(sizeof(ABT_xstream) * num_xstreams); args = (vector_scal_task_args_t *)malloc(sizeof(vector_scal_task_args_t) * num_xstreams); g_pools = (ABT_pool *)malloc(sizeof(ABT_pool) * num_xstreams); a = malloc(sizeof(float) * ntasks); for (i = 0; i < ntasks; i++) { a[i] = i + 100.0f; } /* initialization */ ABT_init(argc, argv); for (i = 0; i < num_xstreams; i++) { ABT_pool_create_basic(ABT_POOL_FIFO, ABT_POOL_ACCESS_MPMC, ABT_TRUE, &g_pools[i]); } /* ES creation */ ABT_xstream_self(&xstreams[0]); ABT_xstream_set_main_sched_basic(xstreams[0], ABT_SCHED_DEFAULT, 1, &g_pools[0]); for (i = 1; i < num_xstreams; i++) { ABT_xstream_create_basic(ABT_SCHED_DEFAULT, 1, &g_pools[i], ABT_SCHED_CONFIG_NULL, &xstreams[i]); ABT_xstream_start(xstreams[i]); } /* Work here */ start = end = 0; int bloc = ntasks / num_xstreams; int rest = ntasks % num_xstreams; gettimeofday(&t_start, NULL); for (j = 0; j < num_xstreams; j++) { start = end; end = start + bloc; if (j < rest) { end++; } args[j].ptr = a; args[j].value = 0.9f; args[j].start = start; args[j].end = end; args[j].id = j; ABT_thread_create_on_xstream(xstreams[j], task_creator, (void *)&args[j], ABT_THREAD_ATTR_NULL, NULL); } gettimeofday(&t_end2, NULL); for (i = 0; i < num_xstreams; i++) { size_t size; do { ABT_thread_yield(); ABT_pool_get_size(g_pools[i], &size); } while (size != 0); } gettimeofday(&t_end, NULL); for (i = 0; i < ntasks; i++) { if (a[i] != (i + 100.0f) * 0.9f) { printf("error: a[%d]\n", i); } } double time = (t_end.tv_sec * 1000000 + t_end.tv_usec) - (t_start.tv_sec * 1000000 + t_start.tv_usec); double time2 = (t_end2.tv_sec * 1000000 + t_end2.tv_usec) - (t_start.tv_sec * 1000000 + t_start.tv_usec); printf("nxstreams: %d\nntasks %d\nTime(s): %f\n", num_xstreams, ntasks, time / 1000000.0); /* join ESs */ for (i = 1; i < num_xstreams; i++) { ABT_xstream_join(xstreams[i]); ABT_xstream_free(&xstreams[i]); } printf("Creation time=%f\n", time2 / 1000000.0); ABT_finalize(); free(xstreams); return EXIT_SUCCESS; }