Ejemplo n.º 1
0
/* 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);
  }
}
Ejemplo n.º 2
0
snet_record_t *SNetRecCreate( snet_record_descr_t descr, ...)
{
  snet_record_t *rec;
  va_list args;

  rec = SNetMemAlloc( sizeof( snet_record_t));
  REC_DESCR( rec) = descr;

  va_start( args, descr);
  switch (descr) {
    case REC_data:
      RECPTR( rec) = SNetMemAlloc( sizeof( snet_record_types_t));
      RECORD( rec, data_rec) = SNetMemAlloc( sizeof( data_rec_t));
      DATA_REC( rec, btags) = SNetIntMapCreate(0);
      DATA_REC( rec, tags) = SNetIntMapCreate(0);
      DATA_REC( rec, fields) = SNetRefMapCreate(0);
      DATA_REC( rec, mode) = MODE_binary;
      GenerateRecId( &DATA_REC( rec, rid) );
      DATA_REC( rec, parent_rids) = NULL;
      DATA_REC( rec, interface_id) = 0;
      break;
    case REC_trigger_initialiser:
      RECPTR( rec) = SNetMemAlloc( sizeof( snet_record_types_t));
      break;
    case REC_sync:
      {
        RECPTR( rec) = SNetMemAlloc( sizeof( snet_record_types_t));
        RECORD( rec, sync_rec) = SNetMemAlloc( sizeof( sync_rec_t));
        SYNC_REC( rec, input) = va_arg( args, snet_stream_t *);
        SYNC_REC( rec, outtype) = NULL;
      }
      break;
    case REC_collect:
      RECPTR( rec) = SNetMemAlloc( sizeof( snet_record_types_t));
      RECORD( rec, coll_rec) = SNetMemAlloc( sizeof( coll_rec_t));
      COLL_REC( rec, output) = va_arg( args, snet_stream_t*);
      break;
    case REC_terminate:
      RECPTR( rec) = SNetMemAlloc( sizeof( snet_record_types_t));
      RECORD( rec, terminate_rec) = SNetMemAlloc( sizeof( terminate_rec_t));
      TERM_REC( rec, local) = false;
      break;
    case REC_sort_end:
      RECPTR( rec) = SNetMemAlloc( sizeof( snet_record_types_t));
      RECORD( rec, sort_end_rec) = SNetMemAlloc( sizeof( sort_end_rec_t));
      SORT_E_REC( rec, level) = va_arg( args, int);
      SORT_E_REC( rec, num) = va_arg( args, int);
      break;
    default:
      SNetUtilDebugFatal("Unknown control record description. [%d]", descr);
      break;
  }
  va_end( args);

  return rec;
}
Ejemplo n.º 3
0
void SNetRecDestroy( snet_record_t *rec)
{
  int name;
  snet_ref_t *field;

  switch (REC_DESCR( rec)) {
    case REC_data:
      RECORD_FOR_EACH_FIELD(rec, name, field) {
        SNetRefDestroy(field);
      }
      SNetRefMapDestroy( DATA_REC( rec, fields));
      SNetIntMapDestroy( DATA_REC( rec, tags));
      SNetIntMapDestroy( DATA_REC( rec, btags));
      if (DATA_REC( rec, parent_rids) != NULL) SNetRecIdListDestroy( DATA_REC( rec, parent_rids));
      SNetMemFree( RECORD( rec, data_rec));
      break;
    case REC_sync:
      {
        snet_variant_t *var = SYNC_REC( rec, outtype);
        if (var != NULL) {
          SNetVariantDestroy(var);
        }
        SNetMemFree( RECORD( rec, sync_rec));
      }
      break;
    case REC_collect:
      SNetMemFree( RECORD( rec, coll_rec));
      break;
    case REC_sort_end:
      SNetMemFree( RECORD( rec, sort_end_rec));
      break;
    case REC_terminate:
      SNetMemFree( RECORD( rec, terminate_rec));
      break;
    case REC_trigger_initialiser:
      break;
    default:
      SNetUtilDebugFatal("Unknown record description, in SNetRecDestroy");
      break;
  }
Ejemplo n.º 4
0
snet_record_t *SNetRecCopy( snet_record_t *rec)
{
  snet_record_t *new_rec;

  switch (REC_DESCR( rec)) {
    case REC_data:
      new_rec = SNetMemAlloc( sizeof( snet_record_t));
      REC_DESCR( new_rec) = REC_data;
      RECPTR( new_rec) = SNetMemAlloc( sizeof( snet_record_types_t));
      RECORD( new_rec, data_rec) = SNetMemAlloc( sizeof( data_rec_t));

      DATA_REC( new_rec, fields) = SNetRefMapCopy(DATA_REC(rec, fields));
      DATA_REC( new_rec, tags) = SNetIntMapCopy( DATA_REC( rec, tags));
      DATA_REC( new_rec, btags) = SNetIntMapCopy( DATA_REC( rec, btags));
      SNetRecSetInterfaceId( new_rec, SNetRecGetInterfaceId( rec));
      SNetRecSetDataMode( new_rec, SNetRecGetDataMode( rec));
      DATA_REC( new_rec, parent_rids) = NULL;
      /*
      (DATA_REC( rec, parent_rids)==NULL) ?
        NULL : SNetRecIdListCopy(DATA_REC( rec, parent_rids));
      */
      break;
    case REC_sort_end:
      new_rec = SNetRecCreate( REC_DESCR( rec),  SORT_E_REC( rec, level),
                               SORT_E_REC( rec, num));
      break;
    case REC_terminate:
      new_rec = SNetRecCreate( REC_terminate);
      TERM_REC(new_rec, local) = TERM_REC(rec, local);
      break;
    default:
      new_rec = NULL;
      SNetUtilDebugFatal("Can't copy record of type %d", REC_DESCR( rec));
      break;
  }

  return new_rec;
}
Ejemplo n.º 5
0
/* DripBack process a record. */
void SNetNodeDripBack(snet_stream_desc_t *desc, snet_record_t *rec)
{
  landing_t             *land = desc->landing;
  dripback_arg_t        *darg = LAND_NODE_SPEC(land, dripback);

  trace(__func__);

  if (land->type == LAND_dripback1) {
    landing_dripback1_t *db1 = LAND_SPEC(land, dripback1);
    landing_dripback2_t *db2 = LAND_SPEC(db1->dripback2, dripback2);
    SNetFifoPut(db1->recfifo, rec);
    if (FAA(&db2->queued, 1) == 0) {
      if (db1->controldesc == NULL) {
        SNetPushLanding(desc, db1->dripback2);
        db1->controldesc = SNetStreamOpen(darg->selfref, desc);
      }
      rec = SNetRecCreate(REC_wakeup);
      SNetWrite(&db1->controldesc, rec, true);
    }
  }
  else if (land->type == LAND_dripback2) {
    landing_dripback2_t *db2 = LAND_SPEC(land, dripback2);
    bool via_access = (DESC_STREAM(desc) == darg->selfref);

    assert(via_access || DESC_STREAM(desc) == darg->dripback);

    while (rec) {
      switch (REC_DESCR( rec)) {
        case REC_data:
          /* Test if record should go to the instance. */
          if (SNetFeedbackMatch( rec, darg->back_patterns, darg->guards)) {
            if (via_access) {
              /* Because record came from outside add a detref counter. */
              assert(db2->detfifo.head->next == NULL);
              SNetRecDetrefAdd(rec, ++(db2->entered), land, &db2->detfifo);
            } else {
              /* Record came from the instance. */
              assert(DATA_REC(rec, detref));
            }
            if (db2->instdesc == NULL) {
              /* Instance should come back to this landing. */
              if (SNetTopLanding(desc) != land) {
                SNetPushLanding(desc, land);
              }
              db2->instdesc = SNetStreamOpen(darg->instance, desc);
              if (SNetTopLanding(desc) == land) {
                SNetPopLanding(desc);
                SNetLandingDone(land);
              }
            }
            SNetWrite(&db2->instdesc, rec, false);
          } else {
            if (!via_access) {
              /* Record leaves the dripback loop. */
              assert(DATA_REC(rec, detref));
              SNetFeedbackLeave(rec, land, &db2->detfifo);
            }
            if (db2->outdesc == NULL) {
              db2->outdesc = SNetStreamOpen(darg->output, desc);
            }
            SNetWrite(&db2->outdesc, rec, false);
          }
          break;

        case REC_wakeup:
          assert(via_access);
          SNetRecDestroy(rec);
          break;

        case REC_terminate:
          assert(via_access);
          assert(db2->terminate == DripBackInitial);
          db2->terminate = DripBackDraining;
          SNetRecDestroy(rec);
          break;

        case REC_detref:
          if (DETREF_REC( rec, leave) == land &&
              DETREF_REC( rec, location) == SNetDistribGetNodeId())
          {
            assert(!via_access);
            SNetDetLeaveCheckDetref(rec, &db2->detfifo);
            if (DETREF_REC( rec, detref) == SNetFifoPeekFirst(&db2->detfifo)) {
              DripBackCheckBusy(db2);
            }
            SNetRecDestroy(rec);
          } else {
            assert(via_access);
            if (db2->outdesc == NULL) {
              db2->outdesc = SNetStreamOpen(darg->output, desc);
            }
            SNetWrite(&db2->outdesc, rec, false);
          }
          break;

        case REC_sync:
          SNetRecDestroy(rec);
          break;

        default:
          SNetRecUnknownEnt(__func__, rec, darg->entity);
      }
      rec = NULL;
      if (db2->state == DripBackBusy) {
        if (DripBackCheckBusy(db2) == false) {
          assert(db2->queued > 0);
          if (SAF(&db2->queued, 1) == 0) {
            db2->state = DripBackIdle;
          } else {
            rec = SNetFifoGet(&db2->recfifo);
            assert(rec);
            via_access = true;
          }
        }
      } else {
        assert(db2->state == DripBackIdle);
        assert(SNetFifoPeekFirst(&db2->detfifo) == NULL);
        if (db2->queued > 0) {
          rec = SNetFifoGet(&db2->recfifo);
          assert(rec);
          via_access = true;
          db2->state = DripBackBusy;
        }
      }
    }
    if (db2->terminate == DripBackDraining) {
      if (db2->state == DripBackIdle) {
        assert(db2->queued == 0 && DripBackCheckBusy(db2) == false);
        db2->terminate = DripBackTerminated;
      }
    }
    if (db2->terminate == DripBackTerminated) {
      if (db2->instdesc) {
        snet_stream_desc_t *desc = db2->instdesc;
        db2->instdesc = NULL;
        SNetDescDone(desc);
        SNetLandingDone(land);
      }
    }
  }
  else {
    assert(0);
  }
}