/* fh_hash_create(keylen,entries) * * Allocates a table large enough to hold 'entries' entries of size 'keylen'. * Note that 'entries' must be a power of two. */ static fh_hash_t * fh_hash_create(size_t entries) { fh_hash_t *hash; if (!IS_POWER_OF_2(entries)) gasneti_fatalerror("fh_hash_create requires a power of 2!"); hash = (fh_hash_t *) gasneti_malloc(sizeof(fh_hash_t)); if (hash == NULL) gasneti_fatalerror("Can't allocate memory for hash structure"); memset(hash, 0, sizeof(fh_hash_t)); hash->fh_table = (void **) gasneti_calloc(entries, sizeof(void *)); hash->fh_mask = entries-1; hash->fh_entries = entries; #ifdef FH_HASH_STATS hash->fh_col_table = (int *) gasneti_malloc(entries * sizeof(int)); /*printf("hash create: entries=%d, mask=%x\n", entries, entries-1);*/ hash->fh_used = 0; hash->fh_collisions = 0; #endif return hash; }
static int split_string(char ***split_strs, char *str, char *delim) { char *temp=NULL,*copy; int ret=0; size_t malloc_len = 8; static gasneti_mutex_t lock= GASNETI_MUTEX_INITIALIZER; copy = gasneti_malloc(sizeof(char)*(strlen(str)+1)); /*since the strtok function is desructive we have to create a copy of the string first to preserve the orignal*/ GASNETE_FAST_UNALIGNED_MEMCPY_CHECK(copy, str, sizeof(char)*(strlen(str)+1)); gasneti_mutex_lock(&lock); *split_strs = (char **) gasneti_malloc(sizeof(char*) * malloc_len); temp = strtok(copy, delim); while(temp != NULL) { if(ret == malloc_len) { /*we've run out of space so grow the array by another factor*/ malloc_len +=malloc_len; *split_strs = (char**) gasneti_realloc(*split_strs, sizeof(char*) * malloc_len); gasneti_fatalerror("more than 8 params not yet supported"); } (*split_strs)[ret] = temp; ret++; temp=strtok(NULL, delim); } *split_strs = (char**) gasneti_realloc(*split_strs, sizeof(char*) * ret); gasneti_mutex_unlock(&lock); return ret; }
/* Prepare the checkpoint directory, optionally choosing it as well. * * If the 'dir' argument is non-NULL, it is used as the checkpoint directory and * is also the return value. Otherwise the default directory name is chosen (as * described below) and its name (in malloced memory) is returned. * * Regardles of whether the directory name is caller-provided or default, the * directory is prepared as follows: * + The directory and all parents are created if they did not already exist. * + A 'metadata' file is created, storing info useful at restart time. * * Default checkpoint directory names are of the form * [jobdir]/[sequence] * where * [jobdir] is one of the following (the first w/o an undefined variable): * 1. ${GASNET_CHECKPOINT_JOBDIR} * 2. ${GASNET_CHECKPOINT_BASEDIR}/[guid_hi].[guid_lo] * 3. ${HOME}/gasnet-checkpoint/[guid_hi].[guid_lo] * and * [sequence] is a decimal integer (increased on each call). * * NOT thread-safe (but neither is checkpoint initiation). */ extern const char *gasneti_checkpoint_dir(const char *dir) { char *filename; if (!dir) { size_t len = strlen(gasneti_checkpoint_jobdir) + 12; /* 12 = "/0123456789\0" */ char *tmp = gasneti_malloc(len); snprintf(tmp, len, "%s/%d", gasneti_checkpoint_jobdir, gasneti_checkpoint_sequence++); dir = tmp; } /* Make a copy of 'dir' which we can write to as needed */ filename = gasneti_malloc(10 + strlen(dir)); /* 10 = "/metadata\0" */ strcpy(filename, dir); { /* The following implements "mkdir -p" (and needs to write to filename) */ char *p = filename; int rc; do { p = strchr(p+1, '/'); if (p) { *p = '\0'; } rc = mkdir(filename, S_IRWXU); if ((rc < 0) && (errno != EEXIST)) { gasneti_fatalerror("Failed to mkdir('%s') %d:%s\n", filename, errno, strerror(errno)); /* BLCR-TODO: error recovery */ } if (p) { *p = '/'; } } while (p); } /* Create metadata file. * Since every process tries, we get one copy per filesystem. */ strcat(filename, "/metadata"); { /* Want O_EXCL, but not available directly via fopen() */ int fd = open(filename, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR); if (fd >= 0) { FILE *md = fdopen(fd, "w"); if (md) { /* BLCR-TODO: error detection or silent failure for fwrite() or fclose()? */ fprintf(md, "argv0:\t%s\n", gasneti_exename); fprintf(md, "nproc:\t%d\n", gasneti_nodes); fprintf(md, "guid:\t%08x.%08x\n", GASNETI_HIWORD(gasneti_checkpoint_guid), GASNETI_LOWORD(gasneti_checkpoint_guid)); fprintf(md, "time:\t%lu\n", (unsigned long)time(NULL)); fclose(md); } else { gasneti_fatalerror("Failed to fdopen file '%s' %d:%s\n", filename, errno, strerror(errno)); } } else if (errno != EEXIST) { gasneti_fatalerror("Failed to create file '%s' %d:%s\n", filename, errno, strerror(errno)); } } gasneti_free(filename); return dir; }
extern void gasneti_checkpoint_init(gasneti_bootstrapBroadcastfn_t bcast_fn) { /* Initialize the GUID if the conduit has not already set a non-zero value */ if (!gasneti_checkpoint_guid) { if (! gasneti_mynode) { gasneti_checkpoint_guid = gasneti_checkpoint_mkguid(); } bcast_fn(&gasneti_checkpoint_guid, sizeof(uint64_t), &gasneti_checkpoint_guid, 0); } /* Enforce use of absolute paths */ { char *val; if (NULL != (val = gasneti_getenv("GASNET_CHECKPOINT_JOBDIR"))) { if ('/' != val[0]) { gasneti_fatalerror("Environment variable GASNET_CHECKPOINT_JOBDIR='%s' is not an absolute path", val); } else { gasneti_checkpoint_jobdir = val; } } else { char *dir; size_t len; if (NULL != (val = gasneti_getenv("GASNET_CHECKPOINT_BASEDIR"))) { if ('/' != val[0]) { gasneti_fatalerror("Environment variable GASNET_CHECKPOINT_BASEDIR='%s' is not an absolute path", val); } else { dir = val; } } else { if (NULL != (val = gasneti_getenv("HOME"))) { if ('/' != val[0]) { gasneti_fatalerror("Environment variable HOME='%s' is not an absolute path", val); } else { const char *rest = "/gasnet-checkpoint"; len = strlen(val) + strlen(rest) + 1; dir = gasneti_malloc(len); strcpy(dir, val); strcat(dir, rest); } } else { gasneti_fatalerror("Environment variable HOME is not set"); } } len = strlen(dir) + 19; /* 19 = 16 digits, '/' , '.' and '\0' */ gasneti_checkpoint_jobdir = gasneti_malloc(len); gasneti_leak(gasneti_checkpoint_jobdir); snprintf(gasneti_checkpoint_jobdir, len, "%s/%08x.%08x", dir, GASNETI_HIWORD(gasneti_checkpoint_guid), GASNETI_LOWORD(gasneti_checkpoint_guid)); if (dir != val) gasneti_free(dir); } } }
static gasnete_coll_dissem_info_t *gasnete_coll_build_dissemination(int r, gasnete_coll_team_t team) { gasnete_coll_dissem_info_t *ret; int h,w,i,j,distance,x,numpeers,destproc; int num_out_peers, num_in_peers; ret = (gasnete_coll_dissem_info_t*) gasneti_malloc(sizeof(gasnete_coll_dissem_info_t)); w = gasnete_coll_build_tree_mylogn(team->total_ranks, r); ret->dissemination_radix = r; ret->dissemination_phases = w; distance = 1; /* phase 2: communication in log_r(team->total_ranks) steps*/ for(i=0; i<w; i++) { if(i==(w-1)) { /*h = ceil(team->total_ranks/DIST);*/ h = team->total_ranks/distance; if(team->total_ranks % distance != 0) h++; } else { h = r; } ret->exchange_order[i].n = h-1; ret->exchange_order[i].elem_list = (gasnet_node_t*) gasneti_malloc(sizeof(gasnet_node_t)*(h-1)); for(j=1; j<h; j++) { ret->barrier_order[i].elem_list[j-1] = (team->myrank + j*distance) % team->total_ranks; } /*scale the distance by the radix*/ distance *= r; } /*simulate the packing step and figure out what is the maxiumum number of blocks that come in across all the nodes*/ ret->max_dissem_blocks =MAX(1,(team->total_ranks/ret->dissemination_radix)); for(i=0; i<w; i++) { int curr_count = 0; for(j=0; j<team->total_ranks; j++) { if( ((j / gasnete_coll_build_tree_mypow(ret->dissemination_radix, i)) % ret->dissemination_radix) == 1) curr_count++; } ret->max_dissem_blocks=MAX(ret->max_dissem_blocks, curr_count); } return ret; }
myxml_node_t *myxml_createNode_attr_list(myxml_node_t* parent, const char *tag, const char **attribute_list, const char **attribute_vals, int num_attributes, const char *value) { int i; myxml_node_t *ret=gasneti_calloc(1,sizeof(myxml_node_t)); ret->parent = parent; ret->num_children = 0; ret->children = NULL; /*make sure that we aren't adding to a leaf or know that this is the root node*/ if(parent==NULL) { ret->nodeclass = MYXML_ROOT_NODE; } else if(parent->nodeclass == MYXML_LEAF_NODE) { fprintf(stderr, "can't add a child to a leaf node!\n"); exit(1); } if(tag==NULL) { fprintf(stderr, "tag can't be null!\n"); exit(1); } else { STR_ALLOC_AND_COPY(ret->tag, tag); } /*this mustbe a leaf node since an explicit value was declared*/ if(value) { STR_ALLOC_AND_COPY(ret->value, value); ret->nodeclass = MYXML_LEAF_NODE; } else if(parent!=NULL) { ret->nodeclass = MYXML_INTER_NODE; } ret->attribute_list = gasneti_malloc(sizeof(myxml_attribute_t)*num_attributes); for(i=0; i<num_attributes; i++) { STR_ALLOC_AND_COPY(ret->attribute_list[i].attribute_name, attribute_list[i]); STR_ALLOC_AND_COPY(ret->attribute_list[i].attribute_value, attribute_vals[i]); } /*add myself to my parents children list*/ if(parent) { parent->num_children++; if(parent->children) { parent->children = gasneti_realloc(parent->children,parent->num_children*sizeof(myxml_node_t*)); } else { parent->children = gasneti_malloc(parent->num_children*sizeof(myxml_node_t*)); } parent->children[parent->num_children-1] = ret; } return ret; }
static tree_node_t make_nary_tree(tree_node_t *nodes, gasnet_node_t num_nodes, int radix) { gasnet_node_t num_children=0; int i,j; if(num_nodes > 1) { tree_node_t *children; for(j=0; j<radix; j++){ int start,end; start = (j==0 ? 1 : MIN(num_nodes, j*(MYCEIL(num_nodes, radix)))); end = MIN(num_nodes, (j+1)*MYCEIL(num_nodes, radix)); if(start == end) continue; num_children++; } if(num_children > 0) { children = (tree_node_t*) gasneti_malloc(num_children*sizeof(tree_node_t)); for(j=0, i=num_children-1; j<radix; j++) { int start,end; start = (j==0 ? 1 : MIN(num_nodes, j*(MYCEIL(num_nodes, radix)))); end = MIN(num_nodes, (j+1)*MYCEIL(num_nodes, radix)); if(start == end) continue; children[i] = make_nary_tree(nodes+start, end-start, radix); i--; } nodes[0]->children_reversed=1; preappend_children(nodes[0], children, num_children); gasneti_free(children); } } return nodes[0]; }
static gasnete_coll_tree_type_t make_tree_type_str_helper(char *tree_name) { gasnete_coll_tree_type_t ret = gasnete_coll_get_tree_type(); char **inner_split; int num_splits; int i; char inner_delim[]=","; num_splits = split_string(&inner_split, tree_name,inner_delim); if(strcmp(inner_split[0], "NARY_TREE")==0) { ret->tree_class = GASNETE_COLL_NARY_TREE; } else if(strcmp(inner_split[0], "KNOMIAL_TREE")==0) { ret->tree_class = GASNETE_COLL_KNOMIAL_TREE; } else if(strcmp(inner_split[0], "RECURSIVE_TREE")==0) { ret->tree_class = GASNETE_COLL_RECURSIVE_TREE; } else if(strcmp(inner_split[0], "FORK_TREE")==0) { ret->tree_class = GASNETE_COLL_FORK_TREE; }else if(strcmp(inner_split[0], "FLAT_TREE")==0) { ret->tree_class = GASNETE_COLL_FLAT_TREE; } else { gasneti_fatalerror("Unknown Tree Type: %s\n", tree_name); } ret->params = gasneti_malloc(sizeof(int)*num_splits-1); ret->num_params = num_splits-1; for(i=0; i<ret->num_params; i++) { ret->params[i] = atoi(inner_split[i+1]); } gasneti_free(inner_split); return ret; }
/* Naive (poorly scaling) "reference" implementation via gasnetc_bootstrapExchange() */ static void gasnetc_bootstrapSNodeBroadcast(void *src, size_t len, void *dest, int rootnode) { void *tmp = gasneti_malloc(len * gasneti_nodes); gasneti_assert(NULL != src); gasnetc_bootstrapExchange(src, len, tmp); memcpy(dest, (void*)((uintptr_t)tmp + (len * rootnode)), len); gasneti_free(tmp); }
void gasnete_coll_set_dissemination_order(gasnete_coll_local_tree_geom_t *geom, int gasnete_coll_tree_mynode, int gasnete_coll_tree_nodes) { int i = gasnete_coll_tree_nodes; int j, k; int factor; int lognp; gasnet_node_t *proc_list; lognp = 0; i = gasnete_coll_tree_nodes; while(i > 1) { lognp ++; i = i/2; } proc_list = (gasnet_node_t*)gasneti_malloc(sizeof(gasnet_node_t)*lognp); k=0; factor = 2; for(i=0; i<lognp; i++) { j = (gasnete_coll_tree_mynode + (factor/2))%factor; j += (gasnete_coll_tree_mynode / factor) * factor; proc_list[i] = j; factor = factor * 2; } geom->dissem_order = proc_list; geom->dissem_count = lognp; }
static tree_node_t make_hiearchical_tree_helper(gasnete_coll_tree_type_t tree_type, int level, int final_level, tree_node_t *allnodes, int num_nodes, int *node_counts) { tree_node_t rootnode; tree_node_t *temp; gasneti_assert(tree_type !=NULL); if(level == final_level) { switch (tree_type->tree_class) { case GASNETE_COLL_NARY_TREE: rootnode = make_nary_tree(allnodes, num_nodes, tree_type->params[0]); break; case GASNETE_COLL_FLAT_TREE: rootnode = make_flat_tree(allnodes, num_nodes); break; case GASNETE_COLL_KNOMIAL_TREE: rootnode = make_knomial_tree(allnodes, num_nodes, tree_type->params[0]); break; case GASNETE_COLL_RECURSIVE_TREE: rootnode = make_recursive_tree(allnodes, num_nodes, tree_type->params[0]); break; case GASNETE_COLL_FORK_TREE: rootnode = make_fork_tree(allnodes, num_nodes, tree_type->params, tree_type->num_params); break; default: gasneti_fatalerror("unknown tree type"); } } else { int i,j=0,num_processed=0; int level_nodes = MYCEIL(num_nodes, node_counts[0]); temp = gasneti_malloc(sizeof(tree_node_t) * level_nodes); for(i=0; i<level_nodes-1; i++) { temp[j]=make_hiearchical_tree_helper(tree_type->subtree, level+1, final_level, allnodes+i*node_counts[0], node_counts[0], node_counts+1); j++; num_processed += node_counts[0]; } temp[j]=make_hiearchical_tree_helper(tree_type->subtree, level+1, final_level, allnodes+i*node_counts[0], num_nodes - num_processed, node_counts+1); j++; switch (tree_type->tree_class) { case GASNETE_COLL_NARY_TREE: rootnode = make_nary_tree(temp, j, tree_type->params[0]); break; case GASNETE_COLL_FLAT_TREE: rootnode = make_flat_tree(temp,j); break; case GASNETE_COLL_KNOMIAL_TREE: rootnode = make_knomial_tree(temp, j, tree_type->params[0]); break; case GASNETE_COLL_RECURSIVE_TREE: rootnode = make_recursive_tree(temp, j, tree_type->params[0]); break; case GASNETE_COLL_FORK_TREE: rootnode = make_fork_tree(temp, j, tree_type->params, tree_type->num_params); break; default: gasneti_fatalerror("unknown tree type"); } gasneti_free(temp); } return rootnode; }
gasnete_coll_tree_type_t gasnete_coll_get_tree_type(void) { gasnete_coll_tree_type_t ret; ret = gasneti_lifo_pop(&gasnete_coll_tree_type_free_list); if(!ret) { ret = (gasnete_coll_tree_type_t) gasneti_malloc(sizeof(struct gasnete_coll_tree_type_t_)); } memset(ret, 0, sizeof(struct gasnete_coll_tree_type_t_)); return ret; }
/*preappend a list of children*/ static tree_node_t preappend_children(tree_node_t main_node, tree_node_t *child_nodes, int num_nodes) { if(num_nodes > 0) { if(main_node->num_children == 0) { main_node->children = gasneti_malloc(num_nodes * sizeof(tree_node_t)); GASNETE_FAST_UNALIGNED_MEMCPY_CHECK(main_node->children, child_nodes, sizeof(tree_node_t)*num_nodes); } else { tree_node_t *new_children = gasneti_malloc(sizeof(tree_node_t)* (main_node->num_children+num_nodes)); GASNETE_FAST_UNALIGNED_MEMCPY_CHECK(new_children, child_nodes, num_nodes*sizeof(tree_node_t)); GASNETE_FAST_UNALIGNED_MEMCPY_CHECK(new_children+num_nodes, main_node->children, main_node->num_children*(sizeof(tree_node_t))); gasneti_free(main_node->children); main_node->children = new_children; } main_node->num_children = main_node->num_children+num_nodes; } return main_node; }
gasnet_mxm_send_req_t * gasnetc_alloc_send_req(void) { gasnet_mxm_send_req_t * sreq = (gasnet_mxm_send_req_t *) #if GASNET_DEBUG gasneti_calloc(1, sizeof(gasnet_mxm_send_req_t)); #else gasneti_malloc(sizeof(gasnet_mxm_send_req_t)); #endif gasneti_assert(sreq && "Out of memory"); return sreq; }
/* allocate a new iop */ GASNETI_NEVER_INLINE(gasnete_iop_alloc, static gasnete_iop_t *gasnete_iop_alloc(gasneti_threaddata_t * const thread)) { gasnete_iop_t *iop = (gasnete_iop_t *)gasneti_malloc(sizeof(gasnete_iop_t)); gasneti_leak(iop); #if GASNET_DEBUG memset(iop, 0, sizeof(gasnete_iop_t)); /* set pad to known value */ #endif SET_OPTYPE((gasnete_op_t *)iop, OPTYPE_IMPLICIT); iop->threadidx = thread->threadidx; iop->initiated_get_cnt = 0; iop->initiated_put_cnt = 0; gasnetc_atomic_set(&(iop->completed_get_cnt), 0, 0); gasnetc_atomic_set(&(iop->completed_put_cnt), 0, 0); return iop; }
gasnete_coll_tree_type_t gasnete_coll_make_tree_type(int tree_class, int *params, int num_params) { gasnete_coll_tree_type_t ret= gasnete_coll_get_tree_type(); #if GASNET_DEBUG if(tree_class >= GASNETE_COLL_NUM_TREE_CLASSES) { gasneti_fatalerror("Unknown Tree Class: %d\n", tree_class); } #endif ret->tree_class = (gasnete_coll_tree_class_t) tree_class; ret->params = (int*) gasneti_malloc(sizeof(int)*num_params); GASNETE_FAST_UNALIGNED_MEMCPY_CHECK(ret->params, params, num_params*sizeof(int)); ret->num_params = num_params; return ret; }
extern gasnet_mxm_recv_req_t * gasnetc_alloc_recv_req(void) { gasnet_mxm_recv_req_t * r; size_t size = GASNETI_PAGE_ALIGNUP(gasneti_AMMaxMedium()); void * buf; r = gasneti_malloc(sizeof(*r)); gasneti_assert(r && "Out of memory"); buf = gasneti_mmap(size); gasneti_assert(buf && "Out of memory"); r->mxm_rreq.base.data.buffer.ptr = buf; r->mxm_rreq.base.data.buffer.length = size; return r; }
void gasneti_bootstrapExchange_mpi(void *src, size_t len, void *dest) { const int inplace = ((uint8_t *)src == (uint8_t *)dest + len * gasnetc_mpi_rank); int err; if (inplace) { #if GASNETC_MPI_ALLGATHER_IN_PLACE src = MPI_IN_PLACE; #else src = memcpy(gasneti_malloc(len), src, len); #endif } err = MPI_Allgather(src, len, MPI_BYTE, dest, len, MPI_BYTE, gasnetc_mpi_comm); gasneti_assert(err == MPI_SUCCESS); #if !GASNETC_MPI_ALLGATHER_IN_PLACE if (inplace) gasneti_free(src); #endif }
void gasneti_bootstrapAlltoall_mpi(void *src, size_t len, void *dest) { const int inplace = (src == dest); int err; if (inplace) { #if GASNETC_MPI_ALLTOALL_IN_PLACE src = MPI_IN_PLACE; #else const size_t total_len = len * gasnetc_mpi_size; src = memcpy(gasneti_malloc(total_len), src, total_len); #endif } err = MPI_Alltoall(src, len, MPI_BYTE, dest, len, MPI_BYTE, gasnetc_mpi_comm); gasneti_assert(err == MPI_SUCCESS); #if !GASNETC_MPI_ALLTOALL_IN_PLACE if (inplace) gasneti_free(src); #endif }
gasnete_coll_tree_type_t gasnete_coll_make_tree_type_str(char *tree_name_str) { char outter_delim[]=":"; char inner_delim[]=","; char **outer_split; gasnete_coll_tree_type_t ret; /*first split the tree string on the ":"*/ int num_levels = split_string(&outer_split, tree_name_str, outter_delim); if(num_levels > 1) { char **inner_split; int num_splits, num_params; int i; gasnete_coll_tree_type_t temp; ret = gasnete_coll_get_tree_type(); num_splits = split_string(&inner_split, outer_split[0],inner_delim); num_params = num_splits-1;/*first split is the tree name*/ gasneti_assert(strcmp(inner_split[0], "HIERARCHICAL_TREE")==0); ret->tree_class = GASNETE_COLL_HIERARCHICAL_TREE; if(num_params != num_levels-1){ gasneti_fatalerror("badly formed hierarchical tree expect HIEARCHICAL_TREE,<numlevels>,<in level1>,<in level2>,..,<in level n-1>:TREE1,PARAMS1:TREE2,PARAMS2:(etc)\n"); } /*NOT DONE*/ ret->params = gasneti_malloc(sizeof(int)*(num_params)); ret->num_params = num_params; for(i=0; i<num_params; i++) { ret->params[i] = atoi(inner_split[i+1]); } temp = ret; for(i=1; i<num_levels; i++) { temp->subtree = make_tree_type_str_helper(outer_split[i]); temp = temp->subtree; } } else { ret = make_tree_type_str_helper(tree_name_str); } gasneti_free(outer_split); return ret; }
/* 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; }
static tree_node_t make_knomial_tree(tree_node_t *nodes, int num_nodes, int radix) { int i; int num_children=0; gasneti_assert(radix>1); if(num_nodes > 1) { int r; int stride = 1; int num_proc = 1; tree_node_t *children; while(num_proc < num_nodes) { for(r=stride; r<stride*radix; r+=stride) { num_proc += MIN(stride, num_nodes - num_proc); num_children++; if(num_proc == num_nodes) break; } stride*=radix; } children = (tree_node_t*) gasneti_malloc(num_children*sizeof(tree_node_t)); num_proc = 1; i=1; stride = 1; while(num_proc<num_nodes) { for(r=stride; r<stride*radix; r+=stride) { gasneti_assert(i<=num_children); children[num_children-i] = make_knomial_tree(nodes+r,MIN(stride, num_nodes - num_proc), radix); num_proc += MIN(stride, num_nodes - num_proc); if(num_proc == num_nodes) break; i++; } stride*=radix; } nodes[0]->children_reversed=1; preappend_children(nodes[0], children, num_children); gasneti_free(children); } return nodes[0]; }
static tree_node_t *allocate_nodes(tree_node_t **curr_nodes, gasnet_team_handle_t team, int rootrank) { gasnet_node_t i; int new_allocation=0; if(!(*curr_nodes)) { *curr_nodes = (tree_node_t*) gasneti_malloc(sizeof(tree_node_t)*team->total_ranks); new_allocation=1; } for(i=0; i<team->total_ranks; i++) { if(new_allocation) { (*curr_nodes)[i] = (struct tree_node_t_*) gasneti_calloc(1,sizeof(struct tree_node_t_)); } else { gasneti_free((*curr_nodes)[i]->children); (*curr_nodes)[i]->children = NULL; (*curr_nodes)[i]->num_children = 0; (*curr_nodes)[i]->children_reversed = 0; } (*curr_nodes)[i]->id = (i+rootrank)%team->total_ranks; (*curr_nodes)[i]->parent = NULL; } return *curr_nodes; }
/*need to worry about corner cases*/ static tree_node_t make_fork_tree(tree_node_t *nodes, int num_nodes, int *dims, int ndims) { int i; int stride; tree_node_t *temp_nodes; gasneti_assert(ndims > 0); gasneti_assert(multarr(dims, ndims)==num_nodes); if(ndims > 1) { temp_nodes = gasneti_malloc(sizeof(tree_node_t)*dims[0]); stride = multarr(dims+1,ndims-1); for(i=dims[0]-1; i>=0; i--) { temp_nodes[i] = make_fork_tree(nodes+stride*i, stride, dims+1, ndims-1); } make_chain_tree(temp_nodes, dims[0]); gasneti_free(temp_nodes); } else { make_chain_tree(nodes, dims[0]); } nodes[0]->children_reversed=1; return nodes[0]; }
static tree_node_t make_recursive_tree(tree_node_t *nodes, gasnet_node_t num_nodes, int radix) { gasnet_node_t i,j; int num_children=0; if(num_nodes > 1) { tree_node_t *children; gasneti_assert(radix > 1); for(i=1; i<num_nodes; i*=radix) { num_children++; } children = (tree_node_t*) gasneti_malloc(num_children*sizeof(tree_node_t)); /*reverse the order of hte children as specified by the binomial tree construction*/ for(i=1,j=num_children-1; i<num_nodes; i*=radix,j--) { children[j] = make_recursive_tree(nodes+i, (MIN(num_nodes, (i*radix)) - i), radix); } nodes[0]->children_reversed=1; preappend_children(nodes[0], children, num_children); gasneti_free(children); } return nodes[0]; }
/* ------------------------------------------------------------------------------------ */ extern int gasnetc_attach(gasnet_handlerentry_t *table, int numentries, uintptr_t segsize, uintptr_t minheapoffset) { void *segbase = NULL; int ret; GASNETI_TRACE_PRINTF(C,("gasnetc_attach(table (%i entries), segsize=%lu, minheapoffset=%lu)", numentries, (unsigned long)segsize, (unsigned long)minheapoffset)); if (!gasneti_init_done) GASNETI_RETURN_ERRR(NOT_INIT, "GASNet attach called before init"); if (gasneti_attach_done) GASNETI_RETURN_ERRR(NOT_INIT, "GASNet already attached"); /* check argument sanity */ #if GASNET_SEGMENT_FAST || GASNET_SEGMENT_LARGE if ((segsize % GASNET_PAGESIZE) != 0) GASNETI_RETURN_ERRR(BAD_ARG, "segsize not page-aligned"); if (segsize > gasneti_MaxLocalSegmentSize) GASNETI_RETURN_ERRR(BAD_ARG, "segsize too large"); if ((minheapoffset % GASNET_PAGESIZE) != 0) /* round up the minheapoffset to page sz */ minheapoffset = ((minheapoffset / GASNET_PAGESIZE) + 1) * GASNET_PAGESIZE; #else segsize = 0; minheapoffset = 0; #endif segsize = gasneti_auxseg_preattach(segsize); /* adjust segsize for auxseg reqts */ /* ------------------------------------------------------------------------------------ */ /* register handlers */ { int i; for (i = 0; i < GASNETC_MAX_NUMHANDLERS; i++) gasnetc_handler[i] = (gasneti_handler_fn_t)&gasneti_defaultAMHandler; } { /* core API handlers */ gasnet_handlerentry_t *ctable = (gasnet_handlerentry_t *)gasnetc_get_handlertable(); int len = 0; int numreg = 0; gasneti_assert(ctable); while (ctable[len].fnptr) len++; /* calc len */ if (gasnetc_reghandlers(ctable, len, 1, 63, 0, &numreg) != GASNET_OK) GASNETI_RETURN_ERRR(RESOURCE,"Error registering core API handlers"); gasneti_assert(numreg == len); } { /* extended API handlers */ gasnet_handlerentry_t *etable = (gasnet_handlerentry_t *)gasnete_get_handlertable(); int len = 0; int numreg = 0; gasneti_assert(etable); while (etable[len].fnptr) len++; /* calc len */ if (gasnetc_reghandlers(etable, len, 64, 127, 0, &numreg) != GASNET_OK) GASNETI_RETURN_ERRR(RESOURCE,"Error registering extended API handlers"); gasneti_assert(numreg == len); } if (table) { /* client handlers */ int numreg1 = 0; int numreg2 = 0; /* first pass - assign all fixed-index handlers */ if (gasnetc_reghandlers(table, numentries, 128, 255, 0, &numreg1) != GASNET_OK) GASNETI_RETURN_ERRR(RESOURCE,"Error registering fixed-index client handlers"); /* second pass - fill in dontcare-index handlers */ if (gasnetc_reghandlers(table, numentries, 128, 255, 1, &numreg2) != GASNET_OK) GASNETI_RETURN_ERRR(RESOURCE,"Error registering fixed-index client handlers"); gasneti_assert(numreg1 + numreg2 == numentries); } /* ------------------------------------------------------------------------------------ */ /* register fatal signal handlers */ /* catch fatal signals and convert to SIGQUIT */ gasneti_registerSignalHandlers(gasneti_defaultSignalHandler); #if HAVE_ON_EXIT on_exit(gasnetc_on_exit, NULL); #else atexit(gasnetc_atexit); #endif /* ------------------------------------------------------------------------------------ */ /* register segment */ gasneti_seginfo = (gasnet_seginfo_t *)gasneti_malloc(gasneti_nodes*sizeof(gasnet_seginfo_t)); gasneti_leak(gasneti_seginfo); #if GASNET_SEGMENT_FAST || GASNET_SEGMENT_LARGE if (segsize == 0) segbase = NULL; /* no segment */ else { gasneti_segmentAttach(segsize, minheapoffset, gasneti_seginfo, &gasnetc_bootstrapExchange); segbase = gasneti_seginfo[gasneti_mynode].addr; segsize = gasneti_seginfo[gasneti_mynode].size; gasneti_assert(((uintptr_t)segbase) % GASNET_PAGESIZE == 0); gasneti_assert(segsize % GASNET_PAGESIZE == 0); } #else { /* GASNET_SEGMENT_EVERYTHING */ gasnet_node_t i; for (i=0; i<gasneti_nodes; i++) { gasneti_seginfo[i].addr = (void *)0; gasneti_seginfo[i].size = (uintptr_t)-1; } segbase = (void *)0; segsize = (uintptr_t)-1; } #endif ret = gasnetc_p4_attach(segbase, segsize); if (GASNET_OK != ret) { GASNETI_RETURN_ERRR(RESOURCE,"Error attaching Portals4 resources"); } /* ------------------------------------------------------------------------------------ */ /* gather segment information */ /* This was done by segmentAttach above */ /* ------------------------------------------------------------------------------------ */ /* primary attach complete */ gasneti_attach_done = 1; gasnetc_bootstrapBarrier(); GASNETI_TRACE_PRINTF(C,("gasnetc_attach(): primary attach complete")); gasneti_assert(gasneti_seginfo[gasneti_mynode].addr == segbase && gasneti_seginfo[gasneti_mynode].size == segsize); gasneti_auxseg_attach(); /* provide auxseg */ gasnete_init(); /* init the extended API */ gasneti_nodemapFini(); /* ensure extended API is initialized across nodes */ gasnetc_bootstrapBarrier(); return GASNET_OK; }
/* ------------------------------------------------------------------------------------ */ extern int gasnetc_attach(gasnet_handlerentry_t *table, int numentries, uintptr_t segsize, uintptr_t minheapoffset) { int retval = GASNET_OK; void *segbase = NULL; GASNETI_TRACE_PRINTF(C,("gasnetc_attach(table (%i entries), segsize=%lu, minheapoffset=%lu)", numentries, (unsigned long)segsize, (unsigned long)minheapoffset)); AMLOCK(); if (!gasneti_init_done) INITERR(NOT_INIT, "GASNet attach called before init"); if (gasneti_attach_done) INITERR(NOT_INIT, "GASNet already attached"); /* pause to make sure all nodes have called attach if a node calls gasnet_exit() between init/attach, then this allows us to process the AMUDP_SPMD control messages required for job shutdown */ gasnetc_bootstrapBarrier(); /* check argument sanity */ #if GASNET_SEGMENT_FAST || GASNET_SEGMENT_LARGE if ((segsize % GASNET_PAGESIZE) != 0) INITERR(BAD_ARG, "segsize not page-aligned"); if (segsize > gasneti_MaxLocalSegmentSize) INITERR(BAD_ARG, "segsize too large"); if ((minheapoffset % GASNET_PAGESIZE) != 0) /* round up the minheapoffset to page sz */ minheapoffset = ((minheapoffset / GASNET_PAGESIZE) + 1) * GASNET_PAGESIZE; #else segsize = 0; minheapoffset = 0; #endif segsize = gasneti_auxseg_preattach(segsize); /* adjust segsize for auxseg reqts */ /* ------------------------------------------------------------------------------------ */ /* register handlers */ #ifdef GASNETC_MAX_NUMHANDLERS /* Initialize shadow handler table */ { int i; for (i=0; i<GASNETC_MAX_NUMHANDLERS; i++) gasnetc_handler[i]=(gasneti_handler_fn_t)&gasneti_defaultAMHandler; } #endif { /* core API handlers */ gasnet_handlerentry_t *ctable = (gasnet_handlerentry_t *)gasnetc_get_handlertable(); int len = 0; int numreg = 0; gasneti_assert(ctable); while (ctable[len].fnptr) len++; /* calc len */ if (gasnetc_reghandlers(ctable, len, 1, 63, 0, &numreg) != GASNET_OK) INITERR(RESOURCE,"Error registering core API handlers"); gasneti_assert(numreg == len); } { /* extended API handlers */ gasnet_handlerentry_t *etable = (gasnet_handlerentry_t *)gasnete_get_handlertable(); int len = 0; int numreg = 0; gasneti_assert(etable); while (etable[len].fnptr) len++; /* calc len */ if (gasnetc_reghandlers(etable, len, 64, 127, 0, &numreg) != GASNET_OK) INITERR(RESOURCE,"Error registering extended API handlers"); gasneti_assert(numreg == len); } if (table) { /* client handlers */ int numreg1 = 0; int numreg2 = 0; /* first pass - assign all fixed-index handlers */ if (gasnetc_reghandlers(table, numentries, 128, 255, 0, &numreg1) != GASNET_OK) INITERR(RESOURCE,"Error registering fixed-index client handlers"); /* second pass - fill in dontcare-index handlers */ if (gasnetc_reghandlers(table, numentries, 128, 255, 1, &numreg2) != GASNET_OK) INITERR(RESOURCE,"Error registering fixed-index client handlers"); gasneti_assert(numreg1 + numreg2 == numentries); } /* ------------------------------------------------------------------------------------ */ /* register fatal signal handlers */ /* catch fatal signals and convert to SIGQUIT */ gasneti_registerSignalHandlers(gasneti_defaultSignalHandler); #if HAVE_ON_EXIT on_exit(gasnetc_on_exit, NULL); #else atexit(gasnetc_atexit); #endif /* ------------------------------------------------------------------------------------ */ /* register segment */ gasneti_seginfo = (gasnet_seginfo_t *)gasneti_malloc(gasneti_nodes*sizeof(gasnet_seginfo_t)); gasneti_leak(gasneti_seginfo); #if GASNET_SEGMENT_FAST || GASNET_SEGMENT_LARGE gasneti_segmentAttach(segsize, minheapoffset, gasneti_seginfo, &gasnetc_bootstrapExchange); #else /* GASNET_SEGMENT_EVERYTHING */ { int i; for (i=0;i<gasneti_nodes;i++) { gasneti_seginfo[i].addr = (void *)0; gasneti_seginfo[i].size = (uintptr_t)-1; } } #endif segbase = gasneti_seginfo[gasneti_mynode].addr; segsize = gasneti_seginfo[gasneti_mynode].size; /* After local segment is attached, call optional client-provided hook (###) should call BEFORE any conduit-specific pinning/registration of the segment */ if (gasnet_client_attach_hook) { gasnet_client_attach_hook(segbase, segsize); } /* AMUDP allows arbitrary registration with no further action */ if (segsize) { retval = AM_SetSeg(gasnetc_endpoint, segbase, segsize); if (retval != AM_OK) INITERR(RESOURCE, "AM_SetSeg() failed"); } #if GASNET_TRACE if (GASNETI_TRACE_ENABLED(A)) GASNETI_AM_SAFE(AMUDP_SetHandlerCallbacks(gasnetc_endpoint, gasnetc_enteringHandler_hook, gasnetc_leavingHandler_hook)); #endif /* ------------------------------------------------------------------------------------ */ /* primary attach complete */ gasneti_attach_done = 1; gasnetc_bootstrapBarrier(); AMUNLOCK(); GASNETI_TRACE_PRINTF(C,("gasnetc_attach(): primary attach complete\n")); gasneti_auxseg_attach(); /* provide auxseg */ gasnete_init(); /* init the extended API */ gasneti_nodemapFini(); /* ensure extended API is initialized across nodes */ AMLOCK(); gasnetc_bootstrapBarrier(); AMUNLOCK(); gasneti_assert(retval == GASNET_OK); return retval; done: /* error return while locked */ AMUNLOCK(); GASNETI_RETURN(retval); }
/* ------------------------------------------------------------------------------------ */ extern int gasnetc_attach(gasnet_handlerentry_t *table, int numentries, uintptr_t segsize, uintptr_t minheapoffset) { void *segbase = NULL; GASNETI_TRACE_PRINTF(C,("gasnetc_attach(table (%i entries), segsize=%"PRIuPTR", minheapoffset=%"PRIuPTR")", numentries, segsize, minheapoffset)); if (!gasneti_init_done) GASNETI_RETURN_ERRR(NOT_INIT, "GASNet attach called before init"); if (gasneti_attach_done) GASNETI_RETURN_ERRR(NOT_INIT, "GASNet already attached"); /* check argument sanity */ #if GASNET_SEGMENT_FAST || GASNET_SEGMENT_LARGE if ((segsize % GASNET_PAGESIZE) != 0) GASNETI_RETURN_ERRR(BAD_ARG, "segsize not page-aligned"); if (segsize > gasneti_MaxLocalSegmentSize) GASNETI_RETURN_ERRR(BAD_ARG, "segsize too large"); if ((minheapoffset % GASNET_PAGESIZE) != 0) /* round up the minheapoffset to page sz */ minheapoffset = ((minheapoffset / GASNET_PAGESIZE) + 1) * GASNET_PAGESIZE; #else segsize = 0; minheapoffset = 0; #endif segsize = gasneti_auxseg_preattach(segsize); /* adjust segsize for auxseg reqts */ /* ------------------------------------------------------------------------------------ */ /* register handlers */ { int i; for (i = 0; i < GASNETC_MAX_NUMHANDLERS; i++) gasnetc_handler[i] = (gasneti_handler_fn_t)&gasneti_defaultAMHandler; } { /* core API handlers */ gasnet_handlerentry_t *ctable = (gasnet_handlerentry_t *)gasnetc_get_handlertable(); int len = 0; int numreg = 0; gasneti_assert(ctable); while (ctable[len].fnptr) len++; /* calc len */ if (gasneti_amregister(ctable, len, 1, 63, 0, &numreg) != GASNET_OK) GASNETI_RETURN_ERRR(RESOURCE,"Error registering core API handlers"); gasneti_assert(numreg == len); } { /* extended API handlers */ gasnet_handlerentry_t *etable = (gasnet_handlerentry_t *)gasnete_get_handlertable(); int len = 0; int numreg = 0; gasneti_assert(etable); while (etable[len].fnptr) len++; /* calc len */ if (gasneti_amregister(etable, len, 64, 127, 0, &numreg) != GASNET_OK) GASNETI_RETURN_ERRR(RESOURCE,"Error registering extended API handlers"); gasneti_assert(numreg == len); } if (table) { /* client handlers */ int numreg1 = 0; int numreg2 = 0; /* first pass - assign all fixed-index handlers */ if (gasneti_amregister(table, numentries, 128, 255, 0, &numreg1) != GASNET_OK) GASNETI_RETURN_ERRR(RESOURCE,"Error registering fixed-index client handlers"); /* second pass - fill in dontcare-index handlers */ if (gasneti_amregister(table, numentries, 128, 255, 1, &numreg2) != GASNET_OK) GASNETI_RETURN_ERRR(RESOURCE,"Error registering variable-index client handlers"); gasneti_assert(numreg1 + numreg2 == numentries); } /* ------------------------------------------------------------------------------------ */ /* register fatal signal handlers */ /* catch fatal signals and convert to SIGQUIT */ gasneti_registerSignalHandlers(gasneti_defaultSignalHandler); /* ------------------------------------------------------------------------------------ */ /* setup fo rexit coordination */ gasnetc_exittimeout = gasneti_get_exittimeout(GASNETC_DEFAULT_EXITTIMEOUT_MAX, GASNETC_DEFAULT_EXITTIMEOUT_MIN, GASNETC_DEFAULT_EXITTIMEOUT_FACTOR, GASNETC_DEFAULT_EXITTIMEOUT_MIN); #if HAVE_ON_EXIT on_exit(gasnetc_on_exit, NULL); #else atexit(gasnetc_atexit); #endif /* ------------------------------------------------------------------------------------ */ /* register segment */ gasneti_seginfo = (gasnet_seginfo_t *)gasneti_malloc(gasneti_nodes*sizeof(gasnet_seginfo_t)); gasneti_leak(gasneti_seginfo); #if GASNET_SEGMENT_FAST || GASNET_SEGMENT_LARGE if (segsize == 0) segbase = NULL; /* no segment */ else { gasneti_segmentAttach(segsize, minheapoffset, gasneti_seginfo, gasneti_bootstrapExchange); segbase = gasneti_seginfo[gasneti_mynode].addr; segsize = gasneti_seginfo[gasneti_mynode].size; gasneti_assert(((uintptr_t)segbase) % GASNET_PAGESIZE == 0); gasneti_assert(segsize % GASNET_PAGESIZE == 0); } #else { /* GASNET_SEGMENT_EVERYTHING */ gasnet_node_t i; for (i=0; i<gasneti_nodes; i++) { gasneti_seginfo[i].addr = (void *)0; gasneti_seginfo[i].size = (uintptr_t)-1; } segbase = (void *)0; segsize = (uintptr_t)-1; } #endif gasnetc_ofi_attach(segbase, segsize); /* After local segment is attached, call optional client-provided hook (###) should call BEFORE any conduit-specific pinning/registration of the segment */ if (gasnet_client_attach_hook) { gasnet_client_attach_hook(segbase, segsize); } /* ------------------------------------------------------------------------------------ */ /* primary attach complete */ gasneti_attach_done = 1; gasneti_bootstrapBarrier(); GASNETI_TRACE_PRINTF(C,("gasnetc_attach(): primary attach complete")); gasneti_assert(gasneti_seginfo[gasneti_mynode].addr == segbase && gasneti_seginfo[gasneti_mynode].size == segsize); /* (###) exchange_fn is optional (may be NULL) and is only used with GASNET_SEGMENT_EVERYTHING if your conduit has an optimized bootstrapExchange pass it in place of NULL */ gasneti_auxseg_attach(NULL); /* provide auxseg */ gasnete_init(); /* init the extended API */ gasneti_nodemapFini(); /* ensure extended API is initialized across nodes */ gasneti_bootstrapBarrier(); return GASNET_OK; }
/* Packetizes remotelist into a list of gasnete_packetdesc_t entries based on maxpayload packet size sharedpacket => metadata and corresponding data travel together in unified packets (put) so that for each packet i: datasz_i + metadatasz_i <= maxpayload !sharedpacket => metadata and corresponding data travel in separate packets (get) so that for each packet i: MAX(datasz_i,metadatasz_i) <= maxpayload A local packet table is also computed to match the remote packetization boundaries of the data on a byte-for-byte basis Allocates and populates the plocalpt and premotept arrays with the packetization information Returns the number of packets described by the resulting plocalpt and premotept arrays */ size_t gasnete_packetize_addrlist(size_t remotecount, size_t remotelen, size_t localcount, size_t locallen, gasnete_packetdesc_t **premotept, gasnete_packetdesc_t **plocalpt, size_t maxpayload, int sharedpacket) { size_t ptidx; int done = 0; size_t ridx = 0, roffset = 0, lidx = 0, loffset = 0; size_t const metadatasz = sizeof(void *); size_t const runit = (sharedpacket ? metadatasz + remotelen : MAX(metadatasz,remotelen)); size_t ptsz = (runit <= maxpayload ? /* conservative upper bound on packet count */ remotecount / (maxpayload / runit) + 1 : remotelen*remotecount / (maxpayload - 2*metadatasz) + 1); gasnete_packetdesc_t *remotept = gasneti_malloc(ptsz*sizeof(gasnete_packetdesc_t)); gasnete_packetdesc_t *localpt = gasneti_malloc(ptsz*sizeof(gasnete_packetdesc_t)); gasneti_assert(premotept && plocalpt && remotecount && remotelen && localcount && locallen); gasneti_assert(remotecount*remotelen == localcount*locallen); gasneti_assert(remotecount*remotelen > 0); for (ptidx = 0; ; ptidx++) { ssize_t packetremain = maxpayload; ssize_t packetdata = 0; size_t rdatasz, ldatasz; gasneti_assert(ptidx < ptsz); /* begin remote packet */ remotept[ptidx].firstidx = ridx; remotept[ptidx].firstoffset = roffset; /* begin local packet */ if_pf (lidx == localcount) localpt[ptidx].firstidx = lidx-1; else localpt[ptidx].firstidx = lidx; localpt[ptidx].firstoffset = loffset; if (roffset > 0) { /* initial partial entry */ gasneti_assert(roffset < remotelen); rdatasz = remotelen - roffset; /* data left in current entry */ /* try to add the entire entry to packet */ if (sharedpacket) packetremain -= (metadatasz + rdatasz); else packetremain -= MAX(metadatasz, rdatasz); if (packetremain < 0) { /* overflowed - finished a packet, and spill to next */ rdatasz += packetremain; /* compute truncated datasz that fits in this packet */ roffset += rdatasz; /* update offset into current entry */ packetdata += rdatasz; goto rend; } else { packetdata += rdatasz; roffset = 0; /* finished an entry */ ridx++; if (ridx == remotecount) { done = 1; goto rend; } /* done - this is last packet */ } } if (packetremain >= runit) { /* whole entries */ size_t numunits = packetremain / runit; if (ridx + numunits > remotecount) numunits = remotecount - ridx; rdatasz = remotelen; packetremain -= runit*numunits; packetdata += remotelen*numunits; ridx += numunits; gasneti_assert(roffset == 0); if (ridx == remotecount) { done = 1; goto rend; } /* done - this is last packet */ } if (packetremain > metadatasz) { /* trailing partial entry */ gasneti_assert(packetremain < runit); if (sharedpacket) rdatasz = packetremain - metadatasz; else rdatasz = packetremain; packetdata += rdatasz; roffset = rdatasz; } rend: /* end remote packet */ if (roffset == 0) remotept[ptidx].lastidx = ridx-1; else remotept[ptidx].lastidx = ridx; remotept[ptidx].lastlen = rdatasz; #if GASNET_DEBUG /* verify packing properties */ gasnete_packetize_verify(remotept, ptidx, done, remotecount, remotelen, 0); { size_t datachk = 0, i; size_t entries = remotept[ptidx].lastidx - remotept[ptidx].firstidx + 1; for (i = remotept[ptidx].firstidx; i <= remotept[ptidx].lastidx; i++) { if (i == remotept[ptidx].lastidx) datachk += remotept[ptidx].lastlen; else if (i == remotept[ptidx].firstidx) datachk += (remotelen - remotept[ptidx].firstoffset); else datachk += remotelen; } gasneti_assert(packetdata == datachk); if (sharedpacket) { gasneti_assert((metadatasz*entries + packetdata) <= maxpayload); /* not overfull */ gasneti_assert(((metadatasz*entries + packetdata) >= maxpayload - metadatasz) || done); /* not underfull */ } else { gasneti_assert(MAX(metadatasz*entries,packetdata) <= maxpayload); /* not overfull */ gasneti_assert((MAX(metadatasz*entries,packetdata) >= maxpayload - 2*metadatasz) || done); /* not underfull */ } } #endif ldatasz = 0; if (loffset > 0) { /* initial partial entry */ gasneti_assert(loffset < locallen); ldatasz = locallen - loffset; /* data left in current entry */ packetdata -= ldatasz; if (packetdata < 0) { /* overflowed - this entry spills into next packet */ ldatasz += packetdata; /* compute truncated datasz that fits in this packet */ loffset += ldatasz; /* update offset into current entry */ packetdata = 0; } else { loffset = 0; /* finished an entry */ lidx++; gasneti_assert(lidx < localcount || (lidx == localcount && packetdata == 0)); } } if (packetdata >= locallen) { /* whole entries */ size_t numunits = packetdata / locallen; if (lidx + numunits > localcount) numunits = localcount - lidx; ldatasz = locallen; packetdata -= locallen*numunits; lidx += numunits; gasneti_assert(lidx < localcount || (lidx == localcount && packetdata == 0)); gasneti_assert(loffset == 0); } if (packetdata > 0) { /* trailing partial entry */ gasneti_assert(packetdata < locallen); ldatasz = packetdata; loffset = ldatasz; } /* end local packet */ if (loffset == 0) localpt[ptidx].lastidx = lidx-1; else localpt[ptidx].lastidx = lidx; localpt[ptidx].lastlen = ldatasz; #if GASNET_DEBUG /* verify packing properties */ gasnete_packetize_verify(localpt, ptidx, done, localcount, locallen, 0); #endif if (done) { gasneti_assert(ridx == remotecount && roffset == 0 && lidx == localcount && loffset == 0); *premotept = remotept; *plocalpt = localpt; return ptidx+1; } }
void smp_coll_set_barrier_routine_with_root(smp_coll_t handle, smp_coll_barrier_routine_t routine_id, int in_radix, int root) { smp_coll_safe_barrier(handle, 0); if(handle->dissem_info) smp_coll_free_dissemination(handle->dissem_info); handle->dissem_info = smp_coll_build_dissemination(in_radix, handle->MYTHREAD, handle->THREADS); handle->barrier_root = root; handle->barrier_radix = in_radix; handle->barrier_log_2_radix = smp_coll_mylogn(in_radix,2); handle->barrier_log_radix_THREADS = smp_coll_mylogn(handle->THREADS, in_radix); if(routine_id < SMP_COLL_NUM_BARR_ROUTINES /* && routine_id >=0 (TYPE IS UNSIGNED) */) { handle->curr_barrier_routine = routine_id; } else { if(handle->MYTHREAD==0) fprintf(stderr, "bad barrier routine id: %d\n", routine_id); exit(1); } #define ACT2REL(actrank) ( ((actrank) >= (root)) ? (actrank) - (root) : (actrank) \ - (root) + (handle->THREADS) ) #define REL2ACT(relrank) ( (relrank) < (handle->THREADS-root) ? \ (relrank) + (root) : (relrank) + (root) - (handle->THREADS)) { int num_digits = handle->barrier_log_radix_THREADS; int radixlog2 = handle->barrier_log_2_radix; int radix = handle->barrier_radix; int i,j,k; int child_count=0; int myrelrank = ACT2REL(handle->MYTHREAD); if(myrelrank!=0) { i=0; while(SMP_COLL_GET_ITH_DIGIT_POWER2RADIX(myrelrank,i,radix,radixlog2)==0) { i++; } handle->barrier_parent = REL2ACT(SMP_COLL_REPLACE_DIGIT_POWER2RADIX(myrelrank,i,0,radix,radixlog2)); } else { handle->barrier_parent = -1; } /* reduce data from all the children*/ for(i=num_digits-1,j=0; i>=0; i--,j++) { /*if my i^th digit is 0 that means that i am a sender for this round*/ if(SMP_COLL_GET_ITH_DIGIT_POWER2RADIX(myrelrank, i, radix, radixlog2)==0 && SMP_COLL_GET_LOWER_K_DIGITS_POWER2RADIX(myrelrank, i, radix, radixlog2)==0) { for(k=1;k<radix;k++) { int dest = SMP_COLL_MAKE_NUM_POWER2RADIX(myrelrank, i, k, radix, radixlog2); if(dest<handle->THREADS) { child_count++; } } } } handle->barrier_children = (int*) gasneti_malloc(sizeof(int)*child_count); /* if(child_count > 0) { */ /* } else { */ /* handle->barrier_children = NULL; */ /* } */ handle->barrier_num_children = child_count; child_count = 0; for(i=num_digits-1,j=0; i>=0; i--,j++) { /*if my i^th digit is 0 that means that i am a sender for this round*/ if(SMP_COLL_GET_ITH_DIGIT_POWER2RADIX(myrelrank, i, radix, radixlog2)==0 && SMP_COLL_GET_LOWER_K_DIGITS_POWER2RADIX(myrelrank, i, radix, radixlog2)==0) { for(k=1;k<radix;k++) { int dest = SMP_COLL_MAKE_NUM_POWER2RADIX(myrelrank, i, k, radix, radixlog2); if(dest<handle->THREADS) { handle->barrier_children[child_count] = REL2ACT(dest); child_count++; } } } } /* print_barrier_tree(handle); */ } smp_coll_safe_barrier(handle, 0); }