X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FMain.c;h=83fb11527f12a6831bad747aa540b8813cbdf064;hb=fb7a723bfd7650a705cb226e07c5b08b7a8e9279;hp=990c9ebb9cb8de54c846f6c3d10e785244033452;hpb=720dedcefbaac7553a171376ff6276983092c9ef;p=ghc-hetmet.git diff --git a/ghc/rts/Main.c b/ghc/rts/Main.c index 990c9eb..83fb115 100644 --- a/ghc/rts/Main.c +++ b/ghc/rts/Main.c @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- - * $Id: Main.c,v 1.8 1999/05/10 10:06:24 sof Exp $ + * $Id: Main.c,v 1.31 2001/09/04 18:29:21 ken Exp $ * - * (c) The GHC Team 1998-1999 + * (c) The GHC Team 1998-2000 * * Main function for a standalone Haskell program. * @@ -9,102 +9,131 @@ #define COMPILING_RTS_MAIN +#include "PosixSource.h" #include "Rts.h" #include "RtsAPI.h" +#include "SchedAPI.h" #include "RtsFlags.h" -#include "Schedule.h" /* for MainTSO */ #include "RtsUtils.h" +#include "Prelude.h" #ifdef DEBUG -#include "Printer.h" /* for printing */ +# include "Printer.h" /* for printing */ #endif #ifdef INTERPRETER -#include "Assembler.h" +# include "Assembler.h" #endif #ifdef PAR -#include "ParInit.h" -#include "Parallel.h" -#include "LLC.h" +# include "Parallel.h" +# include "ParallelRts.h" +# include "LLC.h" #endif -#ifdef HAVE_WINDOWS_H -#include +#if defined(GRAN) || defined(PAR) +# include "GranSimRts.h" #endif +#ifdef HAVE_WINDOWS_H +# include +#endif -#ifndef ENABLE_WIN32_DLL_SUPPORT +extern void __stginit_PrelMain(void); /* Hack: we assume that we're building a batch-mode system unless * INTERPRETER is set */ -# ifndef INTERPRETER /* Hack */ +#ifndef INTERPRETER /* Hack */ int main(int argc, char *argv[]) { + int exit_status; SchedulerStatus status; - startupHaskell(argc,argv); - -# ifndef PAR - MainTSO = createIOThread(stg_max(BLOCK_SIZE_W, - RtsFlags.GcFlags.initialStkSize), - (StgClosure *)&mainIO_closure); - status = schedule(MainTSO,NULL); -# else + /* all GranSim/GUM init is done in startupHaskell; sets IAmMainThread! */ + + startupHaskell(argc,argv,__stginit_PrelMain); + + /* kick off the computation by creating the main thread with a pointer + to mainIO_closure representing the computation of the overall program; + then enter the scheduler with this thread and off we go; + + the same for GranSim (we have only one instance of this code) + + in a parallel setup, where we have many instances of this code + running on different PEs, we should do this only for the main PE + (IAmMainThread is set in startupHaskell) + */ + +# if defined(PAR) + +# if defined(DEBUG) + { /* a wait loop to allow attachment of gdb to UNIX threads */ + nat i, j, s; + + for (i=0, s=0; i<(nat)RtsFlags.ParFlags.wait; i++) + for (j=0; j<1000000; j++) + s += j % 65536; + } + IF_PAR_DEBUG(verbose, + belch("Passed wait loop")); +# endif + if (IAmMainThread == rtsTrue) { - /*Just to show we're alive */ - fprintf(stderr, "Main Thread Started ...\n"); - - MainTSO = createIOThread(stg_max(BLOCK_SIZE_W, - RtsFlags.GcFlags.initialStkSize), - (StgClosure *)&mainIO_closure); - status = schedule(MainTSO,NULL); + IF_PAR_DEBUG(verbose, + fprintf(stderr, "==== [%x] Main Thread Started ...\n", mytid)); + + /* ToDo: Dump event for the main thread */ + status = rts_evalIO((HaskellObj)mainIO_closure, NULL); } else { - WaitForPEOp(PP_FINISH,SysManTask); - exit(EXIT_SUCCESS); + /* Just to show we're alive */ + IF_PAR_DEBUG(verbose, + fprintf(stderr, "== [%x] Non-Main PE enters scheduler via taskStart() without work ...\n", + mytid)); + + /* all non-main threads enter the scheduler without work */ + taskStart(); + status = Success; // declare victory (see shutdownParallelSystem) } -# endif /* PAR */ + +# elif defined(GRAN) + + /* ToDo: Dump event for the main thread */ + status = rts_evalIO(mainIO_closure, NULL); + +# else /* !PAR && !GRAN */ + + /* ToDo: want to start with a larger stack size */ + status = rts_evalIO((HaskellObj)mainIO_closure, NULL); + +# endif /* !PAR && !GRAN */ + + /* check the status of the entire Haskell computation */ switch (status) { - case AllBlocked: - barf("Scheduler stopped, all threads blocked"); case Deadlock: - shutdownHaskell(); - barf("No threads to run! Deadlock?"); + prog_belch("no threads to run: infinite loop or deadlock?"); + exit_status = EXIT_DEADLOCK; + break; case Killed: - belch("%s: warning: main thread killed", prog_argv[0]); - case Success: + prog_belch("main thread exited (uncaught exception)"); + exit_status = EXIT_KILLED; + break; case Interrupted: - /* carry on */ + prog_belch("interrupted"); + exit_status = EXIT_INTERRUPTED; + break; + case Success: + exit_status = EXIT_SUCCESS; + break; +#if defined(PAR) + case NoStatus: + prog_belch("main thread PE killed; probably due to failure of another PE; check /tmp/pvml..."); + exit_status = EXIT_KILLED; + break; +#endif + default: + barf("main thread completed with invalid status"); } - shutdownHaskell(); - stg_exit(EXIT_SUCCESS); + shutdownHaskellAndExit(exit_status); + return 0; /* never reached, keep gcc -Wall happy */ } # endif /* BATCH_MODE */ - -#else /* !ENABLE_WIN32_DLL_SUPPORT */ - -static char* args[] = { "ghcRts" }; - -BOOL -WINAPI -DllMain ( HINSTANCE hInstance - , DWORD reason - , LPVOID reserved - ) -{ - /* - ToDo: let the user configure RTS options to use - via the registry. - */ - switch (reason) { - case DLL_PROCESS_ATTACH: - startupHaskell(1,args); - /* ToDo: gracefully handle startupHaskell() failures.. */ - return TRUE; - case DLL_PROCESS_DETACH: - shutdownHaskell(); - } - return TRUE; -} - -#endif /* !ENABLE_WIN32_DLL_SUPPORT */