/* 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); }
/* Destroy a stream descriptor. */ void SNetStreamClose(snet_stream_desc_t *desc) { trace(__func__); assert(desc->refs == 0); SNetFifoDone(&desc->fifo); SNetDelete(desc); }
/* Free a stream */ void SNetStreamDestroy(snet_stream_t *stream) { trace(__func__); stream->from = NULL; stream->dest = NULL; SNetDelete(stream); }
/* A record arriving via the loopback now leaves the feedback network. * Remove the detref structure and check for termination conditions. */ void SNetFeedbackLeave(snet_record_t *rec, landing_t *landing, fifo_t *detfifo) { snet_stack_t *stack; detref_t *detref, *first; trace(__func__); // record must have a stack of detrefs if ((stack = DATA_REC(rec, detref)) == NULL) { SNetUtilDebugFatal("[%s]: missing stack.", __func__); } // stack must have at least one detref if ((detref = SNetStackPop(stack)) == NULL) { SNetUtilDebugFatal("[%s]: empty stack.", __func__); } if (SNetStackIsEmpty(stack)) { SNetStackDestroy(stack); DATA_REC(rec, detref) = NULL; } // detref must refer to this DetLeave node if (detref->leave != landing) { SNetUtilDebugFatal("[%s]: leave %p != landing %p.", __func__, detref->leave, landing); } // reference counter must be at least two if (detref->refcount < 2) { SNetUtilDebugFatal("[%s]: refcnt %d < 1.", __func__, detref->refcount); } // decrease reference count if (DETREF_DECR(detref) == 1) { DETREF_DECR(detref); } assert(detref->refcount >= 0); // pop detrefs in sequence which have no more records in the loopback left. while ((first = SNetFifoPeekFirst(detfifo)) != NULL) { // stop processing if more records to come for this sequence counter if (first->refcount > 0) { break; } SNetFifoGet(detfifo); SNetFifoDone(&first->recfifo); SNetDelete(first); } }
/* Destroy a worker. */ void SNetWorkerDestroy(worker_t *worker) { trace(__func__); /* if (SNetVerbose()) { if (worker->id == 1) { printf("Created %u records\n", SNetGetRecCounter()); } } */ /* Verify hash table is empty. */ if ( ! SNetHashPtrTabEmpty(worker->hash_ptab)) { snet_stream_desc_t *desc = SNetHashPtrFirst(worker->hash_ptab); do { work_item_t *item = SNetHashPtrLookup(worker->hash_ptab, desc); printf("%s(%d,%d): desc %p, count %d, refs %d\n", __func__, worker->id, worker->role, desc, item->count, desc->refs); } while ((desc = SNetHashPtrNext(worker->hash_ptab, desc)) != NULL); } /* Free hash table. */ SNetHashPtrTabDestroy(worker->hash_ptab); /* Free the list of free work items. */ while (worker->free.head) { work_item_t *item = worker->free.head; worker->free.head = item->next_free; SNetDelete(item); } /* Free lock */ SNetDelete(worker->steal_lock); SNetDelete(worker->steal_turn); /* Free worker. */ SNetDelete(worker); }
/* Minimize the number of cached work items on the free list. */ static void ReduceWorkItems(worker_t *worker) { work_item_t *item; while ((item = worker->free.head) != NULL && (item->turn < worker->steal_turn->turn || (item->turn == worker->steal_turn->turn && worker->steal_lock->id == 0))) { if ((worker->free.head = item->next_free) == NULL) { worker->free.tail = NULL; } --worker->free.count; SNetDelete(item); } }
/* Check if there are any records in the dripback loop left. */ static bool DripBackCheckBusy(landing_dripback2_t *db2) { detref_t *first; /* check if dripback loop is still active */ while ((first = SNetFifoPeekFirst(&db2->detfifo)) != NULL) { BAR(); if (first->refcount > 0) { break; } SNetFifoGet(&db2->detfifo); SNetFifoDone(&first->recfifo); SNetDelete(first); } return first ? true : false; }
/* 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); } }
/* Check if there are any records in the feedback loop left. */ static void FeedbackCheckBusy(landing_feedback3_t *fb3) { detref_t *first; /* check if feedback loop is still active */ while ((first = SNetFifoPeekFirst(&fb3->detfifo)) != NULL) { if (first->refcount > 0) { break; } SNetFifoGet(&fb3->detfifo); SNetFifoDone(&first->recfifo); SNetDelete(first); } if (first == NULL && fb3->terminate == FeedbackDraining) { fb3->terminate = FeedbackTerminating; } }
/** * 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; }