snet_handle_t *SNetOutRawArray( snet_handle_t *hnd, int if_id, snet_variant_t *variant, void **fields, int *tags, int *btags) { int i, name; snet_record_t *out_rec, *old_rec; #ifdef DBG_RT_TRACE_OUT_TIMINGS struct timeval tv_in; struct timeval tv_out; gettimeofday( &tv_in, NULL); SNetUtilDebugNoticeEnt( hnd->ent, "[BOX] SNetOut called at %lf.", tv_in.tv_sec + tv_in.tv_usec / 1000000.0 ); #endif // set values from box out_rec = SNetRecCreate( REC_data); SNetRecSetInterfaceId( out_rec, if_id); i = 0; VARIANT_FOR_EACH_FIELD(variant, name) { SNetRecSetField( out_rec, name, SNetRefCreate(fields[i], if_id)); i++; }
/** * Process a sort record */ static void ProcessSortRecord( snet_entity_t *ent, snet_record_t *rec, snet_record_t **sort_rec, snet_stream_desc_t *cur_stream, snet_streamset_t *readyset, snet_streamset_t *waitingset) { int res; assert( REC_sort_end == SNetRecGetDescriptor( rec) ); /* sort record: place node in waitingset */ /* remove node */ res = SNetStreamsetRemove( readyset, cur_stream); assert(res == 0); /* put in waiting set */ SNetStreamsetPut( waitingset, cur_stream); if (*sort_rec!=NULL) { /* * check that level & counter match */ if( !SortRecEqual(rec, *sort_rec) ) { SNetUtilDebugNoticeEnt( ent, "[COLL] Warning: Received sort records do not match! " "expected (l%d,c%d) got (l%d,c%d) on %p", /* *trollface* PROBLEM? */ SNetRecGetLevel(*sort_rec), SNetRecGetNum(*sort_rec), SNetRecGetLevel(rec), SNetRecGetNum(rec), cur_stream ); } /* destroy record */ SNetRecDestroy( rec); } else { *sort_rec = rec; } }
/** * Star component task */ static void StarBoxTask(void *arg) { star_arg_t *sarg = arg; snet_record_t *rec; /* read from input stream */ rec = SNetStreamRead( sarg->instream); switch( SNetRecGetDescriptor( rec)) { case REC_data: if( MatchesExitPattern( rec, sarg->exit_patterns, sarg->guards)) { assert(!sarg->sync_cleanup); #ifdef DEBUG_PRINT_GC SNetUtilDebugNoticeEnt( ent, "[STAR] Notice: Data leaves replication network."); #endif /* send rec to collector */ SNetStreamWrite( sarg->outstream, rec); } else { /* if instance has not been created yet, create it */ if( sarg->nextstream == NULL) { CreateOperandNetwork(&sarg->nextstream, sarg, sarg->outstream); } /* send the record to the instance */ SNetStreamWrite( sarg->nextstream, rec); } /* end if not matches exit pattern */ /* deterministic non-incarnate has to append control records */ if (sarg->is_det && !sarg->is_incarnate) { /* send new sort record to collector level=0, counter=0*/ SNetStreamWrite( sarg->outstream, SNetRecCreate( REC_sort_end, 0, sarg->counter) ); /* if has next instance, send new sort record */ if (sarg->nextstream != NULL) { SNetStreamWrite( sarg->nextstream, SNetRecCreate( REC_sort_end, 0, sarg->counter) ); } /* increment counter */ sarg->counter++; } #ifdef ENABLE_GC else if (sarg->sync_cleanup) { snet_record_t *term_rec; /* * If sync_cleanup is set, we decided to postpone termination * due to garbage collection triggered by a sync record until now. * Postponing was done in order not to create the operand network unnecessarily * only to be able to forward the sync record. */ assert( sarg->nextstream != NULL); /* first send a sync record to the next instance */ SNetStreamWrite( sarg->nextstream, SNetRecCreate( REC_sync, SNetStreamGet(sarg->instream)) ); /* send a terminate record to collector, it will close and destroy the stream */ term_rec = SNetRecCreate(REC_terminate); SNetRecSetFlag(term_rec); SNetStreamWrite( sarg->outstream, term_rec); #ifdef DEBUG_PRINT_GC /* terminating due to GC */ SNetUtilDebugNoticeEnt( ent, "[STAR] Notice: Destroying star dispatcher due to GC, " "delayed until new data record!" ); #endif SNetStreamClose(sarg->nextstream, false); SNetStreamClose(sarg->instream, false); TerminateStarBoxTask(sarg->outstream,sarg); return; } #endif /* ENABLE_GC */ break; case REC_sync: { snet_stream_t *newstream = SNetRecGetStream( rec); #ifdef ENABLE_GC snet_locvec_t *loc = SNetStreamGetSource( newstream); #ifdef DEBUG_PRINT_GC if (loc != NULL) { int size = SNetLocvecPrintSize(loc) + 1; char srecloc[size]; srecloc[size - 1] = '\0'; SNetLocvecPrint(srecloc, loc); SNetUtilDebugNoticeTask( "[STAR] Notice: Received sync record with a stream with source %s.", srecloc ); } #endif /* TODO * It is not necessary to carry the whole location vector in the * next stream of a star-entity, only a flag. As a prerequisite, * non_incarnates must not clean themselves up! */ /* * Only incarnates are eligible for cleanup! * check if the source (location) of the stream and the own location are * (subsequent) star dispatcher entities of the same star combinator network * -> if so, we can clean-up ourselves */ if ( sarg->is_incarnate && loc != NULL ) { assert( true == SNetLocvecEqualParent(loc, SNetLocvecGet(sarg->info)) ); /* If the next instance is already created, we can forward the sync-record * immediately and terminate. * Otherwise we postpone termination to the point when a next data record * is received, as we create the operand network then. */ if (sarg->nextstream != NULL) { snet_record_t *term_rec; /* forward the sync record */ SNetStreamWrite( sarg->nextstream, rec); /* send a terminate record to collector, it will close and destroy the stream */ term_rec = SNetRecCreate(REC_terminate); SNetRecSetFlag(term_rec); SNetStreamWrite( sarg->outstream, term_rec); #ifdef DEBUG_PRINT_GC /* terminating due to GC */ SNetUtilDebugNoticeEnt( ent, "[STAR] Notice: Destroying star dispatcher due to GC, " "immediately on sync!" ); #endif SNetStreamClose(sarg->nextstream, false); SNetStreamClose(sarg->instream, true); TerminateStarBoxTask(sarg->outstream,sarg); return; } else { sarg->sync_cleanup = true; #ifdef DEBUG_PRINT_GC SNetUtilDebugNoticeEnt( ent, "[STAR] Notice: Remembering delayed destruction."); #endif /* handle sync record as usual */ SNetStreamReplace( sarg->instream, newstream); SNetRecDestroy( rec); } } else #endif /* ENABLE_GC */ { /* handle sync record as usual */ SNetStreamReplace( sarg->instream, newstream); SNetRecDestroy( rec); } } break; case REC_sort_end: { int rec_lvl = SNetRecGetLevel(rec); /* send a copy to the box, if exists */ if( sarg->nextstream != NULL) { SNetStreamWrite( sarg->nextstream, SNetRecCreate( REC_sort_end, (!sarg->is_incarnate)? rec_lvl+1 : rec_lvl, SNetRecGetNum(rec) ) ); } /* send the original one to the collector */ if (!sarg->is_incarnate) { /* if non-incarnate, we have to increase level */ SNetRecSetLevel( rec, rec_lvl+1); } SNetStreamWrite( sarg->outstream, rec); } break; case REC_terminate: if( sarg->nextstream != NULL) { SNetStreamWrite( sarg->nextstream, SNetRecCopy( rec)); SNetStreamClose( sarg->nextstream, false); } SNetStreamWrite( sarg->outstream, rec); /* note that no sort record has to be appended */ SNetStreamClose(sarg->instream, true); TerminateStarBoxTask(sarg->outstream,sarg); return; case REC_collect: default: SNetUtilDebugFatal("Unknown record type!"); /* if ignore, at least destroy ... */ SNetRecDestroy( rec); } SNetThreadingRespawn(NULL); }
static void BoxTask(snet_entity_t *ent, void *arg) { #ifdef DBG_RT_TRACE_BOX_TIMINGS static struct timeval tv_in; static struct timeval tv_out; #endif #ifdef SNET_DEBUG_COUNTERS snet_time_t time_in; snet_time_t time_out; long mseconds; #endif /* SNET_DEBUG_COUNTERS */ box_arg_t *barg = (box_arg_t *)arg; snet_record_t *rec; snet_stream_desc_t *instream, *outstream; bool terminate = false; instream = SNetStreamOpen(barg->input, 'r'); outstream = SNetStreamOpen(barg->output, 'w'); /* set out descriptor */ barg->hnd.out_sd = outstream; /* set entity */ barg->hnd.ent = ent; /* MAIN LOOP */ while(!terminate) { /* read from input stream */ rec = SNetStreamRead(instream); switch(SNetRecGetDescriptor(rec)) { case REC_trigger_initialiser: case REC_data: barg->hnd.rec = rec; #ifdef DBG_RT_TRACE_BOX_TIMINGS gettimeofday(&tv_in, NULL); SNetUtilDebugNoticeEnt(ent, "[BOX] Firing box function at %lf.", tv_in.tv_sec + tv_in.tv_usec / 1000000.0 ); #endif #ifdef SNET_DEBUG_COUNTERS SNetDebugTimeGetTime(&time_in); #endif /* SNET_DEBUG_COUNTERS */ #ifdef USE_USER_EVENT_LOGGING /* Emit a monitoring message of a record read to be processed by a box */ if (SNetRecGetDescriptor(rec) == REC_data) { SNetThreadingEventSignal(ent, SNetMonInfoCreate(EV_MESSAGE_IN, MON_RECORD, rec) ); } #endif /* execute box function and update execution realm */ barg->hnd = *barg->boxfun(&barg->hnd); barg->hnd = *barg->exerealm_update(&barg->hnd); /* * Emit an event here? * SNetMonInfoEvent(EV_BOX_???, MON_RECORD, rec); */ #ifdef DBG_RT_TRACE_BOX_TIMINGS gettimeofday(&tv_out, NULL); SNetUtilDebugNoticeEnt(ent, "[BOX] Return from box function after %lf sec.", (tv_out.tv_sec - tv_in.tv_sec) + (tv_out.tv_usec - tv_in.tv_usec) / 1000000.0 ); #endif #ifdef SNET_DEBUG_COUNTERS SNetDebugTimeGetTime(&time_out); mseconds = SNetDebugTimeDifferenceInMilliseconds(&time_in, &time_out); SNetDebugCountersIncreaseCounter(mseconds, SNET_COUNTER_TIME_BOX); #endif /* SNET_DEBUG_COUNTERS */ SNetRecDestroy(rec); /* restrict to one data record per execution */ //SNetThreadingYield(); /* check the box task should be migrated after one record execution */ SNetThreadingCheckMigrate(); break; case REC_sync: { snet_stream_t *newstream = SNetRecGetStream(rec); SNetStreamReplace(instream, newstream); SNetRecDestroy(rec); } break; case REC_sort_end: /* forward the sort record */ SNetStreamWrite(outstream, rec); break; case REC_terminate: barg->hnd = *barg->exerealm_destroy(&barg->hnd); SNetStreamWrite(outstream, rec); terminate = true; break; case REC_collect: default: assert(0); } } /* MAIN LOOP END */ barg->hnd = *barg->exerealm_destroy(&barg->hnd); SNetStreamClose(instream, true); SNetStreamClose(outstream, false); /* destroy box arg */ SNetVariantListDestroy(barg->hnd.vars); SNetIntListListDestroy(barg->hnd.sign); SNetMemFree( barg); }
/** * Collector task for dynamic combinators (star/split) * and the static parallel combinator */ void CollectorTask(snet_entity_t *ent, void *arg) { coll_arg_t *carg = (coll_arg_t *)arg; snet_streamset_t readyset, waitingset; snet_stream_iter_t *wait_iter; snet_stream_desc_t *outstream; snet_stream_desc_t *curstream = NULL; snet_stream_desc_t *last = NULL; // when the paired parallel terminate, it sends the sort_end record to the last branch snet_record_t *sort_rec = NULL; snet_record_t *term_rec = NULL; int incount; bool terminate = false; /* open outstream for writing */ outstream = SNetStreamOpen(carg->output, 'w'); readyset = waitingset = NULL; if (carg->is_static) { int i; incount = CARG_ST(carg, num); /* fill initial readyset of collector */ for (i=0; i<incount; i++) { snet_stream_desc_t *tmp; /* open each stream in listening set for reading */ tmp = SNetStreamOpen( CARG_ST(carg, inputs[i]), 'r'); /* add each stream instreams[i] to listening set of collector */ SNetStreamsetPut( &readyset, tmp); } SNetMemFree( CARG_ST(carg, inputs) ); } else { incount = 1; /* Open initial stream and put into readyset */ SNetStreamsetPut( &readyset, SNetStreamOpen(CARG_DYN(carg, input), 'r') ); } /* create an iterator for waiting set, is reused within main loop*/ wait_iter = SNetStreamIterCreate( &waitingset); /* MAIN LOOP */ while( !terminate) { /* get a record */ snet_record_t *rec = GetRecord(&readyset, incount, &curstream); /* process the record */ switch( SNetRecGetDescriptor( rec)) { case REC_data: /* data record: forward to output */ SNetStreamWrite( outstream, rec); break; case REC_sort_end: /* curstream == last, this is the last branch and the paired parallel already terminates * increase the level by one because it was not increased by the paired parallel as it should be * Also later when last becomes the only waiting branch, the collector should terminate. However before terminating, it should pretend that parallel has sent the sort end from all branches */ if (curstream == last) { // imply last != NULL, this will be the last branch and the paired parallel already terminates SNetRecSetLevel(rec, SNetRecGetLevel(rec) + 1); // increase the level by one because it was not increased by the paired parallel as it should be } if (last == NULL && SNetRecGetLevel(rec) == 0 && SNetRecGetNum(rec) == -1) { // if last was not set, and collector receives a sort_end (l0, c-1) --> set the curstream as last last = curstream; // from now on, any sort_end from last will be increased level by 1 SNetRecDestroy( rec); break; // ignore the sort_end } ProcessSortRecord(ent, rec, &sort_rec, curstream, &readyset, &waitingset); /* end processing this stream */ curstream = NULL; break; case REC_sync: SNetStreamReplace( curstream, SNetRecGetStream( rec)); SNetRecDestroy( rec); break; case REC_collect: /* only for dynamic collectors! */ assert( false == carg->is_static ); /* collect: add new stream to ready set */ #ifdef DESTROY_TERM_IN_WAITING_UPON_COLLECT /* but first, check if we can free resources by checking the waiting set for arrival of termination records */ incount -= DestroyTermInWaitingSet(wait_iter, &waitingset); assert(incount > 0); #endif /* finally, add new stream to ready set */ SNetStreamsetPut( &readyset, SNetStreamOpen( SNetRecGetStream( rec), 'r') ); /* update incoming counter */ incount++; /* destroy collect record */ SNetRecDestroy( rec); break; case REC_terminate: /* termination record: close stream and remove from ready set */ ProcessTermRecord(rec, &term_rec, curstream, &readyset, &incount); /* stop processing this stream */ curstream = NULL; break; default: assert(0); /* if ignore, at least destroy ... */ SNetRecDestroy( rec); } /* end switch */ /************* termination conditions *****************/ if ( SNetStreamsetIsEmpty( &readyset)) { /* the streams which had a sort record are in the waitingset */ if ( !SNetStreamsetIsEmpty( &waitingset)) { if ( carg->is_static && (1 == incount) ) { // stat snet_stream_desc_t *in = (waitingset != NULL) ? waitingset : readyset; /* if last is the only one in the waitingset --> pretends that the already-terminated paired parallel has sent the sort end to all branches * Therefore restore the waitingset before terminating (so that a relevant sort_end is sent out) */ if (in == last) RestoreFromWaitingset(&waitingset, &readyset, &sort_rec, outstream); SNetStreamWrite( outstream, SNetRecCreate( REC_sync, SNetStreamGet(in)) ); SNetStreamClose( in, false); terminate = true; #ifdef DEBUG_PRINT_GC /* terminating due to GC */ SNetUtilDebugNoticeEnt( ent, "[COLL] Terminate static collector as only one branch left!" ); #endif } else RestoreFromWaitingset(&waitingset, &readyset, &sort_rec, outstream); } else { /* both ready set and waitingset are empty */ #ifdef DEBUG_PRINT_GC if (carg->is_static) { SNetUtilDebugNoticeEnt( ent, "[COLL] Terminate static collector as no inputs left!"); } #endif assert(term_rec != NULL); SNetStreamWrite( outstream, term_rec); term_rec = NULL; terminate = true; } } /************* end of termination conditions **********/ } /* MAIN LOOP END */ if (term_rec != NULL) { SNetRecDestroy(term_rec); } if (sort_rec != NULL) { SNetRecDestroy(sort_rec); } /* close outstream */ SNetStreamClose( outstream, false); /* destroy iterator */ SNetStreamIterDestroy( wait_iter); /* destroy argument */ SNetMemFree( carg); } /* END of DYNAMIC COLLECTOR TASK */