示例#1
0
/* Create the caller's context file */
extern int gasneti_checkpoint_create(const char *dir) {
  const int flags = O_WRONLY|O_APPEND|O_CREAT|O_EXCL|O_LARGEFILE|O_TRUNC;
  const int mode = S_IRUSR;
  char *filename;
  size_t len;
  int fd;

  gasneti_assert(NULL != dir);

  len = strlen(dir) + 19; /* 19 = "/context.123456789\0" */
  filename = gasneti_malloc(len);
  snprintf(filename, len, "%s/context.%d", dir, gasneti_mynode);
  fd = open(filename, flags, mode);
  gasneti_free(filename);

  if (fd < 0) { /* BLCR-TODO: error checking/recovery */
    gasneti_fatalerror("Failed to create '%s' errno=%d(%s)\n", filename, errno, strerror(errno));
  }

  return fd;
}
示例#2
0
extern int gasnetc_Segment_Attach(
                gex_Segment_t          *segment_p,
                gex_TM_t               tm,
                uintptr_t              length)
{
  gasneti_assert(segment_p);

  // TODO-EX: remove when this limitation is removed
  static int once = 1;
  if (once) once = 0;
  else gasneti_fatalerror("gex_Segment_Attach: current implementation can be called at most once");

  /* create a segment collectively */
  // TODO-EX: this implementation only works *once*
  // TODO-EX: should be using the team's exchange function if possible
  // TODO-EX: need to pass proper flags (e.g. pshm and bind) instead of 0
  if (GASNET_OK != gasnetc_attach_segment(segment_p, tm, length, gasneti_defaultExchange, 0))
    GASNETI_RETURN_ERRR(RESOURCE,"Error attaching segment");

  return GASNET_OK;
}
示例#3
0
void gasnete_coll_tree_type_to_str(char *outbuf, gasnete_coll_tree_type_t in) {
  gasneti_assert(in->subtree == NULL);
  gasneti_assert(in->num_params <= 1);
  switch(in->tree_class) {
    
  case GASNETE_COLL_NARY_TREE:
      sprintf(outbuf, "NARY_TREE,%d", in->params[0]);
      break;
  case GASNETE_COLL_FLAT_TREE:
    strcpy(outbuf, "FLAT_TREE");
    break;
  case GASNETE_COLL_KNOMIAL_TREE:
    sprintf(outbuf, "KNOMIAL_TREE,%d", in->params[0]);
    break;
  case GASNETE_COLL_RECURSIVE_TREE:
    sprintf(outbuf, "RECURSIVE_TREE,%d", in->params[0]);
    break;
  default:
    gasneti_fatalerror("unknown tree type");
  }
  
}
示例#4
0
extern void gasnetc_exit(int exitcode) {
  /* once we start a shutdown, ignore all future SIGQUIT signals or we risk reentrancy */
  gasneti_reghandler(SIGQUIT, SIG_IGN);
  gasnetc_exitcalled = 1;

  {  /* ensure only one thread ever continues past this point */
    static gasneti_mutex_t exit_lock = GASNETI_MUTEX_INITIALIZER;
    gasneti_mutex_lock(&exit_lock);
  }

  GASNETI_TRACE_PRINTF(C,("gasnet_exit(%i)\n", exitcode));

  gasneti_flush_streams();
  gasneti_trace_finish();
  gasneti_sched_yield();

  /* bug2181: try to prevent races where we exit while other local pthreads are in AMUDP
     can't use a blocking lock here, because may be in a signal context
  */
  AMLOCK_CAUTIOUS();

  AMUDP_SPMDExit(exitcode);
  gasneti_fatalerror("AMUDP_SPMDExit failed!");
}
示例#5
0
static inline void gasnetc_PostSend(mxm_send_req_t * mxm_sreq,
                                    uint8_t is_request,
                                    uint8_t block,
                                    uint8_t msg_num)
{
    mxm_error_t mxm_res;

#if GASNET_DEBUG_AM
    MXM_LOG("[pid %d] calling mxm_req_send()...\n", getpid());
#endif

    mxm_res = mxm_req_send(mxm_sreq);

#if GASNET_DEBUG_AM
    MXM_LOG("[pid %d] mxm_req_send() returned %d\n", getpid(), (int)mxm_res);
#endif

    if_pf (mxm_res != MXM_OK)
    gasneti_fatalerror("Error posting send request - %s\n",
                       mxm_error_string(mxm_res));

    if_pt (block)
    gasnetc_ReqRepWait(mxm_sreq, is_request, msg_num);
}
示例#6
0
/*  allocate more eops */
GASNETI_NEVER_INLINE(gasnete_eop_alloc,
static void gasnete_eop_alloc(gasneti_threaddata_t * const thread)) {
    gasnete_eopaddr_t addr;
    int bufidx = thread->eop_num_bufs;
    gasnete_eop_t *buf;
    int i;
    gasnete_threadidx_t threadidx = thread->threadidx;
    if (bufidx == 256) gasneti_fatalerror("GASNet Extended API: Ran out of explicit handles (limit=65535)");
    thread->eop_num_bufs++;
    buf = (gasnete_eop_t *)gasneti_calloc(256,sizeof(gasnete_eop_t));
    gasneti_leak(buf);
    for (i=0; i < 256; i++) {
      addr.bufferidx = bufidx;
      #if GASNETE_SCATTER_EOPS_ACROSS_CACHELINES
        #ifdef GASNETE_EOP_MOD
          addr.eopidx = (i+32) % 255;
        #else
          { int k = i+32;
            addr.eopidx = k > 255 ? k - 255 : k;
          }
        #endif
      #else
        addr.eopidx = i+1;
      #endif
      buf[i].threadidx = threadidx;
      buf[i].addr = addr;
      #if 0 /* these can safely be skipped when the values are zero */
	SET_OPSTATE(&(buf[i]),OPSTATE_FREE);
	SET_OPTYPE(&(buf[i]),OPTYPE_EXPLICIT);
       #if GASNETE_EOP_COUNTED
        buff[i].initiated_cnt = 0;
       #endif
      #endif
      #if GASNETE_EOP_COUNTED
        gasnetc_atomic_set(&(buf[i].completed_cnt), 0, 0);
      #endif
    }
     /*  add a list terminator */
    #if GASNETE_SCATTER_EOPS_ACROSS_CACHELINES
      #ifdef GASNETE_EOP_MOD
        buf[223].addr.eopidx = 255; /* modular arithmetic messes up this one */
      #endif
      buf[255].addr = EOPADDR_NIL;
    #else
      buf[255].addr = EOPADDR_NIL;
    #endif
    thread->eop_bufs[bufidx] = buf;
    addr.bufferidx = bufidx;
    addr.eopidx = 0;
    thread->eop_free = addr;

    #if GASNET_DEBUG
    { /* verify new free list got built correctly */
      int i;
      int seen[256];
      gasnete_eopaddr_t addr = thread->eop_free;

      #if 0
      if (gasneti_mynode == 0)
        for (i=0;i<256;i++) {                                   
          fprintf(stderr,"%i:  %i: next=%i\n",gasneti_mynode,i,buf[i].addr.eopidx);
          fflush(stderr);
        }
        sleep(5);
      #endif

      gasneti_memcheck(thread->eop_bufs[bufidx]);
      memset(seen, 0, 256*sizeof(int));
      for (i=0;i<(bufidx==255?255:256);i++) {                                   
        gasnete_eop_t *eop;                                   
        gasneti_assert(!gasnete_eopaddr_isnil(addr));                 
        eop = GASNETE_EOPADDR_TO_PTR(thread,addr);            
        gasneti_assert(OPTYPE(eop) == OPTYPE_EXPLICIT);               
        gasneti_assert(OPSTATE(eop) == OPSTATE_FREE);
        gasneti_assert(eop->threadidx == threadidx);                  
        gasneti_assert(addr.bufferidx == bufidx);
        gasneti_assert(!seen[addr.eopidx]);/* see if we hit a cycle */
        seen[addr.eopidx] = 1;
        addr = eop->addr;                                     
      }                                                       
      gasneti_assert(gasnete_eopaddr_isnil(addr)); 
    }
    #endif
}
示例#7
0
void gasnetc_bootstrapExchange(void *src, size_t len, void *dest) {
  int retval;
  GASNETI_AM_SAFE_NORETURN(retval,AMUDP_SPMDAllGather(src, dest, len));
  if_pf (retval) gasneti_fatalerror("failure in gasnetc_bootstrapExchange()");
}
示例#8
0
void gasnetc_bootstrapBarrier(void) {
   int retval;
   AM_ASSERT_LOCKED(); /* need this because SPMDBarrier may poll */
   GASNETI_AM_SAFE_NORETURN(retval,AMUDP_SPMDBarrier());
   if_pf (retval) gasneti_fatalerror("failure in gasnetc_bootstrapBarrier()");
}
示例#9
0
static int gasnetc_init(int *argc, char ***argv) {
  int retval = GASNET_OK;

  /*  check system sanity */
  gasnetc_check_config();

  /* --------- begin Master code ------------ */
  if (!AMUDP_SPMDIsWorker(argv?*argv:NULL)) {
    /* assume we're an implicit master 
       (we don't currently support explicit workers spawned 
        without using the AMUDP SPMD API)   
     */
    int num_nodes;
    int i;
    char spawnfn;
    amudp_spawnfn_t fp = (amudp_spawnfn_t)NULL;

    if (!argv) {
      gasneti_fatalerror("implicit-master without argv not supported - use amudprun");
    }

    /* pretend we're node 0, for purposes of verbose env reporting */
    gasneti_init_done = 1;
    gasneti_mynode = 0;

    #if defined(GASNET_CSPAWN_CMD)
    { /* set configure default cspawn cmd */
      const char *cmd = gasneti_getenv_withdefault("GASNET_CSPAWN_CMD",GASNET_CSPAWN_CMD);
      gasneti_setenv("GASNET_CSPAWN_CMD",cmd);
    }
    #endif

    /* parse node count from command line */
    if (*argc < 2) {
      fprintf(stderr, "GASNet: Missing parallel node count\n");
      fprintf(stderr, "GASNet: Specify node count as first argument, or use upcrun/tcrun spawner script to start job\n");
      fprintf(stderr, "GASNet: Usage '%s <num_nodes> {program arguments}'\n", (*argv)[0]);
      exit(-1);
    }
    /*
     * argv[1] is number of nodes; argv[0] is program name; argv is
     * list of arguments including program name and number of nodes.
     * We need to remove argv[1] when the argument array is passed
     * to the tic_main().
     */
    num_nodes = atoi((*argv)[1]);
    if (num_nodes < 1) {
      fprintf (stderr, "GASNet: Invalid number of nodes: %s\n", (*argv)[1]);
      fprintf (stderr, "GASNet: Usage '%s <num_nodes> {program arguments}'\n", (*argv)[0]);
      exit (1);
    }

    /* remove the num_nodes argument */
    for (i = 1; i < (*argc)-1; i++) {
      (*argv)[i] = (*argv)[i+1];
    }
    (*argv)[(*argc)-1] = NULL;
    (*argc)--;

    /* get spawnfn */
    spawnfn = *gasneti_getenv_withdefault("GASNET_SPAWNFN", _STRINGIFY(GASNETC_DEFAULT_SPAWNFN));

    { /* ensure we pass the effective spawnfn to worker env */
      char spawnstr[2];
      spawnstr[0] = toupper(spawnfn);
      spawnstr[1] = '\0';
      gasneti_setenv("GASNET_SPAWNFN",spawnstr);
    }

    /* ensure reliable localhost operation by forcing use of 127.0.0.1
     * setting GASNET_MASTERIP to the empty string will prevent this */
    if (('L' == toupper(spawnfn)) && !gasneti_getenv("GASNET_MASTERIP")) {
      gasneti_setenv("GASNET_MASTERIP","127.0.0.1");
    }

    for (i=0; AMUDP_Spawnfn_Desc[i].abbrev; i++) {
      if (toupper(spawnfn) == toupper(AMUDP_Spawnfn_Desc[i].abbrev)) {
        fp = AMUDP_Spawnfn_Desc[i].fnptr;
        break;
      }
    }

    if (!fp) {
      fprintf (stderr, "GASNet: Invalid spawn function specified in GASNET_SPAWNFN\n");
      fprintf (stderr, "GASNet: The following mechanisms are available:\n");
      for (i=0; AMUDP_Spawnfn_Desc[i].abbrev; i++) {
        fprintf(stderr, "    '%c'  %s\n",  
              toupper(AMUDP_Spawnfn_Desc[i].abbrev), AMUDP_Spawnfn_Desc[i].desc);
      }
      exit(1);
    }

    #if GASNET_DEBUG_VERBOSE
      /* note - can't call trace macros during gasnet_init because trace system not yet initialized */
      fprintf(stderr,"gasnetc_init(): about to spawn...\n"); fflush(stderr);
    #endif

    retval = AMUDP_SPMDStartup(argc, argv, 
      num_nodes, 0, fp,
      NULL, &gasnetc_bundle, &gasnetc_endpoint);
    /* master startup should never return */
    gasneti_fatalerror("master AMUDP_SPMDStartup() failed");
  }

  /* --------- begin Worker code ------------ */
  AMLOCK();
    if (gasneti_init_done) 
      INITERR(NOT_INIT, "GASNet already initialized");

    gasneti_freezeForDebugger();

    AMUDP_VerboseErrors = gasneti_VerboseErrors;
    AMUDP_SPMDkillmyprocess = gasneti_killmyprocess;

    /*  perform job spawn */
    retval = AMUDP_SPMDStartup(argc, argv, 
      0, 0, NULL, /* dummies */
      &gasnetc_networkpid, &gasnetc_bundle, &gasnetc_endpoint);
    if (retval != AM_OK) INITERR(RESOURCE, "slave AMUDP_SPMDStartup() failed");
    gasneti_init_done = 1; /* enable early to allow tracing */

    gasneti_conduit_getenv = (/* cast drops const */ gasneti_getenv_fn_t*)&AMUDP_SPMDgetenvMaster;
    gasneti_mynode = AMUDP_SPMDMyProc();
    gasneti_nodes = AMUDP_SPMDNumProcs();

    /* enable tracing */
    gasneti_trace_init(argc, argv);
    GASNETI_AM_SAFE(AMUDP_SPMDSetExitCallback(gasnetc_traceoutput));

    /* for local spawn, assume we want to wait-block */
    if (gasneti_getenv("GASNET_SPAWNFN") && *gasneti_getenv("GASNET_SPAWNFN") == 'L') { 
      GASNETI_TRACE_PRINTF(C,("setting gasnet_set_waitmode(GASNET_WAIT_BLOCK) for localhost spawn"));
      gasnet_set_waitmode(GASNET_WAIT_BLOCK);
    }

    #if GASNET_DEBUG_VERBOSE
      fprintf(stderr,"gasnetc_init(): spawn successful - node %i/%i starting...\n", 
        gasneti_mynode, gasneti_nodes); fflush(stderr);
    #endif

    gasneti_nodemapInit(&gasnetc_bootstrapExchange, NULL, 0, 0);

    #if GASNET_PSHM
      gasneti_pshm_init(&gasnetc_bootstrapSNodeBroadcast, 0);
    #endif

    #if GASNET_SEGMENT_FAST || GASNET_SEGMENT_LARGE
    { uintptr_t limit;
      #if HAVE_MMAP
        limit = gasneti_mmapLimit((uintptr_t)-1, (uint64_t)-1,
                                  &gasnetc_bootstrapExchange,
                                  &gasnetc_bootstrapBarrier);
      #else
        limit = (intptr_t)-1;
      #endif
      gasneti_segmentInit(limit, &gasnetc_bootstrapExchange);
    }
    #elif GASNET_SEGMENT_EVERYTHING
      /* segment is everything - nothing to do */
    #else
      #error Bad segment config
    #endif

    #if GASNET_BLCR
      gasneti_checkpoint_guid = gasnetc_networkpid;
      gasneti_checkpoint_init(NULL);
    #endif

  AMUNLOCK();

  gasneti_auxseg_init(); /* adjust max seg values based on auxseg */

  gasneti_assert(retval == GASNET_OK);
  return retval;

done: /*  error return while locked */
  AMUNLOCK();
  GASNETI_RETURN(retval);
}
示例#10
0
extern void gasneti_vis_progressfn(void) { 
  GASNETE_THREAD_LOOKUP /* TODO: remove this lookup */
  gasnete_vis_threaddata_t *td = GASNETE_VIS_MYTHREAD; 
  gasneti_vis_op_t **lastp = &(td->active_ops);
  if (td->progressfn_active) return; /* prevent recursion */
  td->progressfn_active = 1;
  for (lastp = &(td->active_ops); *lastp; ) {
    gasneti_vis_op_t * const visop = *lastp;
    #ifdef GASNETE_VIS_PROGRESSFN_EXTRA
           GASNETE_VIS_PROGRESSFN_EXTRA(visop, lastp)
    #endif
    switch (visop->type) {
    #ifdef GASNETE_PUTV_GATHER_SELECTOR
      case GASNETI_VIS_CAT_PUTV_GATHER:
        if (gasnete_try_syncnb(visop->handle) == GASNET_OK) { /* TODO: remove recursive poll */
          GASNETE_VISOP_SIGNAL_AND_FREE(visop, 0);
        }
      break;
    #endif
    #ifdef GASNETE_GETV_SCATTER_SELECTOR
      case GASNETI_VIS_CAT_GETV_SCATTER:
        if (gasnete_try_syncnb(visop->handle) == GASNET_OK) {
          gasnet_memvec_t const * const savedlst = (gasnet_memvec_t const *)(visop + 1);
          void const * const packedbuf = savedlst + visop->count;
          gasnete_memvec_unpack(visop->count, savedlst, packedbuf, 0, (size_t)-1);
          GASNETE_VISOP_SIGNAL_AND_FREE(visop, 1);
        }
      break;
    #endif
    #ifdef GASNETE_PUTI_GATHER_SELECTOR
      case GASNETI_VIS_CAT_PUTI_GATHER:
        if (gasnete_try_syncnb(visop->handle) == GASNET_OK) { 
          GASNETE_VISOP_SIGNAL_AND_FREE(visop, 0);
        }
      break;
    #endif
    #ifdef GASNETE_GETI_SCATTER_SELECTOR
      case GASNETI_VIS_CAT_GETI_SCATTER:
        if (gasnete_try_syncnb(visop->handle) == GASNET_OK) {
          void * const * const savedlst = (void * const *)(visop + 1);
          void const * const packedbuf = savedlst + visop->count;
          gasnete_addrlist_unpack(visop->count, savedlst, visop->len, packedbuf, 0, (size_t)-1);
          GASNETE_VISOP_SIGNAL_AND_FREE(visop, 1);
        }
      break;
    #endif
    #ifdef GASNETE_PUTS_GATHER_SELECTOR
      case GASNETI_VIS_CAT_PUTS_GATHER:
        if (gasnete_try_syncnb(visop->handle) == GASNET_OK) { 
          GASNETE_VISOP_SIGNAL_AND_FREE(visop, 0);
        }
      break;
    #endif
    #ifdef GASNETE_GETS_SCATTER_SELECTOR
      case GASNETI_VIS_CAT_GETS_SCATTER:
        if (gasnete_try_syncnb(visop->handle) == GASNET_OK) {
          size_t stridelevels = visop->len;
          size_t * const savedstrides = (size_t *)(visop + 1);
          size_t * const savedcount = savedstrides + stridelevels;
          void * const packedbuf = (void *)(savedcount + stridelevels + 1);
          gasnete_strided_unpack_all(visop->addr, savedstrides, savedcount, stridelevels, packedbuf);
          GASNETE_VISOP_SIGNAL_AND_FREE(visop, 1);
        }
      break;
    #endif
      default: gasneti_fatalerror("unrecognized visop category: %i", visop->type);
    }
    lastp = &(visop->next); /* advance */
    visop_removed: ;
  }
  td->progressfn_active = 0;
}
示例#11
0
extern void gasnetc_barrier_fence(void)
{
    gasnet_mxm_send_req_t * sreqs;
    mxm_send_req_t * mxm_sreq;
    mxm_error_t mxm_res;
    int dest;

    sreqs = (gasnet_mxm_send_req_t *)
            alloca(sizeof(gasnet_mxm_send_req_t) * gasneti_nodes);

    for (dest = 0; dest < gasneti_nodes; dest++) {
        if (!gasnet_mxm_module.need_fence[dest])
            continue;
        if_pf (dest == gasneti_mynode)
        continue;
#if GASNET_PSHM
        if_pf (gasneti_pshm_in_supernode(dest))
        continue;
#endif
        mxm_sreq = &sreqs[dest].mxm_sreq;
#if MXM_API < MXM_VERSION(2,0)
        mxm_sreq->opcode = MXM_REQ_OP_FENCE;
        mxm_sreq->base.flags = MXM_REQ_FLAG_SEND_SYNC;
#else
        mxm_sreq->opcode = MXM_REQ_OP_PUT_SYNC;
        mxm_sreq->flags  = MXM_REQ_SEND_FLAG_FENCE;
        mxm_sreq->op.mem.remote_vaddr = 0;
        mxm_sreq->op.mem.remote_mkey  = &mxm_empty_mem_key;
#endif

        mxm_sreq->base.state = MXM_REQ_NEW;
        mxm_sreq->base.conn = gasnet_mxm_module.connections[dest];
        mxm_sreq->base.mq = gasnet_mxm_module.mxm_mq;

        mxm_sreq->base.data.buffer.ptr = NULL;
        mxm_sreq->base.data.buffer.length = 0;

#if MXM_API < MXM_VERSION(1,5)
        mxm_sreq->base.data.buffer.mkey = MXM_MKEY_NONE;
#else
        mxm_sreq->base.data.buffer.memh = NULL;
#endif
        mxm_sreq->base.data_type = MXM_REQ_DATA_BUFFER;

        mxm_sreq->base.completed_cb = NULL;
        mxm_sreq->base.context = NULL;

        mxm_res = mxm_req_send(mxm_sreq);
        if_pt (MXM_OK != mxm_res)
        gasneti_fatalerror("Error posting send request - %s\n",
                           mxm_error_string(mxm_res));
    }

    for (dest = 0; dest < gasneti_nodes; dest++) {
        if (!gasnet_mxm_module.need_fence[dest])
            continue;
        if_pf (dest == gasneti_mynode)
        continue;
#if GASNET_PSHM
        if_pf (gasneti_pshm_in_supernode(dest))
        continue;
#endif
        mxm_sreq = &sreqs[dest].mxm_sreq;

        /* we are waiting for real completion, not just for SENT state */
        while (!mxm_req_test(&mxm_sreq->base))
            gasnetc_AMPoll();

        gasnet_mxm_module.need_fence[dest] = 0;
    }
}
示例#12
0
/* Get the default algorithm for a given (geometery, collective) pair.
   This will be the first "always works" algorithm unless user provides an override.
*/
extern void
gasnetc_dflt_coll_alg(pami_geometry_t geom, pami_xfer_type_t op, pami_algorithm_t *alg_p) {
  static int print_once[PAMI_XFER_COUNT]; /* static var must initially be all zeros */
  pami_result_t rc;
  size_t counts[2];
  pami_algorithm_t *algorithms;
  pami_metadata_t *metadata;
  const char *envvar, *envval, *dfltval;
  int alg, fullcount;

  gasneti_assert(op >= 0);
  gasneti_assert(op < PAMI_XFER_COUNT);

  rc = PAMI_Geometry_algorithms_num(geom, op, counts);
  GASNETC_PAMI_CHECK(rc, "calling PAMI_Geometry_algorithms_num()");
  fullcount = counts[0] + counts[1];

  /* Space for algorithms and metadata */
  algorithms = alloca(fullcount * sizeof(pami_algorithm_t));
  metadata   = alloca(fullcount * sizeof(pami_metadata_t));

  rc = PAMI_Geometry_algorithms_query(geom, op,
                                      algorithms, metadata, counts[0],
                                      algorithms+counts[0], metadata+counts[0], counts[1]);
  GASNETC_PAMI_CHECK(rc, "calling PAMI_Geometry_algorithms_query()");

  /* Process environment and defaults: */
  switch(op) { /* please keep alphabetical */
  /* Used for blocking gasnet exchange: */
  case PAMI_XFER_ALLTOALL:
    envvar = "GASNET_PAMI_ALLTOALL_ALG";
  #if GASNETI_ARCH_BGQ
    dfltval = "I0:M2MComposite:MU:MU"; /* Best on BG/Q by a large margin */
  #else
    dfltval = "I0:Ring:"; /* Uniformly 2nd place (out of 3) on PERCS */
  #endif
    break;

  /* Used for blocking gasnet exchange w/ multiple images: */
  case PAMI_XFER_ALLTOALLV_INT:
    envvar = "GASNET_PAMI_ALLTOALLV_INT_ALG";
  #if GASNETI_ARCH_BGQ
    dfltval = "I0:M2MComposite:MU:MU"; /* Best on BG/Q by a large margin */
  #else
    dfltval = "I0:M2MComposite:"; /* Best on PERCS for all but smallest len (where it is close) */
  #endif
    break;

  /* Used for blocking gasnet gatherall and gasnetc_bootstrapExchange(): */
  case PAMI_XFER_ALLGATHER:
    envvar = "GASNET_PAMI_ALLGATHER_ALG";
  #if GASNETI_ARCH_BGQ && 0 /* TODO: split choice based on size */
    dfltval = "I0:RectangleDput:"; /* Uniformly best (or very near) for LARGE case only... */
    /* .. but only available for "rectangular" jobs. */
    alg = gasnetc_find_alg(dfltval, metadata, counts[0]);
    if (alg < counts[0]) break; /* Otherwise fall through */
  #endif
    dfltval = "I0:Binomial:"; /* Uniformly 2nd place (out of 3) on PERCS, uniformly "OK" on BG/Q */
    break;

  /* Used for blocking gasnet gatherall w/ multiple images: */
  case PAMI_XFER_ALLGATHERV_INT:
    envvar = "GASNET_PAMI_ALLGATHERV_INT_ALG";
  #if GASNETI_ARCH_BGQ && 0 /* TODO: split choice based on size */
    dfltval = "I0:RectangleDput:"; /* Uniformly best for small to moderate cases only ... */
    /* .. but only available for "rectangular" jobs. */
    alg = gasnetc_find_alg(dfltval, metadata, counts[0]);
    if (alg < counts[0]) break; /* Otherwise fall through */
  #endif
    dfltval = NULL; /* Only one other option available on systems I've tested -PHH */
    break;

  /* Used for exitcode reduction and "PAMIALLREDUCE" barrier: */
  case PAMI_XFER_ALLREDUCE:
    envvar = "GASNET_PAMI_ALLREDUCE_ALG";
  #if GASNETI_ARCH_BGQ
    dfltval = "I0:Binomial:-:ShortMU"; /* great when available */
    alg = gasnetc_find_alg(dfltval, metadata, fullcount);
    if (alg < fullcount) {
      /* make sure PAMI-allreduce barrier and exitcode reduction will "fit" */
      pami_metadata_t *md = &metadata[alg];
      if ((!md->check_correct.values.rangeminmax  || md->range_lo <= sizeof(int)) &&
          (!md->check_correct.values.rangeminmax  || md->range_hi >= 2*sizeof(uint64_t)) &&
          (!md->check_correct.values.sendminalign || md->send_min_align >= sizeof(char)) &&
          (!md->check_correct.values.recvminalign || md->recv_min_align >= sizeof(char))) {
        break; /* Otherwise fall through */
      }
    }
    dfltval = "I1:ShortAllreduce:"; /* excellent second choice on BG/Q */
    alg = gasnetc_find_alg(dfltval, metadata, fullcount);
    if (alg < fullcount) {
      /* make sure PAMI-allreduce barrier and exitcode reduction will "fit" */
      pami_metadata_t *md = &metadata[alg];
      if ((!md->check_correct.values.rangeminmax  || md->range_lo <= sizeof(int)) &&
          (!md->check_correct.values.rangeminmax  || md->range_hi >= 2*sizeof(uint64_t)) &&
          (!md->check_correct.values.sendminalign || md->send_min_align >= sizeof(char)) &&
          (!md->check_correct.values.recvminalign || md->recv_min_align >= sizeof(char))) {
        break; /* Otherwise fall through */
      }
    }
  #endif
    dfltval = "I0:Binomial:"; /* uniformly "good" on BG/Q and PERCS */
    break;

  /* Used for gasnetc_fast_barrier() and GASNET_BARRIERFLAG_UNNAMED */
  case PAMI_XFER_BARRIER:
    envvar = "GASNET_PAMI_BARRIER_ALG";
  #if GASNETI_ARCH_BGQ
    /* Note: this could be any of
     *     "I0:MultiSync2Device:SHMEM:GI"
     *     "I0:MultiSync:SHMEM:-",
     *     "I0:MultiSync:-:GI",
     * depending on job layout, and may not be available on team != ALL.
     */
    dfltval = "I0:MultiSync";
    alg = gasnetc_find_alg(dfltval, metadata, counts[0]);
    if (alg < counts[0]) break; /* Otherwise fall through */
  #endif
    dfltval = NULL; /* TODO: tune a better default than alg[0]? */
    break;

  /* Used for blocking gasnet broadcast: */
  case PAMI_XFER_BROADCAST:
    envvar = "GASNET_PAMI_BROADCAST_ALG";
  #if GASNETI_ARCH_BGQ
    dfltval = "I0:2-nary:"; /* uniformly "near-best" on BG/Q */
  #else
   #if 0 /* Seen to deadlock when using multiple procs/node */
    dfltval = "I0:4-nary:"; /* uniformly "near-best" on PERSC */
   #else
    dfltval = NULL; /* TODO: tune for better default or wait for bug fix */
   #endif
  #endif
    break;

  /* Used for blocking gasnet gather: */
  case PAMI_XFER_GATHER:
    envvar = "GASNET_PAMI_GATHER_ALG";
    dfltval = NULL; /* TODO: tune for better default */
    break;

  /* Used for blocking gasnet gather w/ multiple images: */
  case PAMI_XFER_GATHERV_INT:
    envvar = "GASNET_PAMI_GATHERV_INT_ALG";
    dfltval = NULL; /* TODO: tune for better default */
    break;

  /* Used for blocking gasnet scatter: */
  case PAMI_XFER_SCATTER:
    envvar = "GASNET_PAMI_SCATTER_ALG";
    dfltval = "I0:Binomial:"; /* uniformly "good" on BG/Q and PERSC */
    break;

  /* Used for blocking gasnet scatter w/ multiple images: */
  case PAMI_XFER_SCATTERV_INT:
    envvar = "GASNET_PAMI_SCATTERV_INT_ALG";
    dfltval = NULL; /* TODO: tune for better default */
    break;

  default:
    gasneti_fatalerror("Unknown 'op' value %d in %s", (int)op, __FUNCTION__);
    envvar = dfltval = NULL; /* for warning suppression only */
  }
  /* Override the defaults above for the single-task case: */
  if (gasneti_nodes == 1) {
    const char *onetask = "I0:OneTask";
    if (gasnetc_find_alg(onetask, metadata, counts[0]) < counts[0]) {
      dfltval = onetask;
    }
  }
  /* Now the user's environment value if any: */
  envval = gasneti_getenv_withdefault(envvar, dfltval);
  alg = 0; /* failsafe */
  if (NULL != envval) {
    while (envval[0] && isspace(envval[0])) ++envval; /* leading whitespace */
    if (!envval[0]) {
      /* empty - treat as zero */
    } else if (0 == strcmp("LIST", envval)) {
      if (!gasneti_mynode && !print_once[(int)op]) {
        int i;
        fprintf(stderr, "Listing available values for environment variable %s:\n", envvar);
        for (i=0; i<fullcount; ++i) {
          fprintf(stderr, " %c %3d %s\n", ((i<counts[0])?' ':'*'), i, metadata[i].name);
        }
        if (counts[1]) {
          fprintf(stderr,
                  "Note: Lines marked with '*' may not be valid for all inputs and/or job layouts.\n"
                  "      The user is responsible for ensuring only valid algorithms are requested.\n"
                 );
        }
        print_once[(int)op] = 1;
      }
    } else if (isdigit(envval[0])) {
      /* integer is used just as given */
      alg = atoi(envval);
      if (alg < 0 || alg >= fullcount) {
        if (!gasneti_mynode && !print_once[(int)op]) {
          fprintf(stderr, "WARNING: Ignoring value '%d' for environment variable %s,\n"
                          "         because it is outside the range of available algorithms.\n"
                          "         Set this variable to LIST for a list of all algorithms.\n",
                           alg, envvar);
          print_once[(int)op] = 1;
        }
        alg = 0;
      }
    } else {
      /* string is used for PREFIX match */
      alg = gasnetc_find_alg(envval, metadata, fullcount);
      if (alg == fullcount) {
        if (!gasneti_mynode && !print_once[(int)op] && (envval != dfltval)) {
          fprintf(stderr, "WARNING: Ignoring value '%s' for environment variable %s,\n"
                          "         because it does not match any available algorithm.\n"
                          "         Set this variable to LIST for a list of all algorithms.\n",
                           envval, envvar);
          print_once[(int)op] = 1;
        }
        alg = 0;
      }
    }
  }

  *alg_p = algorithms[alg];
}
示例#13
0
static int gasnetc_init(int *argc, char ***argv, gex_Flags_t flags) {
  int retval = GASNET_OK;

  /*  check system sanity */
  gasnetc_check_config();

  /* --------- begin Master code ------------ */
  if (!AMUDP_SPMDIsWorker(argv?*argv:NULL)) {
    /* assume we're an implicit master 
       (we don't currently support explicit workers spawned 
        without using the AMUDP SPMD API)   
     */
    int num_nodes;
    int i;
    char spawnfn;
    amudp_spawnfn_t fp = (amudp_spawnfn_t)NULL;

    if (!argv) {
      gasneti_fatalerror("implicit-master without argv not supported - use amudprun");
    }

    /* pretend we're node 0, for purposes of verbose env reporting */
    gasneti_init_done = 1;
    gasneti_mynode = 0;

    #if defined(GASNET_CSPAWN_CMD)
    { /* set configure default cspawn cmd */
      const char *cmd = gasneti_getenv_withdefault("GASNET_CSPAWN_CMD",GASNET_CSPAWN_CMD);
      gasneti_setenv("GASNET_CSPAWN_CMD",cmd);
    }
    #endif

    /* parse node count from command line */
    if (*argc < 2) {
      fprintf(stderr, "GASNet: Missing parallel node count\n");
      fprintf(stderr, "GASNet: Specify node count as first argument, or use upcrun/tcrun spawner script to start job\n");
      fprintf(stderr, "GASNet: Usage '%s <num_nodes> {program arguments}'\n", (*argv)[0]);
      exit(-1);
    }
    /*
     * argv[1] is number of nodes; argv[0] is program name; argv is
     * list of arguments including program name and number of nodes.
     * We need to remove argv[1] when the argument array is passed
     * to the tic_main().
     */
    num_nodes = atoi((*argv)[1]);
    if (num_nodes < 1) {
      fprintf (stderr, "GASNet: Invalid number of nodes: %s\n", (*argv)[1]);
      fprintf (stderr, "GASNet: Usage '%s <num_nodes> {program arguments}'\n", (*argv)[0]);
      exit (1);
    }

    /* remove the num_nodes argument */
    for (i = 1; i < (*argc)-1; i++) {
      (*argv)[i] = (*argv)[i+1];
    }
    (*argv)[(*argc)-1] = NULL;
    (*argc)--;

    /* get spawnfn */
    spawnfn = *gasneti_getenv_withdefault("GASNET_SPAWNFN", _STRINGIFY(GASNETC_DEFAULT_SPAWNFN));

    { /* ensure we pass the effective spawnfn to worker env */
      char spawnstr[2];
      spawnstr[0] = toupper(spawnfn);
      spawnstr[1] = '\0';
      gasneti_setenv("GASNET_SPAWNFN",spawnstr);
    }

    /* ensure reliable localhost operation by forcing use of 127.0.0.1
     * setting GASNET_MASTERIP to the empty string will prevent this */
    if (('L' == toupper(spawnfn)) && !gasneti_getenv("GASNET_MASTERIP")) {
      gasneti_setenv("GASNET_MASTERIP","127.0.0.1");
    }

    for (i=0; AMUDP_Spawnfn_Desc[i].abbrev; i++) {
      if (toupper(spawnfn) == toupper(AMUDP_Spawnfn_Desc[i].abbrev)) {
        fp = AMUDP_Spawnfn_Desc[i].fnptr;
        break;
      }
    }

    if (!fp) {
      fprintf (stderr, "GASNet: Invalid spawn function specified in GASNET_SPAWNFN\n");
      fprintf (stderr, "GASNet: The following mechanisms are available:\n");
      for (i=0; AMUDP_Spawnfn_Desc[i].abbrev; i++) {
        fprintf(stderr, "    '%c'  %s\n",  
              toupper(AMUDP_Spawnfn_Desc[i].abbrev), AMUDP_Spawnfn_Desc[i].desc);
      }
      exit(1);
    }

    #if GASNET_DEBUG_VERBOSE
      /* note - can't call trace macros during gasnet_init because trace system not yet initialized */
      fprintf(stderr,"gasnetc_init(): about to spawn...\n"); fflush(stderr);
    #endif

    retval = AMUDP_SPMDStartup(argc, argv, 
      num_nodes, 0, fp,
      NULL, &gasnetc_bundle, &gasnetc_endpoint);
    /* master startup should never return */
    gasneti_fatalerror("master AMUDP_SPMDStartup() failed");
  }

  /* --------- begin Worker code ------------ */
  AMLOCK();
    if (gasneti_init_done) 
      INITERR(NOT_INIT, "GASNet already initialized");

    gasneti_freezeForDebugger();

    AMX_VerboseErrors = gasneti_VerboseErrors;
    AMUDP_SPMDkillmyprocess = gasneti_killmyprocess;

#if GASNETI_CALIBRATE_TSC
    // Early x86*/Linux timer initialization before AMUDP_SPMDStartup()
    //
    // udp-conduit does not support user-provided values for GASNET_TSC_RATE*
    // (which fine-tune timer calibration on x86/Linux).  This is partially due
    // to a dependency cycle at startup with envvar propagation, but more
    // importantly because the retransmission algorithm (and hence all conduit
    // comms) rely on gasnet timers to be accurate (at least approximately), so
    // we don't allow the user to weaken or disable their calibration.
    gasneti_unsetenv("GASNET_TSC_RATE");
    gasneti_unsetenv("GASNET_TSC_RATE_TOLERANCE");
    gasneti_unsetenv("GASNET_TSC_RATE_HARD_TOLERANCE");
    GASNETI_TICKS_INIT();
#endif

    /*  perform job spawn */
    retval = AMUDP_SPMDStartup(argc, argv, 
      0, 0, NULL, /* dummies */
      &gasnetc_networkpid, &gasnetc_bundle, &gasnetc_endpoint);
    if (retval != AM_OK) INITERR(RESOURCE, "slave AMUDP_SPMDStartup() failed");
    gasneti_init_done = 1; /* enable early to allow tracing */

    gasneti_getenv_hook = (/* cast drops const */ gasneti_getenv_fn_t*)&AMUDP_SPMDgetenvMaster;
    gasneti_mynode = AMUDP_SPMDMyProc();
    gasneti_nodes = AMUDP_SPMDNumProcs();

#if !GASNETI_CALIBRATE_TSC
    /* Must init timers after global env, and preferably before tracing */
    GASNETI_TICKS_INIT();
#endif

    /* enable tracing */
    gasneti_trace_init(argc, argv);
    GASNETI_AM_SAFE(AMUDP_SPMDSetExitCallback(gasnetc_traceoutput));

    /* for local spawn, assume we want to wait-block */
    if (gasneti_getenv("GASNET_SPAWNFN") && *gasneti_getenv("GASNET_SPAWNFN") == 'L') { 
      GASNETI_TRACE_PRINTF(C,("setting gasnet_set_waitmode(GASNET_WAIT_BLOCK) for localhost spawn"));
      gasnet_set_waitmode(GASNET_WAIT_BLOCK);
    }

    #if GASNET_DEBUG_VERBOSE
      fprintf(stderr,"gasnetc_init(): spawn successful - node %i/%i starting...\n", 
        gasneti_mynode, gasneti_nodes); fflush(stderr);
    #endif

    gasneti_nodemapInit(&gasnetc_bootstrapExchange, NULL, 0, 0);

    #if GASNET_PSHM
      gasneti_pshm_init(&gasnetc_bootstrapSNodeBroadcast, 0);
    #endif

    uintptr_t mmap_limit;
    #if HAVE_MMAP
      mmap_limit = gasneti_mmapLimit((uintptr_t)-1, (uint64_t)-1,
                                  &gasnetc_bootstrapExchange,
                                  &gasnetc_bootstrapBarrier);
    #else
      // TODO-EX: we can at least look at rlimits but such logic belongs in conduit-indep code
      mmap_limit = (intptr_t)-1;
    #endif

    /* allocate and attach an aux segment */

    gasneti_auxsegAttach(mmap_limit, &gasnetc_bootstrapExchange);

    /* determine Max{Local,GLobal}SegmentSize */
    gasneti_segmentInit(mmap_limit, &gasnetc_bootstrapExchange, flags);

    #if GASNET_BLCR
      gasneti_checkpoint_guid = gasnetc_networkpid;
      gasneti_checkpoint_init(NULL);
    #endif

  AMUNLOCK();

  gasneti_assert(retval == GASNET_OK);
  return retval;

done: /*  error return while locked */
  AMUNLOCK();
  GASNETI_RETURN(retval);
}
示例#14
0
/* gasneti_bootstrapInit
 */
