int main(int argc, char *argv[]) { size_t threads = 1000, i; aligned_t *rets; qtimer_t t; unsigned int iter, iterations = 10; assert(qthread_initialize() == 0); t = qtimer_create(); CHECK_VERBOSE(); NUMARG(threads, "THREADS"); NUMARG(iterations, "ITERATIONS"); initme = (aligned_t *)calloc(threads, sizeof(aligned_t)); assert(initme); rets = (aligned_t *)malloc(iterations * threads * sizeof(aligned_t)); assert(rets); iprintf("creating the barrier for %zu threads\n", threads + 1); wait_on_me = qt_feb_barrier_create(threads + 1); // all my spawnees plus me assert(wait_on_me); for (iter = 0; iter < iterations; iter++) { iprintf("%i: forking the threads\n", iter); for (i = 0; i < threads; i++) { qthread_fork(barrier_thread, wait_on_me, rets + (iter * threads) + i); } iprintf("%i: done forking the threads, entering the barrier\n", iter); qtimer_start(t); qt_feb_barrier_enter(wait_on_me); qtimer_stop(t); iprintf("%i: main thread exited barrier in %f seconds\n", iter, qtimer_secs(t)); initme_idx = 0; for (i = 0; i < threads; i++) { if (initme[i] != iter + 1) { iprintf("initme[%i] = %i (should be %i)\n", (int)i, (int)initme[i], iter + 1); } assert(initme[i] == iter + 1); } } iprintf("Destroying barrier...\n"); qt_feb_barrier_destroy(wait_on_me); iprintf("Success!\n"); /* this loop shouldn't be necessary... but seems to avoid crashes in rare * cases (in other words there must a race condition in qthread_finalize() * if there are outstanding threads out there) */ for (i = 0; i < threads * 2; i++) { aligned_t tmp = 1; qthread_readFF(&tmp, rets + i); assert(tmp == 0); } return 0; }
// ////////////////////////////////////////////////////////////////////////////// int main(int argc, char *argv[]) { size_t depth = 3; assert(qthread_initialize() == 0); CHECK_VERBOSE(); NUMARG(depth, "TEST_DEPTH"); // Test creating an empty sinc { qt_sinc_t zero_sinc; qt_sinc_init(&zero_sinc, 0, NULL, NULL, 0); qt_sinc_wait(&zero_sinc, NULL); qt_sinc_fini(&zero_sinc); qt_sinc_t *three_sinc = qt_sinc_create(0, NULL, NULL, 0); qt_sinc_expect(three_sinc, 3); qthread_fork(submit_to_sinc, three_sinc, NULL); qthread_fork(submit_to_sinc, three_sinc, NULL); qthread_fork(submit_to_sinc, three_sinc, NULL); qt_sinc_wait(three_sinc, NULL); qt_sinc_destroy(three_sinc); } qt_sinc_t *sinc = qt_sinc_create(0, NULL, NULL, 2); // Spawn additional waits aligned_t rets[3]; { qthread_fork(wait_on_sinc, sinc, &rets[0]); qthread_fork(wait_on_sinc, sinc, &rets[1]); qthread_fork(wait_on_sinc, sinc, &rets[2]); } { v_args_t args = { depth, sinc }; // These two spawns covered by qt_sinc_create(...,2) qthread_fork_syncvar_copyargs(visit, &args, sizeof(v_args_t), NULL); qthread_fork_syncvar_copyargs(visit, &args, sizeof(v_args_t), NULL); } qt_sinc_wait(sinc, NULL); for (int i = 0; i < 3; i++) qthread_readFF(NULL, &rets[i]); // Reset the sinc qt_sinc_reset(sinc, 2); // Second use { v_args_t args = { depth, sinc }; // These two spawns covered by qt_sinc_reset(...,2) qthread_fork_syncvar_copyargs(visit, &args, sizeof(v_args_t), NULL); qthread_fork_syncvar_copyargs(visit, &args, sizeof(v_args_t), NULL); } qt_sinc_wait(sinc, NULL); qt_sinc_destroy(sinc); return 0; }
void API_FUNC qutil_mergesort(double *array, size_t length) { /*{{{*/ /* first, decide how much of the array each thread gets */ size_t chunksize = MT_LOOP_CHUNK; /* second, decide how many threads to use... */ size_t numthreads; aligned_t *rets; size_t i; struct qutil_mergesort_args *args; assert(qthread_library_initialized); chunksize = 10; /* third, an initial qsort() */ numthreads = length / chunksize; if (length - (numthreads * chunksize)) { numthreads++; } rets = MALLOC(sizeof(aligned_t) * numthreads); args = MALLOC(sizeof(struct qutil_mergesort_args) * numthreads); for (i = 0; i < numthreads; i++) { args[i].array = array; args[i].first_start = i * chunksize; args[i].first_stop = (i + 1) * chunksize - 1; if (args[i].first_stop >= length) { args[i].first_stop = length - 1; } qthread_fork((qthread_f)qutil_mergesort_presort, args + i, rets + i); } for (i = 0; i < numthreads; i++) { qthread_readFF(NULL, rets + i); } FREE(rets, sizeof(aligned_t) * numthreads); FREE(args, sizeof(struct qutil_mergesort_args) * numthreads); /* prepare scratch memory */ if (chunksize <= length) { numthreads = (length - chunksize) / (2 * chunksize); if ((length - chunksize) - (2 * chunksize * numthreads)) { numthreads++; } rets = MALLOC(sizeof(aligned_t) * numthreads); assert(rets); args = MALLOC(sizeof(struct qutil_mergesort_args) * numthreads); assert(args); numthreads = 0; } /* now, commence with the merging */ while (chunksize <= length) { i = 0; numthreads = 0; while (i < length - chunksize) { args[numthreads].array = array; args[numthreads].first_start = i; args[numthreads].first_stop = i + chunksize - 1; args[numthreads].second_start = i + chunksize; args[numthreads].second_stop = ((i + 2 * chunksize - 1) < (length - 1)) ? (i + 2 * chunksize - 1) : (length - 1); qthread_fork((qthread_f)qutil_mergesort_inner, args + numthreads, rets + numthreads); i += 2 * chunksize; numthreads++; } for (i = 0; i < numthreads; i++) { qthread_readFF(NULL, rets + i); } chunksize *= 2; } if (rets) { FREE(rets, sizeof(aligned_t) * numthreads); FREE(args, sizeof(struct qutil_mergesort_args) * numthreads); } } /*}}}*/