Beispiel #1
0
struct Value *operator(struct Value *args, struct Value *body,
                        struct Value *env)
{
  struct Operator *o;
  if (!(o = allocate(sizeof(struct Operator))))
    return 0;
  o->args = args;
  o->body = body;
  o->env = env;
  ref_inc(args);
  ref_inc(body);
  ref_inc(env);
  return make_value(OPERATOR, o);
}
Beispiel #2
0
struct Value *closure(struct Value *args, struct Value *body,
                       struct Value *env)
{
  struct Closure *c;
  if (!(c = allocate(sizeof(struct Closure))))
    return 0;
  c->args = args;
  c->body = body;
  c->env = env;
  ref_inc(args);
  ref_inc(body);
  ref_inc(env);
  return make_value(CLOSURE, c);
}
Beispiel #3
0
/*
 * Fills the arrays / queues with the states from the trace file and updates
 * counters. Assumes everything passed (except the filename) to be NULL/0.
 */
static void
read_events(char const *filename, size_t *ranks, struct State_q **state_q,
    struct Link_q ***links, outter_t *sends, struct State_q ***recvs, uint64_t
    **slens, double **last, double **clast, struct State_q ***scattersS,
    struct State_q ***scattersR, struct State_q ***gathersS, struct State_q
    ***gathersR)
{
  /* Important for some (size_t) conversions from marks registered as uint64 */
  assert(SIZE_MAX <= UINT64_MAX);
  FILE *f = fopen(filename, "r");
  if (!f)
    LOG_AND_EXIT("Could not open %s: %s\n", filename, strerror(errno));
  char *line = mygetline(f);
  if (!line)
    REPORT_AND_EXIT;
  uint64_t *scaps = NULL;
  uint64_t const ocap = 10;
  /* Initialize all arrs/queues with one rank each */
  grow_outer(ranks, 1, links, sends, recvs, scattersS, scattersR, gathersS,
      gathersR, last, clast, slens, &scaps, ocap);
  do {
    /* strtok shenanigans */
    char *state_line = strdup(line),
         *link_line = strdup(line),
         *etc_line = strdup(line);
    free(line);
    if (!state_line || !link_line || !etc_line)
      REPORT_AND_EXIT;
    struct State *state = state_from_line(state_line);
    if (!state) {
      struct Link *link = link_from_line(link_line);
      if (!link) {
        LOG_DEBUG("Line is not a State nor a Link\n");//: %s", etc_line);
        printf("%s", etc_line);
      } else {
        size_t rank = (size_t)(link->to + 1);
        if (rank > *ranks)
          grow_outer(ranks, rank, links, sends, recvs, scattersS, scattersR,
              gathersS, gathersR, last, clast, slens, &scaps, ocap);
        /* (grow outer aborts on failure) */
        link_q_push_ref((*links) + link->to, link);
        /* Toss away our local ref obtained on allocation */
        ref_dec(&(link->ref));
      }
    } else {
      size_t rank = (size_t)(state->rank + 1);
      if (rank > *ranks)
        grow_outer(ranks, rank, links, sends, recvs, scattersS, scattersR,
            gathersS, gathersR, last, clast, slens, &scaps, ocap);
      if ((*last)[state->rank] < 0)
        (*last)[state->rank] = state->start;
      state_q_push_ref(state_q, state);
      if (state_is_send(state)) {
        (*sends)[state->rank][(*slens)[state->rank]] = state;
        ref_inc(&(state->ref));
        if (++((*slens)[state->rank]) >= scaps[state->rank])
          grow_inner((*sends) + state->rank, scaps + state->rank);
      } else if (state_is_recv(state)) {
        state_q_push_ref((*recvs) + state->rank, state);
      } else if (state_is_wait(state)) {
        /*
         * For now we only support MPI_Wait for MPI_Isend (->mark). Thus,
         * MPI_Wait is always in the same rank as the matching MPI_Isend and
         * always comes after it, so we can assume the matching send has
         * already been processed and create a temporary comm in here, to be
         * used later to link the MPI_Wait to the MPI_Recv it is actually
         * waiting for (we assume MPI_Isend was synchronous, albeit
         * instantaneous, and we assert for that).
         */
        if ((*slens)[state->rank] <= state->mark) {
          LOG_CRITICAL("There is no Send for the Wait. Did you call MPI_Wait "
              "without (or before) a matching MPI_Isend? This is not "
              "supported.\n");
          exit(EXIT_FAILURE);
        }         // TODO can this be moved to pj_compensate.c with the rest?
        struct State *send = (*sends)[state->rank][state->mark];
        assert(send->mark == state->mark);
        send->comm.c = comm_new(state, NULL, 0);
      // TODO dont use a separate queue for scatter/gather
      } else if (state_is_1tn(state)) {
        if (state_is_1tns(state))
          state_q_push_ref((*scattersS) + state->rank, state);
        else
          state_q_push_ref((*scattersR) + state->rank, state);
      } else if (state_is_nt1(state)) {
        if (state_is_nt1s(state))
          state_q_push_ref((*gathersS) + state->rank, state);
        else
          state_q_push_ref((*gathersR) + state->rank, state);
      }
      ref_dec(&(state->ref));
    }
    free(state_line);
    free(link_line);
    free(etc_line);
    line = mygetline(f);
  } while (line);
  fclose(f);
  free(scaps);
  for (size_t i = 0; i < *ranks; i++)
    if ((*last)[i] < 0)
      LOG_WARNING("Empty rank %zu or initial timestamp < 0\n", i);
}