[project @ 1999-08-25 16:11:43 by simonmar]
[ghc-hetmet.git] / ghc / rts / RtsStartup.c
1 /* -----------------------------------------------------------------------------
2  * $Id: RtsStartup.c,v 1.18 1999/08/25 16:11:50 simonmar 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 "Signals.h"
19 #include "Itimer.h"
20 #include "Weak.h"
21 #include "Ticky.h"
22
23 #if defined(PROFILING)
24 # include "ProfRts.h"
25 #elif defined(DEBUG)
26 # include "DebugProf.h"
27 #endif
28
29 #ifdef PAR
30 #include "ParInit.h"
31 #include "Parallel.h"
32 #include "LLC.h"
33 #endif
34
35 /*
36  * Flag Structure
37  */
38 struct RTS_FLAGS RtsFlags;
39
40 static int rts_has_started_up = 0;
41
42 void
43 startupHaskell(int argc, char *argv[])
44 {
45 #ifdef ENABLE_WIN32_DLL_SUPPORT
46     int i;
47 #endif
48
49     /* To avoid repeated initialisations of the RTS */
50    if (rts_has_started_up)
51      return;
52    else
53      rts_has_started_up=1;
54
55 #if defined(PAR)
56     int nPEs = 0;                   /* Number of PEs */
57 #endif
58
59     /* The very first thing we do is grab the start time...just in case we're
60      * collecting timing statistics.
61      */
62     start_time();
63
64 #ifdef PAR
65 /*
66  *The parallel system needs to be initialised and synchronised before
67  *the program is run.  
68  */
69     if (*argv[0] == '-') {     /* Look to see whether we're the Main Thread */
70         IAmMainThread = rtsTrue;
71         argv++; argc--;                 /* Strip off flag argument */
72 /*      fprintf(stderr, "I am Main Thread\n"); */
73     }
74     /* 
75      * Grab the number of PEs out of the argument vector, and
76      * eliminate it from further argument processing.
77      */
78     nPEs = atoi(argv[1]);
79     argv[1] = argv[0];
80     argv++; argc--;
81     initEachPEHook();                  /* HWL: hook to be execed on each PE */
82     SynchroniseSystem();
83 #endif
84
85     /* Set the RTS flags to default values. */
86     initRtsFlagsDefaults();
87
88     /* Call the user hook to reset defaults, if present */
89     defaultsHook();
90
91     /* Parse the flags, separating the RTS flags from the programs args */
92     setupRtsFlags(&argc, argv, &rts_argc, rts_argv);
93     prog_argc = argc;
94     prog_argv = argv;
95
96 #ifdef PAR
97    /* Initialise the parallel system -- before initHeap! */
98     initParallelSystem();
99    /* And start GranSim profiling if required: omitted for now
100     *if (Rtsflags.ParFlags.granSimStats)
101     *init_gr_profiling(rts_argc, rts_argv, prog_argc, prog_argv);
102     */
103 #endif  /* PAR */
104
105     /* initialize the storage manager */
106     initStorage();
107
108     /* initialise the stable pointer table */
109     initStablePtrTable();
110
111 #if defined(PROFILING) || defined(DEBUG)
112     initProfiling();
113 #endif
114
115     /* start the ticker */
116     install_vtalrm_handler();
117     initialize_virtual_timer(TICK_MILLISECS);
118
119     /* Initialise the scheduler */
120     initScheduler();
121
122     /* Initialise the stats department */
123     initStats();
124
125     /* Initialise the user signal handler set */
126     initUserSignals();
127  
128     /* When the RTS and Prelude live in separate DLLs,
129        we need to patch up the char- and int-like tables
130        that the RTS keep after both DLLs have been loaded,
131        filling in the tables with references to where the
132        static info tables have been loaded inside the running
133        process.
134     */
135 #ifdef ENABLE_WIN32_DLL_SUPPORT
136     for(i=0;i<=255;i++)
137        (CHARLIKE_closure[i]).header.info = (const StgInfoTable*)&Czh_static_info;
138
139     for(i=0;i<=32;i++)
140        (INTLIKE_closure[i]).header.info = (const StgInfoTable*)&Izh_static_info;
141        
142 #endif
143     /* Record initialization times */
144     end_init();
145 }
146
147 /*
148  * Shutting down the RTS - two ways of doing this, one which
149  * calls exit(), one that doesn't.
150  *
151  * (shutdownHaskellAndExit() is called by System.exitWith).
152  */
153 void
154 shutdownHaskellAndExit(int n)
155 {
156   OnExitHook();
157   shutdownHaskell();
158   stg_exit(n);
159 }
160
161 void
162 shutdownHaskell(void)
163 {
164   if (!rts_has_started_up)
165      return;
166
167   /* Finalize any remaining weak pointers */
168   finalizeWeakPointersNow();
169
170 #if defined(GRAN)
171   #error FixMe.
172   if (!RTSflags.GranFlags.granSimStats_suppressed)
173     end_gr_simulation();
174 #endif
175
176   /* clean up things from the storage manager's point of view */
177   exitStorage();
178
179   /* stop the ticker */
180   initialize_virtual_timer(0);
181
182 #if defined(PROFILING) || defined(DEBUG)
183   endProfiling();
184 #endif
185
186 #if defined(PROFILING) 
187   report_ccs_profiling( );
188 #endif
189
190 #if defined(TICKY_TICKY)
191   if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
192 #endif
193
194   rts_has_started_up=0;
195 }
196
197
198 /* 
199  * called from STG-land to exit the program
200  */
201
202 void  
203 stg_exit(I_ n)
204 {
205 #ifdef PAR
206   par_exit(n);
207 #else
208   exit(n);
209 #endif
210 }
211