//-------------------------------------------------------------------------------------- // FUNCTION: RCCE_barrier //-------------------------------------------------------------------------------------- // very simple, linear barrier //-------------------------------------------------------------------------------------- int RCCE_barrier(RCCE_COMM *comm) { int counter, i, error; int ROOT = 0; t_vchar cyclechar[RCCE_LINE_SIZE]; t_vchar valchar [RCCE_LINE_SIZE]; t_vcharp gatherp, releasep; RCCE_FLAG_STATUS cycle; counter = 0; gatherp = comm->gather.line_address; if (RCCE_debug_synch) fprintf(STDERR,"UE %d has checked into barrier\n", RCCE_IAM); // flip local barrier variable if (error = RCCE_get(cyclechar, gatherp, RCCE_LINE_SIZE, RCCE_IAM)) return(RCCE_error_return(RCCE_debug_synch,error)); cycle = RCCE_flip_bit_value(cyclechar, comm->gather.location); if (error = RCCE_put(comm->gather.line_address, cyclechar, RCCE_LINE_SIZE, RCCE_IAM)) return(RCCE_error_return(RCCE_debug_synch,error)); if (RCCE_IAM==comm->member[ROOT]) { // read "remote" gather flags; once all equal "cycle" (i.e counter==comm->size), // we know all UEs have reached the barrier while (counter != comm->size) { // skip the first member (#0), because that is the ROOT for (counter=i=1; i<comm->size; i++) { // copy flag values out of comm buffer if (error = RCCE_get(valchar, comm->gather.line_address, RCCE_LINE_SIZE, comm->member[i])) return(RCCE_error_return(RCCE_debug_synch,error)); if (RCCE_bit_value(valchar, comm->gather.location) == cycle) counter++; } } // set release flags for (i=1; i<comm->size; i++) if (error = RCCE_flag_write(&(comm->release), cycle, comm->member[i])) return(RCCE_error_return(RCCE_debug_synch,error)); } else { if (error = RCCE_wait_until(comm->release, cycle)) return(RCCE_error_return(RCCE_debug_synch,error)); } if (RCCE_debug_synch) fprintf(STDERR,"UE %d has cleared barrier\n", RCCE_IAM); return(RCCE_SUCCESS); }
//-------------------------------------------------------------------------------------- // FUNCTION: RCCE_flag_free //-------------------------------------------------------------------------------------- // free space for one flag. Since multiple fit on a single cache line, we only // need to free claimed MPB space when the all existing lines are completely emptied. //-------------------------------------------------------------------------------------- int RCCE_flag_free(RCCE_FLAG *flag) { RCCE_FLAG_LINE *flagp, *flagpminus1 = NULL; int loc; // check wether flag exists, and whether the location field is valid if (!flag || flag->location < 0) return(RCCE_error_return(RCCE_debug_synch,RCCE_ERROR_FLAG_UNDEFINED)); // find flag line in globally maintained structure flagp = &RCCE_flags; while (flagp->next && flag->line_address != flagp->line_address) { flagpminus1 = flagp; flagp = flagp->next; } if (flag->line_address != flagp->line_address) return(RCCE_error_return(RCCE_debug_synch,RCCE_ERROR_FLAG_UNDEFINED)); // error checking is done flagp->members--; loc = flag->location; #ifdef SINGLEBITFLAGS RCCE_flip_bit_value(flagp->flag+loc/RCCE_FLAGS_PER_BYTE,loc%RCCE_FLAGS_PER_BYTE); #else flagp->flag[flag->location] = (char) ((unsigned int) 0); #endif // something special happens if we've emptied an entire line if (flagp->members==0) { if (flagpminus1) { // there is a predecessor; splice out current flag line from linked list RCCE_free(flagp->line_address); flagpminus1->next = flagp->next; free(flagp); } // if there is a successor but no predecessor, do nothing } // invalidate location field to make sure we won't free again by mistake flag->location = -1; flag->line_address = NULL; return(RCCE_SUCCESS); }