rts: Claim AP_STACK before adjusting Sp
[ghc.git] / rts / RtsMain.c
index e89445d..d9f0557 100644 (file)
 #include "RtsUtils.h"
 #include "Prelude.h"
 #include "Task.h"
-#if defined(mingw32_HOST_OS)
-#include "win32/seh_excn.h"
-#endif
+#include "Excn.h"
 
-#ifdef DEBUG
+#if defined(DEBUG)
 # include "Printer.h"   /* for printing        */
 #endif
 
-#ifdef HAVE_WINDOWS_H
-# include <windows.h>
-#endif
+// Hack: we assume that we're building a batch-mode system unless
+// INTERPRETER is set
+#if !defined(INTERPRETER) /* Hack */
 
-/* Annoying global vars for passing parameters to real_main() below
- * This is to get around problem with Windows SEH, see hs_main(). */
-static int progargc;
-static char **progargv;
-static StgClosure *progmain_closure;  /* This will be ZCMain_main_closure */
-static RtsConfig rtsconfig;
+// The rts entry point from a compiled program using a Haskell main
+// function.  This gets called from a tiny main function generated by
+// GHC and linked into each compiled Haskell program that uses a
+// Haskell main function.
+// 
+// We expect the caller to pass ZCMain_main_closure for
+// main_closure. The reason we cannot refer to this symbol directly
+// is because we're inside the rts and we do not know for sure that
+// we'll be using a Haskell main function.
+// 
+// NOTE: This function is marked as _noreturn_ in Main.h
 
-/* Hack: we assume that we're building a batch-mode system unless
- * INTERPRETER is set
- */
-#ifndef INTERPRETER /* Hack */
-static void real_main(void) GNUC3_ATTRIBUTE(__noreturn__);
-static void real_main(void)
+int hs_main ( int argc, char *argv[],       // program args
+              StgClosure *main_closure,     // closure for Main.main
+              RtsConfig rts_config)         // RTS configuration
+              
 {
+    BEGIN_WINDOWS_VEH_HANDLER
+
     int exit_status;
     SchedulerStatus status;
 
-    hs_init_ghc(&progargc, &progargv, rtsconfig);
+    hs_init_ghc(&argc, &argv, rts_config);
 
-    /* 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)
+    // 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;
+    // 
+    // 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)
 
-       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) 
-    */
-
-    /* ToDo: want to start with a larger stack size */
-    { 
-       Capability *cap = rts_lock();
-        rts_evalLazyIO(&cap,progmain_closure, NULL);
-       status = rts_getSchedStatus(cap);
+    // ToDo: want to start with a larger stack size
+    {
+        Capability *cap = rts_lock();
+        rts_evalLazyIO(&cap, main_closure, NULL);
+        status = rts_getSchedStatus(cap);
         rts_unlock(cap);
     }
 
-    /* check the status of the entire Haskell computation */
+    // check the status of the entire Haskell computation
     switch (status) {
     case Killed:
-      errorBelch("main thread exited (uncaught exception)");
-      exit_status = EXIT_KILLED;
-      break;
+        errorBelch("main thread exited (uncaught exception)");
+        exit_status = EXIT_KILLED;
+        break;
     case Interrupted:
-      errorBelch("interrupted");
-      exit_status = EXIT_INTERRUPTED;
-      break;
+        errorBelch("interrupted");
+        exit_status = EXIT_INTERRUPTED;
+        break;
     case HeapExhausted:
-      exit_status = EXIT_HEAPOVERFLOW;
-      break;
+        exit_status = EXIT_HEAPOVERFLOW;
+        break;
     case Success:
-      exit_status = EXIT_SUCCESS;
-      break;
+        exit_status = EXIT_SUCCESS;
+        break;
     default:
-      barf("main thread completed with invalid status");
+        barf("main thread completed with invalid status");
     }
-    shutdownHaskellAndExit(exit_status);
-}
 
-/* The rts entry point from a compiled program using a Haskell main
- * function.  This gets called from a tiny main function generated by
- * GHC and linked into each compiled Haskell program that uses a
- * Haskell main function.
- *
- * We expect the caller to pass ZCMain_main_closure for
- * main_closure. The reason we cannot refer to this symbol directly
- * is because we're inside the rts and we do not know for sure that
- * we'll be using a Haskell main function.
- */
-int hs_main (int argc, char *argv[],     // program args
-             StgClosure *main_closure,   // closure for Main.main
-             RtsConfig rts_config)    // RTS configuration
-{
-    /* 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;
-    progmain_closure = main_closure;
-    rtsconfig = rts_config;
+    END_WINDOWS_VEH_HANDLER
 
-#if defined(mingw32_HOST_OS)
-    BEGIN_CATCH
-#endif
-    real_main();
-#if defined(mingw32_HOST_OS)
-    END_CATCH
-#endif
+    shutdownHaskellAndExit(exit_status, 0 /* !fastExit */);
+    // No code beyond this point. Dead code elimination will remove it 
 }
 # endif /* BATCH_MODE */