/* $Source: runtime/gasnet/udp-conduit/gasnet_core.c $ * $Date: Tue, 09 Aug 2005 22:38:09 -0700 $ * $Revision: 1.7.1.10 $ * Description: GASNet UDP conduit Implementation * Copyright 2002, Dan Bonachea * Terms of use are as specified in license.txt */ #include #include #include #include #include #include #include #include GASNETI_IDENT(gasnetc_IdentString_Version, "$GASNetCoreLibraryVersion: " GASNET_CORE_VERSION_STR " $"); GASNETI_IDENT(gasnetc_IdentString_ConduitName, "$GASNetConduitName: " GASNET_CORE_NAME_STR " $"); gasnet_handlerentry_t const *gasnetc_get_handlertable(); static void gasnetc_atexit(void); static void gasnetc_traceoutput(int); eb_t gasnetc_bundle; ep_t gasnetc_endpoint; gasneti_mutex_t gasnetc_AMlock = GASNETI_MUTEX_INITIALIZER; /* protect access to AMUDP */ #if GASNET_TRACE extern void gasnetc_enteringHandler_hook(amudp_category_t cat, int isReq, int handlerId, void *token, void *buf, size_t nbytes, int numargs, uint32_t *args); extern void gasnetc_leavingHandler_hook(amudp_category_t cat, int isReq); #endif #if defined(GASNET_CSPAWN_CMD) #define GASNETC_DEFAULT_SPAWNFN C GASNETI_IDENT(gasnetc_IdentString_Default_CSpawnCommand, "$GASNetCSpawnCommand: " GASNET_CSPAWN_CMD " $"); #elif defined(REXEC) #define GASNETC_DEFAULT_SPAWNFN R #else /* AMUDP implicit ssh startup */ #define GASNETC_DEFAULT_SPAWNFN S #endif GASNETI_IDENT(gasnetc_IdentString_DefaultSpawnFn, "$GASNetDefaultSpawnFunction: " _STRINGIFY(GASNETC_DEFAULT_SPAWNFN) " $"); /* ------------------------------------------------------------------------------------ */ /* Initialization ============== */ /* called at startup to check configuration sanity */ static void gasnetc_check_config() { gasneti_check_config_preinit(); gasneti_assert(GASNET_MAXNODES <= AMUDP_MAX_SPMDPROCS); gasneti_assert(AMUDP_MAX_NUMHANDLERS >= 256); gasneti_assert(AMUDP_MAX_SEGLENGTH == (uintptr_t)-1); gasneti_assert(GASNET_ERR_NOT_INIT == AM_ERR_NOT_INIT); gasneti_assert(GASNET_ERR_RESOURCE == AM_ERR_RESOURCE); gasneti_assert(GASNET_ERR_BAD_ARG == AM_ERR_BAD_ARG); } #define gasnetc_bootstrapBarrier() \ AM_ASSERT_LOCKED(); /* need this because SPMDBarrier may poll */ \ if (!GASNETI_AM_SAFE_NORETURN(AMUDP_SPMDBarrier())) \ gasneti_fatalerror("failure in gasnetc_bootstrapBarrier()") void gasnetc_bootstrapExchange(void *src, size_t len, void *dest) { GASNETI_AM_SAFE_NORETURN(AMUDP_SPMDAllGather(src, dest, len)); } #define INITERR(type, reason) do { \ if (gasneti_VerboseErrors) { \ fprintf(stderr, "GASNet initialization encountered an error: %s\n" \ " in %s at %s:%i\n", \ #reason, GASNETI_CURRENT_FUNCTION, __FILE__, __LINE__); \ } \ retval = GASNET_ERR_ ## type; \ goto done; \ } while (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)) { /* 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 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 {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 {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[255]; sprintf(spawnstr,"%c",toupper(spawnfn)); gasneti_setenv("GASNET_SPAWNFN",spawnstr); } 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 */ NULL, &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 #if GASNET_SEGMENT_FAST || GASNET_SEGMENT_LARGE gasneti_segmentInit((uintptr_t)-1, &gasnetc_bootstrapExchange); #elif GASNET_SEGMENT_EVERYTHING /* segment is everything - nothing to do */ #else #error Bad segment config #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); } /* ------------------------------------------------------------------------------------ */ extern int gasnet_init(int *argc, char ***argv) { int retval = gasnetc_init(argc, argv); if (retval != GASNET_OK) GASNETI_RETURN(retval); #if 0 /* called within gasnet_init to allow init tracing */ gasneti_trace_init(argc, argv); #endif return GASNET_OK; } /* ------------------------------------------------------------------------------------ */ static char checkuniqhandler[256] = { 0 }; static int gasnetc_reghandlers(gasnet_handlerentry_t *table, int numentries, int lowlimit, int highlimit, int dontcare, int *numregistered) { int i; *numregistered = 0; for (i = 0; i < numentries; i++) { int newindex; if ((table[i].index == 0 && !dontcare) || (table[i].index && dontcare)) continue; else if (table[i].index) newindex = table[i].index; else { /* deterministic assignment of dontcare indexes */ for (newindex = lowlimit; newindex <= highlimit; newindex++) { if (!checkuniqhandler[newindex]) break; } if (newindex > highlimit) { char s[255]; sprintf(s,"Too many handlers. (limit=%i)", highlimit - lowlimit + 1); GASNETI_RETURN_ERRR(BAD_ARG, s); } } /* ensure handlers fall into the proper range of pre-assigned values */ if (newindex < lowlimit || newindex > highlimit) { char s[255]; sprintf(s, "handler index (%i) out of range [%i..%i]", newindex, lowlimit, highlimit); GASNETI_RETURN_ERRR(BAD_ARG, s); } /* discover duplicates */ if (checkuniqhandler[newindex] != 0) GASNETI_RETURN_ERRR(BAD_ARG, "handler index not unique"); checkuniqhandler[newindex] = 1; /* register the handler */ if (AM_SetHandler(gasnetc_endpoint, (handler_t)newindex, table[i].fnptr) != AM_OK) GASNETI_RETURN_ERRR(RESOURCE, "AM_SetHandler() failed while registering handlers"); /* The check below for !table[i].index is redundant and present * only to defeat the over-aggressive optimizer in pathcc 2.1 */ if (dontcare && !table[i].index) table[i].index = newindex; (*numregistered)++; } 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 */ { /* 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); atexit(gasnetc_atexit); /* ------------------------------------------------------------------------------------ */ /* register segment */ gasneti_seginfo = (gasnet_seginfo_t *)gasneti_malloc(gasneti_nodes*sizeof(gasnet_seginfo_t)); #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= 0 && sourceid < gasneti_nodes); *srcindex = sourceid; return GASNET_OK; } else GASNETI_RETURN_ERR(RESOURCE); } extern int gasnetc_AMPoll() { int retval; GASNETI_CHECKATTACH(); AMLOCK(); retval = GASNETI_AM_SAFE_NORETURN(AM_Poll(gasnetc_bundle)); AMUNLOCK(); if (retval) return GASNET_OK; else GASNETI_RETURN_ERR(RESOURCE); } /* ------------------------------------------------------------------------------------ */ /* Active Message Request Functions ================================ */ extern int gasnetc_AMRequestShortM( gasnet_node_t dest, /* destination node */ gasnet_handler_t handler, /* index into destination endpoint's handler table */ int numargs, ...) { int retval; va_list argptr; GASNETI_COMMON_AMREQUESTSHORT(dest,handler,numargs); va_start(argptr, numargs); /* pass in last argument */ AMLOCK_TOSEND(); retval = GASNETI_AM_SAFE_NORETURN( AMUDP_RequestVA(gasnetc_endpoint, dest, handler, numargs, argptr)); AMUNLOCK(); va_end(argptr); if (retval) return GASNET_OK; else GASNETI_RETURN_ERR(RESOURCE); } extern int gasnetc_AMRequestMediumM( gasnet_node_t dest, /* destination node */ gasnet_handler_t handler, /* index into destination endpoint's handler table */ void *source_addr, size_t nbytes, /* data payload */ int numargs, ...) { int retval; va_list argptr; GASNETI_COMMON_AMREQUESTMEDIUM(dest,handler,source_addr,nbytes,numargs); va_start(argptr, numargs); /* pass in last argument */ AMLOCK_TOSEND(); retval = GASNETI_AM_SAFE_NORETURN( AMUDP_RequestIVA(gasnetc_endpoint, dest, handler, source_addr, nbytes, numargs, argptr)); AMUNLOCK(); va_end(argptr); if (retval) return GASNET_OK; else GASNETI_RETURN_ERR(RESOURCE); } extern int gasnetc_AMRequestLongM( gasnet_node_t dest, /* destination node */ gasnet_handler_t handler, /* index into destination endpoint's handler table */ void *source_addr, size_t nbytes, /* data payload */ void *dest_addr, /* data destination on destination node */ int numargs, ...) { int retval; uintptr_t dest_offset; va_list argptr; GASNETI_COMMON_AMREQUESTLONG(dest,handler,source_addr,nbytes,dest_addr,numargs); dest_offset = ((uintptr_t)dest_addr) - ((uintptr_t)gasneti_seginfo[dest].addr); va_start(argptr, numargs); /* pass in last argument */ AMLOCK_TOSEND(); retval = GASNETI_AM_SAFE_NORETURN( AMUDP_RequestXferVA(gasnetc_endpoint, dest, handler, source_addr, nbytes, dest_offset, 0, numargs, argptr)); AMUNLOCK(); va_end(argptr); if (retval) return GASNET_OK; else GASNETI_RETURN_ERR(RESOURCE); } extern int gasnetc_AMReplyShortM( gasnet_token_t token, /* token provided on handler entry */ gasnet_handler_t handler, /* index into destination endpoint's handler table */ int numargs, ...) { int retval; va_list argptr; GASNETI_COMMON_AMREPLYSHORT(token,handler,numargs); va_start(argptr, numargs); /* pass in last argument */ AM_ASSERT_LOCKED(); retval = GASNETI_AM_SAFE_NORETURN( AMUDP_ReplyVA(token, handler, numargs, argptr)); va_end(argptr); if (retval) return GASNET_OK; else GASNETI_RETURN_ERR(RESOURCE); } extern int gasnetc_AMReplyMediumM( gasnet_token_t token, /* token provided on handler entry */ gasnet_handler_t handler, /* index into destination endpoint's handler table */ void *source_addr, size_t nbytes, /* data payload */ int numargs, ...) { int retval; va_list argptr; GASNETI_COMMON_AMREPLYMEDIUM(token,handler,source_addr,nbytes,numargs); va_start(argptr, numargs); /* pass in last argument */ AM_ASSERT_LOCKED(); retval = GASNETI_AM_SAFE_NORETURN( AMUDP_ReplyIVA(token, handler, source_addr, nbytes, numargs, argptr)); va_end(argptr); if (retval) return GASNET_OK; else GASNETI_RETURN_ERR(RESOURCE); } extern int gasnetc_AMReplyLongM( gasnet_token_t token, /* token provided on handler entry */ gasnet_handler_t handler, /* index into destination endpoint's handler table */ void *source_addr, size_t nbytes, /* data payload */ void *dest_addr, /* data destination on destination node */ int numargs, ...) { int retval; uintptr_t dest_offset; gasnet_node_t dest; va_list argptr; GASNETI_COMMON_AMREPLYLONG(token,handler,source_addr,nbytes,dest_addr,numargs); GASNETI_SAFE_PROPAGATE(gasnet_AMGetMsgSource(token, &dest)); dest_offset = ((uintptr_t)dest_addr) - ((uintptr_t)gasneti_seginfo[dest].addr); va_start(argptr, numargs); /* pass in last argument */ AM_ASSERT_LOCKED(); retval = GASNETI_AM_SAFE_NORETURN( AMUDP_ReplyXferVA(token, handler, source_addr, nbytes, dest_offset, numargs, argptr)); va_end(argptr); if (retval) return GASNET_OK; else GASNETI_RETURN_ERR(RESOURCE); } /* ------------------------------------------------------------------------------------ */ /* No-interrupt sections ===================== This section is only required for conduits that may use interrupt-based handler dispatch See the GASNet spec and http://www.cs.berkeley.edu/~bonachea/upc/gasnet.html for philosophy and hints on efficiently implementing no-interrupt sections Note: the extended-ref implementation provides a thread-specific void* within the gasnete_threaddata_t data structure which is reserved for use by the core (and this is one place you'll probably want to use it) */ #if GASNETC_USE_INTERRUPTS #error interrupts not implemented extern void gasnetc_hold_interrupts() { GASNETI_CHECKATTACH(); /* add code here to disable handler interrupts for _this_ thread */ } extern void gasnetc_resume_interrupts() { GASNETI_CHECKATTACH(); /* add code here to re-enable handler interrupts for _this_ thread */ } #endif /* ------------------------------------------------------------------------------------ */ /* Handler-safe locks ================== */ #if !GASNETC_NULL_HSL extern void gasnetc_hsl_init (gasnet_hsl_t *hsl) { GASNETI_CHECKATTACH(); gasneti_mutex_init(&(hsl->lock)); #if GASNETC_USE_INTERRUPTS /* add code here to init conduit-specific HSL state */ #error interrupts not implemented #endif } extern void gasnetc_hsl_destroy(gasnet_hsl_t *hsl) { GASNETI_CHECKATTACH(); gasneti_mutex_destroy(&(hsl->lock)); #if GASNETC_USE_INTERRUPTS /* add code here to cleanup conduit-specific HSL state */ #error interrupts not implemented #endif } extern void gasnetc_hsl_lock (gasnet_hsl_t *hsl) { GASNETI_CHECKATTACH(); { #if GASNETI_STATS_OR_TRACE gasneti_stattime_t startlock = GASNETI_STATTIME_NOW_IFENABLED(L); #endif #if GASNETC_HSL_SPINLOCK while (gasneti_mutex_trylock(&(hsl->lock)) == EBUSY) { } #else gasneti_mutex_lock(&(hsl->lock)); #endif #if GASNETI_STATS_OR_TRACE hsl->acquiretime = GASNETI_STATTIME_NOW_IFENABLED(L); GASNETI_TRACE_EVENT_TIME(L, HSL_LOCK, hsl->acquiretime-startlock); #endif } #if GASNETC_USE_INTERRUPTS /* conduits with interrupt-based handler dispatch need to add code here to disable handler interrupts on _this_ thread, (if this is the outermost HSL lock acquire and we're not inside an enclosing no-interrupt section) */ #error interrupts not implemented #endif } extern void gasnetc_hsl_unlock (gasnet_hsl_t *hsl) { GASNETI_CHECKATTACH(); #if GASNETC_USE_INTERRUPTS /* conduits with interrupt-based handler dispatch need to add code here to re-enable handler interrupts on _this_ thread, (if this is the outermost HSL lock release and we're not inside an enclosing no-interrupt section) */ #error interrupts not implemented #endif GASNETI_TRACE_EVENT_TIME(L, HSL_UNLOCK, GASNETI_STATTIME_NOW_IFENABLED(L)-hsl->acquiretime); gasneti_mutex_unlock(&(hsl->lock)); } extern int gasnetc_hsl_trylock(gasnet_hsl_t *hsl) { GASNETI_CHECKATTACH(); { int locked = (gasneti_mutex_trylock(&(hsl->lock)) == 0); GASNETI_TRACE_EVENT_VAL(L, HSL_TRYLOCK, locked); if (locked) { #if GASNETI_STATS_OR_TRACE hsl->acquiretime = GASNETI_STATTIME_NOW_IFENABLED(L); #endif #if GASNETC_USE_INTERRUPTS /* conduits with interrupt-based handler dispatch need to add code here to disable handler interrupts on _this_ thread, (if this is the outermost HSL lock acquire and we're not inside an enclosing no-interrupt section) */ #error interrupts not implemented #endif } return locked ? GASNET_OK : GASNET_ERR_NOT_READY; } } #endif /* ------------------------------------------------------------------------------------ */ #if GASNET_TRACE /* called when entering/leaving handler - also called when entering/leaving AM_Reply call */ extern void gasnetc_enteringHandler_hook(amudp_category_t cat, int isReq, int handlerId, void *token, void *buf, size_t nbytes, int numargs, uint32_t *args) { switch (cat) { case amudp_Short: if (isReq) GASNETI_TRACE_AMSHORT_REQHANDLER(handlerId, token, numargs, args); else GASNETI_TRACE_AMSHORT_REPHANDLER(handlerId, token, numargs, args); break; case amudp_Medium: if (isReq) GASNETI_TRACE_AMMEDIUM_REQHANDLER(handlerId, token, buf, nbytes, numargs, args); else GASNETI_TRACE_AMMEDIUM_REPHANDLER(handlerId, token, buf, nbytes, numargs, args); break; case amudp_Long: if (isReq) GASNETI_TRACE_AMLONG_REQHANDLER(handlerId, token, buf, nbytes, numargs, args); else GASNETI_TRACE_AMLONG_REPHANDLER(handlerId, token, buf, nbytes, numargs, args); break; default: gasneti_fatalerror("Unknown handler type in gasnetc_enteringHandler_hook(): %i", cat); } } extern void gasnetc_leavingHandler_hook(amudp_category_t cat, int isReq) { switch (cat) { case amudp_Short: GASNETI_TRACE_PRINTF(A,("AM%s_SHORT_HANDLER: handler execution complete", (isReq?"REQUEST":"REPLY"))); \ break; case amudp_Medium: GASNETI_TRACE_PRINTF(A,("AM%s_MEDIUM_HANDLER: handler execution complete", (isReq?"REQUEST":"REPLY"))); \ break; case amudp_Long: GASNETI_TRACE_PRINTF(A,("AM%s_LONG_HANDLER: handler execution complete", (isReq?"REQUEST":"REPLY"))); \ break; default: gasneti_fatalerror("Unknown handler type in gasnetc_leavingHandler_hook(): %i", cat); } } #endif /* ------------------------------------------------------------------------------------ */ /* Private Handlers: ================ see mpi-conduit and extended-ref for examples on how to declare AM handlers here (for internal conduit use in bootstrapping, job management, etc.) */ static gasnet_handlerentry_t const gasnetc_handlers[] = { #ifdef GASNETC_AUXSEG_HANDLERS GASNETC_AUXSEG_HANDLERS(), #endif /* ptr-width independent handlers */ /* ptr-width dependent handlers */ { 0, NULL } }; gasnet_handlerentry_t const *gasnetc_get_handlertable() { return gasnetc_handlers; } /* ------------------------------------------------------------------------------------ */