/* * the producer loops over the requested number of items, writing them to the * buffer starting at location 0 and wrapping around when it hits the end of * the buffer. It then writes the value -1 as a sentinel to the next position. */ static aligned_t producer(void *arg) { for (unsigned int i = 0; i < numItems; ++i) { const unsigned int buffInd = i % bufferSize; qthread_writeEF_const(&buff[buffInd], i); iprintf("producer wrote value #%u\n", i); } qthread_writeEF_const(&buff[numItems % bufferSize], -1); iprintf("producer wrote terminus value #%"PRIu64"\n", -1); return 0; }
// 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); }
static aligned_t update(void *arg) { stencil_t *points = ((update_args_t *)arg)->points; size_t i = ((update_args_t *)arg)->i; size_t j = ((update_args_t *)arg)->j; size_t this_stage = ((update_args_t *)arg)->stage; size_t step = ((update_args_t *)arg)->step; size_t next_stage_id = next_stage(this_stage); // Perform local work perform_local_work(); aligned_t **prev = points->stage[prev_stage(this_stage)]; aligned_t sum = *(NORTH(prev, i, j)) + *(WEST(prev, i, j)) + *(HERE(prev, i, j)) + *(EAST(prev, i, j)) + *(SOUTH(prev, i, j)); // Empty the next stage for this index qthread_empty(&points->stage[next_stage_id][i][j]); // Update this point qthread_writeEF_const(&points->stage[this_stage][i][j], sum/NUM_NEIGHBORS); if (step < num_timesteps) { // Spawn next stage update_args_t args = {points, i, j, next_stage_id, step+1}; #ifdef BOUNDARY_SYNC qthread_fork_copyargs_precond(update, &args, sizeof(update_args_t), NULL, NUM_NEIGHBORS, NEIGHBORS(points->stage[this_stage],i,j)); #else if (i == 1) { // North edge if (j == 1) // West edge: EAST & SOUTH qthread_fork_copyargs_precond(update, &args, sizeof(update_args_t), NULL, 2, EAST(points->stage[this_stage],i,j), SOUTH(points->stage[this_stage],i,j)); else if (j == points->M-2) // East edge: WEST & SOUTH qthread_fork_copyargs_precond(update, &args, sizeof(update_args_t), NULL, 2, WEST(points->stage[this_stage],i,j), SOUTH(points->stage[this_stage],i,j)); else // Interior: WEST & EAST & SOUTH qthread_fork_copyargs_precond(update, &args, sizeof(update_args_t), NULL, 3, WEST(points->stage[this_stage],i,j), EAST(points->stage[this_stage],i,j), SOUTH(points->stage[this_stage],i,j)); } else if (i == points->N-2) { // South edge if (j == 1) // West edge: NORTH & EAST qthread_fork_copyargs_precond(update, &args, sizeof(update_args_t), NULL, 2, NORTH(points->stage[this_stage],i,j), EAST(points->stage[this_stage],i,j)); else if (j == points->M-2) // East edge: NORTH & WEST qthread_fork_copyargs_precond(update, &args, sizeof(update_args_t), NULL, 2, NORTH(points->stage[this_stage],i,j), WEST(points->stage[this_stage],i,j)); else // Interior: NORTH & WEST & EAST qthread_fork_copyargs_precond(update, &args, sizeof(update_args_t), NULL, 3, NORTH(points->stage[this_stage],i,j), WEST(points->stage[this_stage],i,j), EAST(points->stage[this_stage],i,j)); } else { // Interior if (j == 1) // West edge: NORTH & EAST & SOUTH qthread_fork_copyargs_precond(update, &args, sizeof(update_args_t), NULL, 3 , NORTH(points->stage[this_stage],i,j), EAST(points->stage[this_stage],i,j), SOUTH(points->stage[this_stage],i,j)); else if (j == points->M-2) // East edge: NORTH & WEST & SOUTH qthread_fork_copyargs_precond(update, &args, sizeof(update_args_t), NULL, 3, NORTH(points->stage[this_stage],i,j), WEST(points->stage[this_stage],i,j), SOUTH(points->stage[this_stage],i,j)); else // Interior: ALL qthread_fork_copyargs_precond(update, &args, sizeof(update_args_t), NULL, 4, NORTH(points->stage[this_stage],i,j), EAST(points->stage[this_stage],i,j), WEST(points->stage[this_stage],i,j), SOUTH(points->stage[this_stage],i,j)); } #endif } else qt_feb_barrier_enter(points->barrier); return 0; }
template < typename T > inline int qthread_writeEF(T *const dest, const T src) { QTHREAD_CHECKSIZE(T); return qthread_writeEF_const((aligned_t *)dest, (aligned_t)src); }
void mt_write(T& target, T2 val) { #ifdef __MTA__ writeef(&target, val); #elif USING_QTHREADS qthread_writeEF_const((aligned_t*) &target, (aligned_t) val); #else target = val; #endif }