[project @ 2000-02-17 17:19:42 by simonmar]
[ghc-hetmet.git] / ghc / rts / RtsStartup.c
1 /* -----------------------------------------------------------------------------
2  * $Id: RtsStartup.c,v 1.29 2000/02/17 17:19:42 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) || defined(DEBUG)
24 # include "ProfRts.h"
25 # include "ProfHeap.h"
26 #endif
27
28 #if defined(GRAN)
29 #include "GranSimRts.h"
30 #include "ParallelRts.h"
31 #endif
32
33 #if defined(PAR)
34 #include "ParInit.h"
35 #include "Parallel.h"
36 #include "LLC.h"
37 #endif
38
39 /*
40  * Flag Structure
41  */
42 struct RTS_FLAGS RtsFlags;
43
44 static int rts_has_started_up = 0;
45 #if defined(PAR)
46 static ullong startTime = 0;
47 #endif
48
49 void
50 startupHaskell(int argc, char *argv[])
51 {
52 #ifdef ENABLE_WIN32_DLL_SUPPORT
53     int i;
54 #endif
55
56     /* To avoid repeated initialisations of the RTS */
57    if (rts_has_started_up)
58      return;
59    else
60      rts_has_started_up=1;
61
62     /* The very first thing we do is grab the start time...just in case we're
63      * collecting timing statistics.
64      */
65     start_time();
66
67 #ifdef PAR
68 /*
69  * The parallel system needs to be initialised and synchronised before
70  * the program is run.  
71  */
72     fprintf(stderr, "startupHaskell: argv[0]=%s\n", argv[0]);
73     if (*argv[0] == '-') {     /* Look to see whether we're the Main Thread */
74         IAmMainThread = rtsTrue;
75         argv++; argc--;                 /* Strip off flag argument */
76         // IF_PAR_DEBUG(verbose,
77                      fprintf(stderr, "[%x] I am Main Thread\n", mytid);
78     }
79     /* 
80      * Grab the number of PEs out of the argument vector, and
81      * eliminate it from further argument processing.
82      */
83     nPEs = atoi(argv[1]);
84     argv[1] = argv[0];
85     argv++; argc--;
86     initEachPEHook();                  /* HWL: hook to be execed on each PE */
87 #endif
88
89     /* Set the RTS flags to default values. */
90     initRtsFlagsDefaults();
91
92     /* Call the user hook to reset defaults, if present */
93     defaultsHook();
94
95     /* Parse the flags, separating the RTS flags from the programs args */
96     setupRtsFlags(&argc, argv, &rts_argc, rts_argv);
97     prog_argc = argc;
98     prog_argv = argv;
99
100 #if defined(PAR)
101     /* NB: this really must be done after processing the RTS flags */
102     fprintf(stderr, "Synchronising system (%d PEs)\n", nPEs);
103     SynchroniseSystem();             // calls initParallelSystem etc
104 #endif  /* PAR */
105
106     /* initialise scheduler data structures (needs to be done before
107      * initStorage()).
108      */
109     initScheduler();
110
111 #if defined(GRAN)
112     /* And start GranSim profiling if required: */
113     if (RtsFlags.GranFlags.GranSimStats.Full)
114       init_gr_simulation(rts_argc, rts_argv, prog_argc, prog_argv);
115 #elif defined(PAR)
116     /* And start GUM profiling if required: */
117     if (RtsFlags.ParFlags.ParStats.Full)
118       init_gr_simulation(rts_argc, rts_argv, prog_argc, prog_argv);
119 #endif  /* PAR || GRAN */
120
121     /* initialize the storage manager */
122     initStorage();
123
124     /* initialise the stable pointer table */
125     initStablePtrTable();
126
127 #if defined(PROFILING) || defined(DEBUG)
128     initProfiling();
129 #endif
130
131     /* start the ticker */
132     install_vtalrm_handler();
133     initialize_virtual_timer(TICK_MILLISECS);
134
135     /* start our haskell execution tasks */
136 #ifdef SMP
137     startTasks();
138 #endif
139
140     /* Initialise the stats department */
141     initStats();
142
143 #if !defined(mingw32_TARGET_OS) && !defined(PAR)
144     /* Initialise the user signal handler set */
145     initUserSignals();
146     /* Set up handler to run on SIGINT */
147     init_shutdown_handler();
148 #endif
149  
150     /* When the RTS and Prelude live in separate DLLs,
151        we need to patch up the char- and int-like tables
152        that the RTS keep after both DLLs have been loaded,
153        filling in the tables with references to where the
154        static info tables have been loaded inside the running
155        process.
156     */
157 #ifdef ENABLE_WIN32_DLL_SUPPORT
158     for(i=0;i<=255;i++)
159        (CHARLIKE_closure[i]).header.info = (const StgInfoTable*)&Czh_static_info;
160
161     for(i=0;i<=32;i++)
162        (INTLIKE_closure[i]).header.info = (const StgInfoTable*)&Izh_static_info;
163        
164 #endif
165     /* Record initialization times */
166     end_init();
167 }
168
169 /*
170  * Shutting down the RTS - two ways of doing this, one which
171  * calls exit(), one that doesn't.
172  *
173  * (shutdownHaskellAndExit() is called by System.exitWith).
174  */
175 void
176 shutdownHaskellAndExit(int n)
177 {
178   OnExitHook();
179   shutdownHaskell();
180   stg_exit(n);
181 }
182
183 void
184 shutdownHaskell(void)
185 {
186   if (!rts_has_started_up)
187      return;
188
189   /* start timing the shutdown */
190   stat_startExit();
191
192 #if !defined(GRAN)
193   /* Finalize any remaining weak pointers */
194   finalizeWeakPointersNow();
195 #endif
196
197 #if defined(GRAN)
198   /* end_gr_simulation prints global stats if requested -- HWL */
199   if (!RtsFlags.GranFlags.GranSimStats.Suppressed)
200     end_gr_simulation();
201 #endif
202
203   /* stop all running tasks */
204   exitScheduler();
205
206   /* stop the ticker */
207   initialize_virtual_timer(0);
208   
209   /* reset the standard file descriptors to blocking mode */
210   resetNonBlockingFd(0);
211   resetNonBlockingFd(1);
212   resetNonBlockingFd(2);
213
214   /* stop timing the shutdown, we're about to print stats */
215   stat_endExit();
216
217   /* clean up things from the storage manager's point of view.
218    * also outputs the stats (+RTS -s) info.
219    */
220   exitStorage();
221
222 #if defined(PROFILING) || defined(DEBUG)
223   endProfiling();
224 #endif
225
226 #if defined(PROFILING) 
227   report_ccs_profiling();
228 #endif
229
230 #if defined(TICKY_TICKY)
231   if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
232 #endif
233
234   rts_has_started_up=0;
235
236 #if defined(PAR)
237   shutdownParallelSystem(0);
238 #endif
239
240 }
241
242 /* 
243  * called from STG-land to exit the program
244  */
245
246 void  
247 stg_exit(I_ n)
248 {
249 #if 0 /* def PAR */
250   par_exit(n);
251 #else
252   exit(n);
253 #endif
254 }
255