// Sync variables void chpl_sync_lock(chpl_sync_aux_t *s) { aligned_t l; chpl_bool uncontested_lock = true; PROFILE_INCR(profile_sync_lock, 1); // // To prevent starvation due to never switching away from a task that is // spinning while doing readXX() on a sync variable, yield if this sync var // has a "lot" of uncontested locks. Note that the uncontested locks do not // have to be consecutive. Also note that the number of uncontested locks // is a lossy counter. Currently a "lot" is defined as ~100 uncontested // locks, with care taken to not yield on the first uncontested lock. // // If real qthreads sync vars were used, it's possible this wouldn't be // needed. // l = qthread_incr(&s->lockers_in, 1); while (l != s->lockers_out) { uncontested_lock = false; qthread_yield(); } if (uncontested_lock) { if ((++s->uncontested_locks & 0x5F) == 0) { qthread_yield(); } } }
// Test that writeFF waits for empty var to be filled, writes, and leaves full. // Requires that only one worker is running. Basically does: // 1: empty var // 1: fork(writeFF) // 1: yields // 2: starts runnning // 2: hits writeFF, and yields since var is empty // 1: writeEF // 1: hits readFF on forked task and yield // 2: running again, finishes writeFF, task returns // 1: readFF competes, finishes static void testWriteFFWaits(void) { aligned_t ret; concurrent_t=45; qthread_empty(&concurrent_t); assert(qthread_num_workers() == 1); iprintf("1: Forking writeFF wrapper\n"); qthread_fork_to(writeFF_wrapper, NULL, &ret, qthread_shep()); iprintf("1: Forked, now yielding to 2\n"); qthread_yield(); iprintf("1: Back from yield\n"); // verify that writeFF has not completed assert(qthread_feb_status(&concurrent_t) == 0); assert(concurrent_t != 55); iprintf("1: Writing EF\n"); qthread_writeEF_const(&concurrent_t, 35); // wait for writeFF wrapper to complete qthread_readFF(NULL, &ret); // veify that writeFF completed and that FEB is full iprintf("1: concurrent_t=%d\n", concurrent_t); assert(qthread_feb_status(&concurrent_t) == 1); assert(concurrent_t == 55); }
void chpl_task_yield(void) { PROFILE_INCR(profile_task_yield,1); if (qthread_shep() == NO_SHEPHERD) { sched_yield(); } else { qthread_yield(); } }
void test_print_qthread(size_t i) { qtimer_t t = qtimer_create(); qtimer_start(t); do { qthread_yield(); qtimer_stop(t); } while(qtimer_secs(t) < 1); qtimer_destroy(t); //std::cout << i << "\n"; }
void accalt_yield_to(ACCALT_ult ult) { #ifdef ARGOBOTS ABT_thread_yield_to(ult); #endif #ifdef MASSIVETHREADS myth_yield(0); #endif #ifdef QTHREADS qthread_yield(); #endif }
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[]) { aligned_t return_value = 0; int status, ret; CHECK_VERBOSE(); // part of the testing harness; toggles iprintf() output NUMARG(THREADS_ENQUEUED, "THREADS_ENQUEUED"); status = qthread_initialize(); assert(status == QTHREAD_SUCCESS); iprintf("%i shepherds...\n", qthread_num_shepherds()); iprintf(" %i threads total\n", qthread_num_workers()); iprintf("Creating the queue...\n"); the_queue = qthread_queue_create(QTHREAD_QUEUE_MULTI_JOIN_LENGTH, 0); assert(the_queue); iprintf("---------------------------------------------------------\n"); iprintf("\tSINGLE THREAD TEST\n\n"); iprintf("1/4 Spawning thread to be queued...\n"); status = qthread_fork(tobequeued, NULL, &return_value); assert(status == QTHREAD_SUCCESS); iprintf("2/4 Waiting for thread to queue itself...\n"); while(qthread_queue_length(the_queue) != 1) qthread_yield(); assert(qthread_readstate(NODE_BUSYNESS) == 1); iprintf("3/4 Releasing the queue...\n"); qthread_queue_release_all(the_queue); ret = qthread_readFF(NULL, &return_value); assert(ret == QTHREAD_SUCCESS); assert(threads_in == 1); assert(awoke == 1); assert(qthread_queue_length(the_queue) == 0); assert(qthread_readstate(NODE_BUSYNESS) == 1); iprintf("4/4 Test passed!\n"); iprintf("---------------------------------------------------------\n"); iprintf("\tMULTI THREAD TEST\n\n"); threads_in = 0; awoke = 0; aligned_t *retvals = malloc(sizeof(aligned_t) * THREADS_ENQUEUED); iprintf("1/6 Spawning %u threads to be queued...\n", THREADS_ENQUEUED); for (int i=0; i<THREADS_ENQUEUED; i++) { status = qthread_fork(tobequeued, NULL, retvals + i); assert(status == QTHREAD_SUCCESS); } iprintf("2/6 Waiting for %u threads to queue themselves...\n", THREADS_ENQUEUED); while(qthread_queue_length(the_queue) != THREADS_ENQUEUED) qthread_yield(); assert(threads_in == THREADS_ENQUEUED); assert(qthread_readstate(NODE_BUSYNESS) == 1); iprintf("3/6 Releasing a single thread...\n"); qthread_queue_release_one(the_queue); iprintf("4/6 Waiting for that thread to exit\n"); while (awoke == 0) qthread_yield(); assert(qthread_queue_length(the_queue) == (THREADS_ENQUEUED - 1)); assert(qthread_readstate(NODE_BUSYNESS) == 1); iprintf("5/6 Releasing the rest of the threads...\n"); qthread_queue_release_all(the_queue); for (int i=0; i<THREADS_ENQUEUED; i++) { ret = qthread_readFF(NULL, retvals + i); assert(ret == QTHREAD_SUCCESS); } assert(qthread_queue_length(the_queue) == 0); assert(qthread_readstate(NODE_BUSYNESS) == 1); iprintf("6/6 Test passed!\n"); return EXIT_SUCCESS; }
void chpl_task_yield(void) { PROFILE_INCR(profile_task_yield,1); qthread_yield(); }
void wait( Kokkos::Experimental::TaskPolicy< Kokkos::Qthread > & policy ) { volatile int * const active_task_count = & policy.m_active_count ; while ( *active_task_count ) qthread_yield(); }