[project @ 2000-01-13 14:33:57 by hwloidl]
[ghc-hetmet.git] / ghc / rts / Main.c
1 /* -----------------------------------------------------------------------------
2  * $Id: Main.c,v 1.14 2000/01/13 14:34:03 hwloidl Exp $
3  *
4  * (c) The GHC Team 1998-1999
5  *
6  * Main function for a standalone Haskell program.
7  *
8  * ---------------------------------------------------------------------------*/
9
10 #define COMPILING_RTS_MAIN
11
12 #include "Rts.h"
13 #include "RtsAPI.h"
14 #include "SchedAPI.h"
15 #include "RtsFlags.h"
16 #include "RtsUtils.h"
17
18 #ifdef DEBUG
19 # include "Printer.h"   /* for printing        */
20 #endif
21
22 #ifdef INTERPRETER
23 # include "Assembler.h"
24 #endif
25
26 #ifdef PAR
27 # include "ParInit.h"
28 # include "Parallel.h"
29 # include "LLC.h"
30 #endif
31
32 #if defined(GRAN) || defined(PAR)
33 # include "GranSimRts.h"
34 #endif
35
36 #ifdef HAVE_WINDOWS_H
37 # include <windows.h>
38 #endif
39
40
41 /* Hack: we assume that we're building a batch-mode system unless 
42  * INTERPRETER is set
43  */
44 # ifndef INTERPRETER /* Hack */
45 int main(int argc, char *argv[])
46 {
47     int exit_status;
48     SchedulerStatus status;
49     /* all GranSim/GUM init is done in startupHaskell; sets IAmMainThread! */
50
51     startupHaskell(argc,argv);
52
53     /* kick off the computation by creating the main thread with a pointer
54        to mainIO_closure representing the computation of the overall program;
55        then enter the scheduler with this thread and off we go;
56       
57        the same for GranSim (we have only one instance of this code)
58
59        in a parallel setup, where we have many instances of this code
60        running on different PEs, we should do this only for the main PE
61        (IAmMainThread is set in startupHaskell) 
62     */
63
64 #  if defined(PAR)
65
66 #   if DEBUG
67     { /* a wait loop to allow attachment of gdb to UNIX threads */
68       nat i, j, s;
69
70       for (i=0, s=0; i<RtsFlags.ParFlags.wait; i++)
71         for (j=0; j<1000000; j++) 
72           s += j % 65536;
73     }
74     IF_PAR_DEBUG(verbose,
75                  belch("Passed wait loop"));
76 #   endif
77
78     if (IAmMainThread == rtsTrue) {
79       fprintf(stderr, "Main Thread Started ...\n");
80
81       /* ToDo: Dump event for the main thread */
82       status = rts_evalIO((StgClosure *)&mainIO_closure, NULL);
83     } else {
84       /* Just to show we're alive */
85       IF_PAR_DEBUG(verbose,
86                    fprintf(stderr, "== [%x] Non-Main PE enters scheduler without work ...\n",
87                            mytid));
88      
89       /* all non-main threads enter the scheduler without work */
90       status = schedule( /* nothing */ );
91     }
92
93 #  elif defined(GRAN)
94
95     /* ToDo: Dump event for the main thread */
96     status = rts_evalIO((StgClosure *)&mainIO_closure, NULL);
97
98 #  else /* !PAR && !GRAN */
99
100     /* ToDo: want to start with a larger stack size */
101     status = rts_evalIO((StgClosure *)&mainIO_closure, NULL);
102
103 #  endif /* !PAR && !GRAN */
104
105     // ToDo: update for parallel execution
106     /* check the status of the entire Haskell computation */
107     switch (status) {
108     case Deadlock:
109       prog_belch("no threads to run:  infinite loop or deadlock?");
110       exit_status = EXIT_DEADLOCK;
111       break;
112     case Killed:
113       prog_belch("main thread killed");
114       exit_status = EXIT_KILLED;
115       break;
116     case Interrupted:
117       prog_belch("interrupted");
118       exit_status = EXIT_INTERRUPTED;
119       break;
120     case Success:
121       exit_status = EXIT_SUCCESS;
122       break;
123     case NoStatus:
124       barf("main thread completed with no status");
125     }
126     shutdownHaskellAndExit(exit_status);
127 }
128 # endif /* BATCH_MODE */