[project @ 1999-02-05 16:02:18 by simonm]
[ghc-hetmet.git] / ghc / rts / RtsStartup.c
1 /* -----------------------------------------------------------------------------
2  * $Id: RtsStartup.c,v 1.6 1999/02/05 16:02:50 simonm Exp $
3  *
4  * (c) The GHC Team, 1998-1999
5  *
6  * Main function for a standalone Haskell program.
7  *
8  * ---------------------------------------------------------------------------*/
9
10 #include "Rts.h"
11 #include "RtsAPI.h"
12 #include "RtsUtils.h"
13 #include "RtsFlags.h"  
14 #include "Storage.h"    /* initStorage, exitStorage */
15 #include "StablePriv.h" /* initStablePtrTable */
16 #include "Schedule.h"   /* initScheduler */
17 #include "Stats.h"      /* initStats */
18 #include "Weak.h"
19 #include "Ticky.h"
20
21 #if defined(PROFILING)
22 # include "ProfRts.h"
23 #elif defined(DEBUG)
24 # include "DebugProf.h"
25 #endif
26
27 #ifdef PAR
28 #include "ParInit.h"
29 #include "Parallel.h"
30 #include "LLC.h"
31 #endif
32
33 /*
34  * Flag Structure
35  */
36 struct RTS_FLAGS RtsFlags;
37
38 extern void startupHaskell(int argc, char *argv[])
39 {
40 #if defined(PAR)
41     int nPEs = 0;                   /* Number of PEs */
42 #endif
43
44     /* The very first thing we do is grab the start time...just in case we're
45      * collecting timing statistics.
46      */
47     start_time();
48
49 #ifdef PAR
50 /*
51  *The parallel system needs to be initialised and synchronised before
52  *the program is run.  
53  */
54     if (*argv[0] == '-') {     /* Look to see whether we're the Main Thread */
55         IAmMainThread = rtsTrue;
56         argv++; argc--;                 /* Strip off flag argument */
57 /*      fprintf(stderr, "I am Main Thread\n"); */
58     }
59     /* 
60      * Grab the number of PEs out of the argument vector, and
61      * eliminate it from further argument processing.
62      */
63     nPEs = atoi(argv[1]);
64     argv[1] = argv[0];
65     argv++; argc--;
66     initEachPEHook();                  /* HWL: hook to be execed on each PE */
67     SynchroniseSystem();
68 #endif
69
70     /* Set the RTS flags to default values. */
71     initRtsFlagsDefaults();
72
73     /* Call the user hook to reset defaults, if present */
74     defaultsHook();
75
76     /* Parse the flags, separating the RTS flags from the programs args */
77     setupRtsFlags(&argc, argv, &rts_argc, rts_argv);
78     prog_argc = argc;
79     prog_argv = argv;
80
81 #if defined(PAR)
82    /* Initialise the parallel system -- before initHeap! */
83     initParallelSystem();
84    /* And start GranSim profiling if required: omitted for now
85     *if (Rtsflags.ParFlags.granSimStats)
86     *init_gr_profiling(rts_argc, rts_argv, prog_argc, prog_argv);
87     */
88 #endif  /* PAR */
89
90     /* initialize the storage manager */
91     initStorage();
92
93     /* initialise the stable pointer table */
94     initStablePtrTable();
95
96 #if defined(PROFILING) || defined(DEBUG)
97     initProfiling();
98 #endif
99
100     /* Initialise the scheduler */
101     initScheduler();
102
103     /* Initialise the stats department */
104     initStats();
105
106 #if 0
107     initUserSignals();
108 #endif
109
110     /* Record initialization times */
111     end_init();
112 }
113
114 void
115 shutdownHaskell(void)
116 {
117   /* Finalise any remaining weak pointers */
118   finaliseWeakPointersNow();
119
120 #if defined(GRAN)
121   #error FixMe.
122   if (!RTSflags.GranFlags.granSimStats_suppressed)
123     end_gr_simulation();
124 #endif
125
126   /* clean up things from the storage manager's point of view */
127   exitStorage();
128
129 #if defined(PROFILING) || defined(DEBUG)
130   endProfiling();
131 #endif
132
133 #if defined(PROFILING) 
134   report_ccs_profiling( );
135 #endif
136
137 #if defined(TICKY_TICKY)
138   if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
139 #endif
140
141   /*
142     This fflush is important, because: if "main" just returns,
143     then we will end up in pre-supplied exit code that will close
144     streams and flush buffers.  In particular we have seen: it
145     will close fd 0 (stdin), then flush fd 1 (stdout), then <who
146     cares>...
147     
148     But if you're playing with sockets, that "close fd 0" might
149     suggest to the daemon that all is over, only to be presented
150     with more stuff on "fd 1" at the flush.
151     
152     The fflush avoids this sad possibility.
153    */
154   fflush(stdout);
155 }
156
157
158 /* 
159  * called from STG-land to exit the program cleanly 
160  */
161
162 void  
163 stg_exit(I_ n)
164 {
165 #ifdef PAR
166   par_exit(n);
167 #else
168   OnExitHook();
169   exit(n);
170 #endif
171 }