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