/* -------------------------------------------------------------------------- Initialising the parallel RTS An extension based on Kevin Hammond's GRAPH for PVM version P. Trinder, January 17th 1995. Adapted for the new RTS P. Trinder, July 1997. H-W. Loidl, November 1999. rewrite for Eden-6.x, Jost Berthold, 2006 adapted to Eden-6.11, August 2009 ------------------------------------------------------------------------ */ #include "Rts.h" #include "RtsUtils.h" #include "LLC.h" #include "HLC.h" #include "MPSystem.h" /* wraps middleware usage */ #include "Trace.h" #include #include "Stats.h" #include #ifndef PARALLEL_RTS /* provide constants nPE and thisPe for foreign import */ nat nPEs = 1; nat thisPE = 1; #endif #ifdef PARALLEL_RTS /* whole rest of the file */ #ifdef TRACING StgWord64 startupTicks; char *argvsave; struct timeval startupTime; struct timezone startupTimeZone; #endif //TRACING /* For flag handling see RtsFlags.h */ void shutdownParallelSystem(StgInt n) { IF_PAR_DEBUG(verbose, if (n==0) debugBelch("==== entered shutdownParallelSystem ...\n"); else debugBelch("==== entered shutdownParallelSystem (ERROR %d)...\n", (int) n); ); // JB 11/2006: write stop event, close trace file. Done here to // avoid a race condition if trace files merged by main node // automatically. //edentrace: traceKillMachine traceKillMachine(thisPE); MP_quit(n); // free allocated space (send/receive buffers) freePackBuffer(); freeRecvBuffer(); /* freeMoreBuffers(); */ // and runtime tables freeRTT(); } /* * SynchroniseSystem synchronises the reduction task with the system * manager, and initialises global structures: receive buffer for * communication, process table, and in GUM the Global address tables * (LAGA & GALA) */ //@cindex synchroniseSystem void synchroniseSystem(void) { MP_sync(); // all kinds of initialisation we can do now... // Don't buffer standard channels... setbuf(stdout,NULL); setbuf(stderr,NULL); // initialise runtime tables initRTT(); // care not to GC any CAFs. Incoming packets might refer to them // This variable lives in Storage.c keepCAFs = rtsTrue; // initialise "system tso" which owns blackholes and stores blocking queues SET_HDR(&stg_system_tso, &stg_TSO_info, CCS_SYSTEM); stg_system_tso.indirectee = (StgClosure*) END_TSO_QUEUE; } void emitStartupEvents(void){ //edentrace: traceCreateMachine //startupTicks was fetched earlier, CreateMachine has //to be the first Event writen to keep the order of the //timestamps in the buffers valid traceCreateMachine(thisPE,((startupTime.tv_sec) * 100000000 + (startupTime.tv_usec) * 100),startupTicks); //edentrace: traceVersion traceVersion(ProjectVersion); //edentrace: traceProgramInvocation traceProgramInvocation(argvsave); } /* Do the startup stuff (middleware-dependencies wrapped in MPSystem.h Global vars held in MPSystem: IAmMainThread, thisPE, nPEs Called at the beginning of RtsStartup.startupHaskell */ void startupParallelSystem(int* argc, char **argv[]) { // getStartTime(); // init start time (in RtsUtils.*) // write Event for machine startup here, before // communication is set up (might take a while) // JB 11/2006: thisPE is still 0 at this moment, we cannot name the // trace file here => startup time is in reality sync time. //MD/TH 03/2010: workaround: store timestamp here and use it in synchroniseSystem #ifdef TRACING startupTicks = stat_getElapsedTime(); // see Stats.c, elapsed time from init gettimeofday(&startupTime,&startupTimeZone); //MD: copy argument list to string for traceProgramInvocation int len = 0; int i=0; while (i < *argc){ len+=strlen((*argv)[i])+1; i++; } argvsave = (char *)calloc(len + 1, sizeof(char)); i=0; while (i < *argc){ strcat(argvsave,(*argv)[i]); strcat(argvsave," "); i++; } #endif //TRACING // possibly starts other PEs (first argv is number) // sets IAmMainThread, nPEs MP_start(argc, *argv); (*argv)[1] = (*argv)[0]; /* ignore the nPEs argument */ (*argv)++; (*argc)--; /* Only in debug mode? */ fprintf(stderr, "==== Starting parallel execution on %d processors ...\n", nPEs); } #endif /* PARALLEL_RTS -- whole file */