/* Read one record from the parser. */ input_state_t SNetGetNextInputRecord(landing_t *land) { landing_input_t *linp = LAND_SPEC(land, input); input_arg_t *iarg = NODE_SPEC(land->node, input); snet_record_t *record = NULL; trace(__func__); assert(NODE_TYPE(land->node) == NODE_input); if (iarg->state == INPUT_reading) { // Ask parser for a new input record. while (SNetInParserGetNextRecord(&record) == SNET_PARSE_CONTINUE) { if (record) { break; } } if (record) { if (REC_DESCR(record) == REC_terminate) { SNetRecDestroy(record); iarg->state = INPUT_terminating; } else { linp->num_inputs += 1; SNetWrite(&linp->outdesc, record, false); return INPUT_reading; } } else { iarg->state = INPUT_terminating; } return iarg->state; } else { return INPUT_terminated; } }
/* Deallocate input node */ void SNetStopInput(node_t *node, fifo_t *fifo) { input_arg_t *iarg = NODE_SPEC(node, input); trace(__func__); iarg->indesc->landing->refs = 0; SNetFreeLanding(iarg->indesc->landing); SNetDelete(iarg->indesc); SNetStopStream(iarg->output, fifo); SNetDelete(node); }
void SNetCloseInput(node_t* node) { input_arg_t *iarg = NODE_SPEC(node, input); landing_input_t *linp = DESC_LAND_SPEC(iarg->indesc, input); trace(__func__); assert(iarg->state == INPUT_terminating); iarg->state = INPUT_terminated; SNetDescDone(linp->outdesc); SNetInParserDestroy(); }
/* DripBack creation function */ snet_stream_t *SNetDripBack( snet_stream_t *input, snet_info_t *info, int location, snet_variant_list_t *back_patterns, snet_expr_list_t *guards, snet_startup_fun_t box_a) { snet_stream_t *output; node_t *node; dripback_arg_t *darg; snet_locvec_t *locvec; int detlevel; trace(__func__); detlevel = SNetDetSwapLevel(0); locvec = SNetLocvecGet(info); SNetLocvecFeedbackEnter(locvec); output = SNetStreamCreate(0); node = SNetNodeNew(NODE_dripback, location, &input, 1, &output, 1, SNetNodeDripBack, SNetStopDripBack, SNetTermDripBack); darg = NODE_SPEC(node, dripback); /* fill in the node argument */ darg->input = input; darg->output = output; darg->back_patterns = back_patterns; darg->guards = guards; darg->stopping = 0; /* Create the instance network */ darg->instance = SNetNodeStreamCreate(node); SNetSubnetIncrLevel(); darg->dripback = (*box_a)(darg->instance, info, location); SNetSubnetDecrLevel(); STREAM_DEST(darg->dripback) = node; SNetNodeTableAdd(darg->dripback); /* Create one self-referencing stream. */ darg->selfref = SNetNodeStreamCreate(node); STREAM_DEST(darg->selfref) = node; SNetNodeTableAdd(darg->selfref); darg->entity = SNetEntityCreate( ENTITY_fbdisp, location, locvec, "<feedback>", NULL, (void*)darg); SNetLocvecFeedbackLeave(locvec); SNetDetSwapLevel(detlevel); return output; }
static bool SNetInputAllowed(worker_t *worker) { bool allowed = true; if (SNetInputThrottle()) { /* Check if output has advanced enough for us to input more. */ size_t outs = NODE_SPEC(worker->output_node, output)->num_outputs; size_t ins = DESC_LAND_SPEC(worker->input_desc, input)->num_inputs; double limit = SNetInputOffset() + SNetInputFactor() * outs; allowed = (ins < limit); } return allowed; }
/* Test if other workers have work to do. */ bool SNetWorkerOthersBusy(worker_t *worker) { int i; bool change = false; if (worker->output_node) { if (NODE_SPEC(worker->output_node, output)->terminated) { return false; } } if (worker->is_idle < 1) { worker->idle_seqnr += 1; worker->is_idle = 1; } for (i = 1; i <= snet_worker_count; ++i) { worker_t *other = snet_workers[i]; if (!other) { worker->is_idle = 1; change = true; break; } else if (other != worker) { if (other->is_idle == 0) { worker->is_idle = 1; change = true; break; } else if (worker->idle_seqnr < other->idle_seqnr) { worker->idle_seqnr = other->idle_seqnr; worker->is_idle = 1; change = true; } else if (worker->idle_seqnr > other->idle_seqnr) { worker->is_idle = 1; change = true; } else if (other->is_idle < worker->is_idle) { change = true; } } } if (change == false) { worker->is_idle += 1; } return (worker->is_idle < 3); }
/* Create a new worker. */ worker_t *SNetWorkerCreate( node_t *input_node, int worker_id, node_t *output_node, worker_role_t role) { worker_t *worker; trace(__func__); worker = SNetNewAlign(worker_t); worker->id = worker_id; worker->role = role; worker->victim_id = worker_id; WorkerTodoInit(&worker->todo); worker->prev = worker->iter = &worker->todo.head; WorkerFreeInit(&worker->free); if (input_node) { worker->input_desc = NODE_SPEC(input_node, input)->indesc; worker->has_input = true; } else { worker->input_desc = NULL; worker->has_input = false; } worker->output_node = output_node; worker->steal_lock = SNetNewAlign(worker_lock_t); worker->steal_lock->id = 0; worker->steal_turn = SNetNewAlign(worker_turn_t); worker->steal_turn->turn = 1; worker->loot.desc = NULL; worker->loot.count = 0; worker->loot.item = NULL; worker->hash_ptab = SNetHashPtrTabCreate(10, true); worker->continue_desc = NULL; worker->continue_rec = NULL; worker->has_work = true; worker->is_idle = false; worker->idle_seqnr = 0; return worker; }
/* Destroy a star node. */ void SNetStopStar(node_t *node, fifo_t *fifo) { star_arg_t *sarg = NODE_SPEC(node, star); trace(__func__); if (!sarg->stopping) { sarg->stopping = 1; SNetStopStream(sarg->instance, fifo); } else if (sarg->stopping == 1) { sarg->stopping = 2; SNetStopStream(sarg->collector, fifo); SNetExprListDestroy(sarg->guards); SNetVariantListDestroy(sarg->exit_patterns); SNetEntityDestroy(sarg->entity); SNetDelete(node); } }
/* Destroy a dripback node. */ void SNetStopDripBack(node_t *node, fifo_t *fifo) { dripback_arg_t *darg = NODE_SPEC(node, dripback); trace(__func__); if (darg->stopping == 0) { darg->stopping = 1; SNetStopStream(darg->instance, fifo); } else if (darg->stopping == 1) { darg->stopping = 2; SNetStopStream(darg->output, fifo); SNetVariantListDestroy(darg->back_patterns); SNetExprListDestroy(darg->guards); SNetStreamDestroy(darg->selfref); SNetEntityDestroy(darg->entity); SNetDelete(node); } }
/* Create the node which reads records from an input file via the parser. * This is called from networkinterface.c to initialize the input module. */ void SNetInInputInit( FILE *file, snetin_label_t *labels, snetin_interface_t *interfaces, snet_stream_t *output) { input_arg_t *iarg; node_t *node; landing_input_t *linp; const int first_worker_id = 1; trace(__func__); /* Create input node in the fixed network. */ node = SNetNodeNew(NODE_input, (snet_stream_t **)NULL, 0, &output, 1, SNetNodeInput, SNetStopInput, SNetTermInput); iarg = NODE_SPEC(node, input); iarg->output = output; iarg->state = INPUT_reading; /* Create an empty input descriptor: needed for SNetStreamOpen. */ iarg->indesc = SNetNewAlign(snet_stream_desc_t); memset(iarg->indesc, 0, sizeof(snet_stream_desc_t)); /* Create landing: needed for locking the input node before use. */ iarg->indesc->landing = SNetNewLanding(node, NULL, LAND_input); linp = DESC_LAND_SPEC(iarg->indesc, input); linp->num_inputs = 0; /* Create output descriptor: needed by parser for writing. */ iarg->indesc->landing->id = first_worker_id; linp->outdesc = SNetStreamOpen(output, iarg->indesc); iarg->indesc->landing->id = 0; /* Initialize the parser */ SNetInParserInit(file, labels, interfaces, NULL, NULL); }
/* Feedback creation function */ snet_stream_t *SNetFeedback( snet_stream_t *input, snet_info_t *info, int location, snet_variant_list_t *back_patterns, snet_expr_list_t *guards, snet_startup_fun_t box_a) { snet_stream_t *output; node_t *node; feedback_arg_t *farg; snet_locvec_t *locvec; int detlevel; trace(__func__); if (SNetFeedbackDeterministic()) { return SNetDripBack(input, info, location, back_patterns, guards, box_a); } detlevel = SNetDetSwapLevel(0); locvec = SNetLocvecGet(info); SNetLocvecFeedbackEnter(locvec); input = SNetRouteUpdate(info, input, location); if (SNetDistribIsNodeLocation(location)) { output = SNetStreamCreate(0); node = SNetNodeNew(NODE_feedback, &input, 1, &output, 1, SNetNodeFeedback, SNetStopFeedback, SNetTermFeedback); farg = NODE_SPEC(node, feedback); /* fill in the node argument */ farg->input = input; farg->output = output; farg->back_patterns = back_patterns; farg->guards = guards; farg->stopping = 0; /* Create the instance network */ farg->instance = SNetNodeStreamCreate(node); farg->feedback = (*box_a)(farg->instance, info, location); farg->feedback = SNetRouteUpdate(info, farg->feedback, location); /* Feedback loop should end at this node. */ assert(STREAM_DEST(farg->feedback) == NULL); STREAM_DEST(farg->feedback) = node; /* Create two self-referencing streams. */ farg->selfref2 = SNetNodeStreamCreate(node); STREAM_DEST(farg->selfref2) = node; farg->selfref4 = SNetNodeStreamCreate(node); STREAM_DEST(farg->selfref4) = node; farg->entity = SNetEntityCreate( ENTITY_fbdisp, location, locvec, "<feedback>", NULL, (void*)farg); } else { SNetExprListDestroy( guards); SNetVariantListDestroy(back_patterns); output = input; } SNetLocvecFeedbackLeave(locvec); SNetDetSwapLevel(detlevel); return output; }
/** * Convenience function for creating * Star, DetStar, StarIncarnate or DetStarIncarnate, * dependent on parameters is_incarnate and is_det. */ static snet_stream_t *CreateStar( snet_stream_t *input, snet_info_t *info, int location, snet_variant_list_t *exit_patterns, snet_expr_list_t *guards, snet_startup_fun_t box_a, snet_startup_fun_t box_b, bool is_incarnate, bool is_det) { snet_stream_t *output; node_t *node; star_arg_t *sarg; snet_locvec_t *locvec; locvec = SNetLocvecGet(info); if (!is_incarnate) { SNetLocvecStarEnter(locvec); } else { assert(false); } output = SNetStreamCreate(0); node = SNetNodeNew(NODE_star, location, &input, 1, &output, 1, SNetNodeStar, SNetStopStar, SNetTermStar); sarg = NODE_SPEC(node, star); sarg->input = input; sarg->collector = output; sarg->exit_patterns = exit_patterns; sarg->guards = guards; sarg->is_incarnate = is_incarnate; sarg->is_det = is_det; sarg->is_detsup = (SNetDetGetLevel() > 0); sarg->stopping = 0; /* create operand A */ sarg->instance = SNetNodeStreamCreate(node); (void) SNetLocvecStarSpawn(locvec); SNetSubnetIncrLevel(); sarg->internal = (*box_a)(sarg->instance, info, location); SNetSubnetDecrLevel(); (void) SNetLocvecStarSpawnRet(locvec); /* direct destination of operand back to this node */ STREAM_DEST(sarg->internal) = node; /* Is this a Star followed by only a Sync? */ if (SNetZipperEnabled() && NODE_TYPE(STREAM_DEST(sarg->instance)) == NODE_sync && STREAM_FROM(sarg->internal) == STREAM_DEST(sarg->instance)) { /* Replace the combination of star + sync with a fused sync-star. */ sync_arg_t *sync = NODE_SPEC(STREAM_DEST(sarg->instance), sync); /* if (SNetVerbose()) { printf("Replacing a star + sync with a fused sync-star.\n"); } */ output = SNetZipper(input, info, location, exit_patterns, guards, sync->patterns, sync->guard_exprs); SNetEntityDestroy(sync->entity); SNetVariantDestroy(sync->merged_pattern); SNetDelete(STREAM_DEST(sarg->instance)); SNetStreamDestroy(sarg->instance); SNetStreamDestroy(sarg->internal); SNetStreamDestroy(sarg->collector); SNetMemFree(node); } else { sarg->entity = SNetEntityCreate( ENTITY_star, location, locvec, "<star>", NULL, (void *) sarg); if (!is_incarnate) { /* the "top-level" star also creates a collector */ output = SNetCollectorDynamic(sarg->collector, location, info, is_det, node); SNetNodeTableAdd(sarg->internal); } } if (!is_incarnate) { SNetLocvecStarLeave(locvec); } return output; }