Keep C main separate from rts lib and link it in for standalone progs
[ghc.git] / rts / Main.c
index aff3011..58d3f37 100644 (file)
 /* -----------------------------------------------------------------------------
  *
- * (c) The GHC Team 1998-2000
+ * (c) The GHC Team 2009
  *
- * Main function for a standalone Haskell program.
+ * The C main() function for a standalone Haskell program.
+ *
+ * Note that this is not part of the RTS. It calls into the RTS to get things
+ * going. It is compiled to a separate Main.o which is linked into every
+ * standalone Haskell program that uses a Haskell Main.main function
+ * (as opposed to a mixed Haskell C program using a C main function).
  *
  * ---------------------------------------------------------------------------*/
 
-#define COMPILING_RTS_MAIN
-
-#include "PosixSource.h"
 #include "Rts.h"
-#include "RtsAPI.h"
-#include "SchedAPI.h"
-#include "RtsFlags.h"
-#include "RtsUtils.h"
-#include "Prelude.h"
-#include "Task.h"
-#if defined(mingw32_HOST_OS)
-#include "win32/seh_excn.h"
-#endif
-#include <stdlib.h>
-
-#ifdef DEBUG
-# include "Printer.h"   /* for printing        */
-#endif
-
-#ifdef PAR
-# include "Parallel.h"
-# include "ParallelRts.h"
-# include "LLC.h"
-#endif
+#include "RtsMain.h"
 
-#if defined(GRAN) || defined(PAR)
-# include "GranSimRts.h"
-#endif
-
-#ifdef HAVE_WINDOWS_H
-# include <windows.h>
-#endif
-
-extern void __stginit_ZCMain(void);
-
-static int progargc;
-static char **progargv;
-
-/* Hack: we assume that we're building a batch-mode system unless 
- * INTERPRETER is set
+/* The symbol for the Haskell Main module's init function. It is safe to refer
+ * to it here because this Main.o object file will only be linked in if we are
+ * linking a Haskell program that uses a Haskell Main.main function.
  */
-#ifndef INTERPRETER /* Hack */
-static void real_main(void)
-{
-    int exit_status;
-    SchedulerStatus status;
-    /* all GranSim/GUM init is done in startupHaskell; sets IAmMainThread! */
-
-    startupHaskell(progargc,progargv,__stginit_ZCMain);
-
-    /* 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) {
-      IF_PAR_DEBUG(verbose,
-                  debugBelch("==== [%x] Main Thread Started ...\n", mytid));
-
-      /* ToDo: Dump event for the main thread */
-      status = rts_mainLazyIO((HaskellObj)mainIO_closure, NULL);
-    } else {
-      /* Just to show we're alive */
-      IF_PAR_DEBUG(verbose,
-                  debugBelch("== [%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)
-    }
-
-#  elif defined(GRAN)
-
-    /* ToDo: Dump event for the main thread */
-    status = rts_mainLazyIO(mainIO_closure, NULL);
-
-#  else /* !PAR && !GRAN */
-
-    /* ToDo: want to start with a larger stack size */
-    { 
-       Capability *cap = rts_lock();
-       cap = rts_evalLazyIO(cap,(HaskellObj)(void *)mainIO_closure, NULL);
-       status = rts_getSchedStatus(cap);
-       taskTimeStamp(myTask());
-       rts_unlock(cap);
-    }
+extern void __stginit_ZCMain(void);
 
-#  endif /* !PAR && !GRAN */
+/* Similarly, we can refer to the ZCMain_main_closure here */
+extern StgClosure ZCMain_main_closure;
 
-    /* check the status of the entire Haskell computation */
-    switch (status) {
-    case Killed:
-      errorBelch("main thread exited (uncaught exception)");
-      exit_status = EXIT_KILLED;
-      break;
-    case Interrupted:
-      errorBelch("interrupted");
-      exit_status = EXIT_INTERRUPTED;
-      break;
-    case HeapExhausted:
-      exit_status = EXIT_HEAPOVERFLOW;
-      break;
-    case Success:
-      exit_status = EXIT_SUCCESS;
-      break;
-#if defined(PAR)
-    case NoStatus:
-      errorBelch("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");
-    }
-    shutdownHaskellAndExit(exit_status);
-}
 int main(int argc, char *argv[])
 {
-    /* We do this dance with argc and argv as otherwise the SEH exception
-       stuff (the BEGIN/END CATCH below) on Windows gets confused */
-    progargc = argc;
-    progargv = argv;
-
-#if defined(mingw32_HOST_OS)
-    BEGIN_CATCH
-#endif
-    real_main();
-#if defined(mingw32_HOST_OS)
-    END_CATCH
-#endif
-    return 0; /* not reached, but keeps gcc -Wall happy */
+    return hs_main(argc, argv, &__stginit_ZCMain, &ZCMain_main_closure);
 }
-# endif /* BATCH_MODE */