int gasneti_bootstrapInit_pmi(
        int *argc_p, char ***argv_p,
        gasnet_node_t *nodes_p, gasnet_node_t *mynode_p) {
    int size, rank;

#if USE_PMI2_API
    int spawned, appnum;
    if (PMI2_SUCCESS != PMI2_Init(&spawned, &size, &rank, &appnum)) {
        return GASNET_ERR_NOT_INIT;
    }
#else
    if (PMI_SUCCESS != PMI_Initialized(&gasneti_pmi_initialized)) {
        return GASNET_ERR_NOT_INIT;
    }

    if (PMI_FALSE == gasneti_pmi_initialized) {
        int spawned;
        if (PMI_SUCCESS != PMI_Init(&spawned)) {
            return GASNET_ERR_NOT_INIT;
        }
    }

    if (PMI_SUCCESS != PMI_Get_rank(&rank)) {
        gasneti_fatalerror("PMI_Get_rank() failed");
    }

    if (PMI_SUCCESS != PMI_Get_size(&size)) {
        gasneti_fatalerror("PMI_Get_size() failed");
    }
#endif

    *mynode_p = rank;
    *nodes_p = size;

#if USE_PMI2_API
    max_name_len = 1024; /* XXX: can almost certainly be shorter than this! */
    max_key_len = PMI2_MAX_KEYLEN;
    max_val_len = PMI2_MAX_VALLEN;
#else
    if (PMI_SUCCESS != PMI_KVS_Get_name_length_max(&max_name_len)) {
        gasneti_fatalerror("PMI_KVS_Get_name_length_max() failed");
    }
    if (PMI_SUCCESS != PMI_KVS_Get_key_length_max(&max_key_len)) {
        gasneti_fatalerror("PMI_KVS_Get_key_length_max() failed");
    }
    if (PMI_SUCCESS != PMI_KVS_Get_value_length_max(&max_val_len)) {
        gasneti_fatalerror("PMI_KVS_Get_value_length_max() failed");
    }
#endif

    kvs_name = (char*) gasneti_malloc(max_name_len);
    kvs_key = (char*) gasneti_malloc(max_key_len);
    kvs_value = (char*) gasneti_malloc(max_val_len);
    max_val_bytes = 4 * (max_val_len / 5);

#if USE_PMI2_API
    if (PMI2_SUCCESS != PMI2_Job_GetId(kvs_name, max_name_len)) {
        gasneti_fatalerror("PMI2_Job_GetId() failed");
    }
#else
    if (PMI_SUCCESS != PMI_KVS_Get_my_name(kvs_name, max_name_len)) {
        gasneti_fatalerror("PMI_KVS_Get_my_name() failed");
    }
#endif

    return GASNET_OK;
}
extern
int 
firehose_move_callback(gasnet_node_t node, 
		const firehose_region_t *unpin_list, size_t unpin_num, 
		firehose_region_t *pin_list, size_t pin_num)
{
	int	 i;
	int	locked = GASNETE_GM_IN_UNKNOWN();
	gm_status_t status;

	if (!locked)
		gasneti_mutex_lock(&gasnetc_lock_gm);

	for (i = 0; i < unpin_num; i++) {
		gasneti_assert(unpin_list[i].addr % GASNET_PAGESIZE == 0);
		gasneti_assert(unpin_list[i].len % GASNET_PAGESIZE == 0);
		status = gm_deregister_memory(_gmc.port, 
			  (void *) unpin_list[i].addr, unpin_list[i].len);
		if (status != GM_SUCCESS) 
		    gasneti_fatalerror("gm_deregister_memory() failed for "
		       "page located at %p (%s)", (void*)unpin_list[i].addr, 
		       gm_strerror(status));
		GASNETI_TRACE_PRINTF(C,
		  ("Firehose unpinlocal = %p, %d", (void *) unpin_list[i].addr,
			(int)unpin_list[i].len));
	}
	GASNETI_TRACE_EVENT_VAL(C, FIREHOSE_LOCALUNPIN_PAGES, unpin_num);

	for (i = 0; i < pin_num; i++) {
                int perm_adj = 0;
              retry_register:
		gasneti_assert(pin_list[i].addr % GASNET_PAGESIZE == 0);
		gasneti_assert(pin_list[i].len % GASNET_PAGESIZE == 0);
		status = gm_register_memory(_gmc.port, (void *)
				pin_list[i].addr, pin_list[i].len);
		if (status != GM_SUCCESS) {
                  if (perm_adj) {
		    gasneti_fatalerror("gm_register_memory() failed for "
		       "page located at %p (%s)", (void*)pin_list[i].addr, 
		       gm_strerror(status));
                  } else { /* bug 1036 - GM cannot register read-only data memory */
                    int j, num_pages = pin_list[i].len / GASNET_PAGESIZE;
                    char *p;
                    static char tst = 0;
                    /* check for readability before we mess with mprotect */
		    GASNETI_TRACE_PRINTF(C,("gm_register_memory() failed for "
		       "page located at %p len=%i pages (%s) -- checking readability", 
                       (void*)pin_list[i].addr, num_pages, gm_strerror(status)));
                    p = (void *)pin_list[i].addr;
                    for (j = 0 ; j < num_pages; j++) {
                      tst += *p; /* if you get a seg fault here, it means firehose tried to register unmapped memory */
                      p += GASNET_PAGESIZE;
                    }
                    p = (void *)pin_list[i].addr;
                    for (j = 0 ; j < num_pages; j++) {
		      GASNETI_TRACE_PRINTF(C,("Attempting mprotect for page located at %p", (void*)p));
                      if (mprotect(p, GASNET_PAGESIZE, PROT_READ|PROT_WRITE))
                        gasneti_fatalerror("mprotect failed in firehose_move_callback: %s", strerror(errno));
                      p += GASNET_PAGESIZE;
                    }
                    perm_adj = 1;
                    goto retry_register;
                  }
                }
		GASNETI_TRACE_PRINTF(C,
		  ("Firehose pinlocal = %p, %d", (void *) pin_list[i].addr,
			(int)pin_list[i].len));
	}
	GASNETI_TRACE_EVENT_VAL(C, FIREHOSE_LOCALPIN_PAGES, pin_num);

	if (!locked)
		gasneti_mutex_unlock(&gasnetc_lock_gm);

	return 0;
}
示例#16
0
/*this fucntion is already serialized in the function that calls this 
  so from here on out there is no worry about locking*/
