1 /* -----------------------------------------------------------------------------
2 * $Id: Main.c,v 1.28 2001/07/26 03:20:52 ken Exp $
4 * (c) The GHC Team 1998-2000
6 * Main function for a standalone Haskell program.
8 * ---------------------------------------------------------------------------*/
10 #define COMPILING_RTS_MAIN
20 # include "Printer.h" /* for printing */
24 # include "Assembler.h"
28 # include "Parallel.h"
29 # include "ParallelRts.h"
33 #if defined(GRAN) || defined(PAR)
34 # include "GranSimRts.h"
45 extern void __init_PrelMain(void);
47 /* Hack: we assume that we're building a batch-mode system unless
50 #ifndef INTERPRETER /* Hack */
51 int main(int argc, char *argv[])
54 SchedulerStatus status;
55 /* all GranSim/GUM init is done in startupHaskell; sets IAmMainThread! */
58 * Believe it or not, calling tzset() at startup seems to get rid of
59 * a scheduler-related Heisenbug on alpha-dec-osf3. The symptom of
60 * the bug is that, when the load on the machine is high or when
61 * there are many threads, the variable "Capability *cap" in the
62 * function "schedule" in the file "Schedule.c" magically becomes
63 * null before the line "t = cap->rCurrentTSO;". Why, and why does
64 * calling tzset() here seem to fix it? Excellent questions!
68 startupHaskell(argc,argv,__init_PrelMain);
70 /* kick off the computation by creating the main thread with a pointer
71 to mainIO_closure representing the computation of the overall program;
72 then enter the scheduler with this thread and off we go;
74 the same for GranSim (we have only one instance of this code)
76 in a parallel setup, where we have many instances of this code
77 running on different PEs, we should do this only for the main PE
78 (IAmMainThread is set in startupHaskell)
84 { /* a wait loop to allow attachment of gdb to UNIX threads */
87 for (i=0, s=0; i<(nat)RtsFlags.ParFlags.wait; i++)
88 for (j=0; j<1000000; j++)
92 belch("Passed wait loop"));
95 if (IAmMainThread == rtsTrue) {
97 fprintf(stderr, "==== [%x] Main Thread Started ...\n", mytid));
99 /* ToDo: Dump event for the main thread */
100 status = rts_evalIO((HaskellObj)mainIO_closure, NULL);
102 /* Just to show we're alive */
103 IF_PAR_DEBUG(verbose,
104 fprintf(stderr, "== [%x] Non-Main PE enters scheduler via taskStart() without work ...\n",
107 /* all non-main threads enter the scheduler without work */
109 status = Success; // declare victory (see shutdownParallelSystem)
114 /* ToDo: Dump event for the main thread */
115 status = rts_evalIO(mainIO_closure, NULL);
117 # else /* !PAR && !GRAN */
119 /* ToDo: want to start with a larger stack size */
120 status = rts_evalIO((HaskellObj)mainIO_closure, NULL);
122 # endif /* !PAR && !GRAN */
124 /* check the status of the entire Haskell computation */
127 prog_belch("no threads to run: infinite loop or deadlock?");
128 exit_status = EXIT_DEADLOCK;
131 prog_belch("main thread exited (uncaught exception)");
132 exit_status = EXIT_KILLED;
135 prog_belch("interrupted");
136 exit_status = EXIT_INTERRUPTED;
139 exit_status = EXIT_SUCCESS;
143 prog_belch("main thread PE killed; probably due to failure of another PE; check /tmp/pvml...");
144 exit_status = EXIT_KILLED;
148 barf("main thread completed with invalid status");
150 shutdownHaskellAndExit(exit_status);
151 return 0; /* never reached, keep gcc -Wall happy */
153 # endif /* BATCH_MODE */