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