gasnete_coll_local_tree_geom_t *gasnete_coll_tree_geom_create_local(gasnete_coll_tree_type_t in_type, int rootrank, gasnete_coll_team_t team, gasnete_coll_tree_geom_t *base_geom)  {
  gasnete_coll_local_tree_geom_t *geom;
  int i;
  gasnete_coll_tree_type_t intype_copy;
  tree_node_t *allnodes = (tree_node_t*) team->tree_construction_scratch;
  tree_node_t rootnode,mynode;
  gasneti_assert(rootrank<team->total_ranks && rootrank >=0);
  gasneti_assert_always(in_type);
  intype_copy = in_type;
  geom = (gasnete_coll_local_tree_geom_t*)gasneti_malloc(sizeof(gasnete_coll_local_tree_geom_t));
  gasneti_assert_always(in_type==intype_copy);
  
  switch (in_type->tree_class) {
#if 1
  case GASNETE_COLL_NARY_TREE:
      gasneti_assert(in_type->num_params ==1);
      allnodes =  allocate_nodes((tree_node_t**) &team->tree_construction_scratch, team, rootrank);
      rootnode = make_nary_tree(allnodes, team->total_ranks, in_type->params[0]);
       geom->rotation_points = (int*) gasneti_malloc(sizeof(int)*1);
       geom->num_rotations = 1;
       geom->rotation_points[0] = rootrank;
      break;
    case GASNETE_COLL_KNOMIAL_TREE:
      gasneti_assert(in_type->num_params ==1);
       allnodes = allocate_nodes((tree_node_t**) &team->tree_construction_scratch, team, rootrank);
      rootnode = make_knomial_tree(allnodes, team->total_ranks, in_type->params[0]);
       geom->rotation_points = (int*) gasneti_malloc(sizeof(int)*1);
       geom->num_rotations = 1;
       geom->rotation_points[0] = rootrank;
      break;
    case GASNETE_COLL_FLAT_TREE:
      allocate_nodes((tree_node_t**) &team->tree_construction_scratch , team, rootrank);
      rootnode = make_flat_tree(team->tree_construction_scratch, team->total_ranks);
      geom->rotation_points = (int*) gasneti_malloc(sizeof(int)*1);
      geom->num_rotations = 1;
      geom->rotation_points[0] = rootrank;
      break;
    case GASNETE_COLL_RECURSIVE_TREE:
      gasneti_assert(in_type->num_params ==1);
      allnodes = allocate_nodes((tree_node_t**) &team->tree_construction_scratch, team, rootrank);
      rootnode = make_recursive_tree(allnodes, team->total_ranks, in_type->params[0]);
      geom->rotation_points = (int*) gasneti_malloc(sizeof(int)*1);
      geom->num_rotations = 1;
      geom->rotation_points[0] = rootrank;
      break;
    case GASNETE_COLL_FORK_TREE:
      allnodes = allocate_nodes((tree_node_t**) &team->tree_construction_scratch, team, rootrank);
      rootnode = make_fork_tree(allnodes, team->total_ranks, in_type->params, in_type->num_params);
       geom->rotation_points = (int*) gasneti_malloc(sizeof(int)*1);
       geom->num_rotations = 1;
       geom->rotation_points[0] = rootrank;
      break;
    case GASNETE_COLL_HIERARCHICAL_TREE:
#if 0
      allnodes = team->tree_construction_scratch = allocate_nodes(allnodes, team, 0);
      rootnode = make_hiearchical_tree(in_type, allnodes, team->total_ranks);
       /* XXX ADD CODE TO GET ROTATION POINTS*/
      break;
#else
       gasneti_fatalerror("HIERARCHICAL_TREE not yet fully supported");
#endif
#endif
    default:
       gasneti_fatalerror("unknown tree type");
      break;
  }
  
  rootnode = setparents(rootnode);
  mynode = find_node(rootnode, team->myrank);

  geom->root = rootrank;
  geom->tree_type = in_type;
  geom->total_size = team->total_ranks;
  geom->parent = GET_PARENT_ID(mynode);
  geom->child_count = GET_NUM_CHILDREN(mynode);
  geom->mysubtree_size = treesize(mynode);
  geom->parent_subtree_size = treesize(mynode->parent);
  geom->children_reversed = mynode->children_reversed;
  if(rootrank != team->myrank) {
    geom->num_siblings = GET_NUM_CHILDREN(mynode->parent);
    geom->sibling_id = -1;
    geom->sibling_offset = 0;
    for(i=0; i<geom->num_siblings; i++) {
      int tmp_id;
      if(mynode->parent->children_reversed==1) {
        tmp_id = geom->num_siblings-1-i;
      } else {
        tmp_id =i;
      }
      if(GET_NODE_ID(GET_CHILD_IDX(mynode->parent, tmp_id))==team->myrank) {
        geom->sibling_id = tmp_id;
        break;
      } else {
        geom->sibling_offset += treesize(GET_CHILD_IDX(mynode->parent, tmp_id));
      }
    }
  } else {
    geom->num_siblings = 0;
    geom->sibling_id = 0;
    geom->sibling_offset = 0;
    /***** THIS NEEDS TO BE TAKEN OUT
      The DFS ordering that we impose on the trees will mean that this no longer needs to be kept around
      but it's in here for now for backward compatability sake until we make the neccessary changes to all the other collective algorithms
      ****/
    geom->dfs_order = (gasnet_node_t*) gasneti_malloc(sizeof(gasnet_node_t)*team->total_ranks);
    for(i=0; i<team->total_ranks; i++) {
      geom->dfs_order[i] = (i+rootrank)%team->total_ranks;
    }
  }
  geom->seq_dfs_order = 1;
  geom->child_list = (gasnet_node_t*) gasneti_malloc(sizeof(gasnet_node_t)*geom->child_count);
  geom->subtree_sizes = (gasnet_node_t*) gasneti_malloc(sizeof(gasnet_node_t)*geom->child_count);
  geom->child_offset = (gasnet_node_t*) gasneti_malloc(sizeof(gasnet_node_t)*geom->child_count);
  geom->grand_children = (gasnet_node_t*)gasneti_malloc(sizeof(gasnet_node_t)*geom->child_count); 
  geom->num_non_leaf_children=0;
  geom->num_leaf_children=0;
  geom->child_contains_wrap = 0;
  for(i=0; i<geom->child_count; i++) {
    geom->child_list[i] = GET_NODE_ID(GET_CHILD_IDX(mynode,i));
    geom->subtree_sizes[i] = treesize(GET_CHILD_IDX(mynode,i));
    geom->grand_children[i] = GET_NUM_CHILDREN(GET_CHILD_IDX(mynode, i));
    if(geom->subtree_sizes[i] > 1) {
      geom->num_non_leaf_children++;
    } else {
      geom->num_leaf_children++;
    }
    if(geom->child_list[i]+geom->subtree_sizes[i] > geom->total_size) {
      geom->child_contains_wrap = 1;
    }
    
  }
  gasneti_assert((geom->num_leaf_children+geom->num_non_leaf_children) == geom->child_count);
  
  if(mynode->children_reversed==1) {
    size_t temp_offset = 0;
    for(i=geom->child_count-1; i>=0; i--) {
      geom->child_offset[i] = temp_offset; 
      temp_offset+=geom->subtree_sizes[i];
    }
  } else {
    size_t temp_offset = 0;
    for(i=0; i<geom->child_count; i++) {
      geom->child_offset[i] = temp_offset; 
      temp_offset+=geom->subtree_sizes[i];
    }
  }

#if 0
  /* Not using the reference counts for now */
  gasneti_weakatomic_set(&(geom->ref_count), 0, 0);
  geom->base_geom = base_geom;
#endif

#if 0  
  gasnete_coll_print_tree(geom, gasneti_mynode);
#endif
  return geom;
}