[project @ 2000-01-14 13:17:15 by hwloidl]
[ghc-hetmet.git] / ghc / rts / RtsStartup.c
1 /* -----------------------------------------------------------------------------
2  * $Id: RtsStartup.c,v 1.27 2000/01/14 13:17:15 hwloidl 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 #if 0 /* tmp--SDM */
134     initialize_virtual_timer(TICK_MILLISECS);
135 #endif
136
137     /* start our haskell execution tasks */
138 #ifdef SMP
139     startTasks();
140 #endif
141
142     /* Initialise the stats department */
143     initStats();
144
145 #if !defined(mingw32_TARGET_OS) && !defined(PAR)
146     /* Initialise the user signal handler set */
147     initUserSignals();
148     /* Set up handler to run on SIGINT */
149     init_shutdown_handler();
150 #endif
151  
152     /* When the RTS and Prelude live in separate DLLs,
153        we need to patch up the char- and int-like tables
154        that the RTS keep after both DLLs have been loaded,
155        filling in the tables with references to where the
156        static info tables have been loaded inside the running
157        process.
158     */
159 #ifdef ENABLE_WIN32_DLL_SUPPORT
160     for(i=0;i<=255;i++)
161        (CHARLIKE_closure[i]).header.info = (const StgInfoTable*)&Czh_static_info;
162
163     for(i=0;i<=32;i++)
164        (INTLIKE_closure[i]).header.info = (const StgInfoTable*)&Izh_static_info;
165        
166 #endif
167     /* Record initialization times */
168     end_init();
169 }
170
171 /*
172  * Shutting down the RTS - two ways of doing this, one which
173  * calls exit(), one that doesn't.
174  *
175  * (shutdownHaskellAndExit() is called by System.exitWith).
176  */
177 void
178 shutdownHaskellAndExit(int n)
179 {
180   OnExitHook();
181   shutdownHaskell();
182   stg_exit(n);
183 }
184
185 void
186 shutdownHaskell(void)
187 {
188   if (!rts_has_started_up)
189      return;
190
191   /* start timing the shutdown */
192   stat_startExit();
193
194 #if !defined(GRAN)
195   /* Finalize any remaining weak pointers */
196   finalizeWeakPointersNow();
197 #endif
198
199 #if defined(GRAN)
200   /* end_gr_simulation prints global stats if requested -- HWL */
201   if (!RtsFlags.GranFlags.GranSimStats.Suppressed)
202     end_gr_simulation();
203 #endif
204
205   /* stop all running tasks */
206   exitScheduler();
207
208   /* stop the ticker */
209   initialize_virtual_timer(0);
210   
211   /* reset the standard file descriptors to blocking mode */
212   resetNonBlockingFd(0);
213   resetNonBlockingFd(1);
214   resetNonBlockingFd(2);
215
216   /* stop timing the shutdown, we're about to print stats */
217   stat_endExit();
218
219   /* clean up things from the storage manager's point of view.
220    * also outputs the stats (+RTS -s) info.
221    */
222   exitStorage();
223
224 #if defined(PROFILING) || defined(DEBUG)
225   endProfiling();
226 #endif
227
228 #if defined(PROFILING) 
229   report_ccs_profiling( );
230 #endif
231
232 #if defined(TICKY_TICKY)
233   if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
234 #endif
235
236   rts_has_started_up=0;
237
238 #if defined(PAR)
239   shutdownParallelSystem(0);
240 #endif
241
242 }
243
244 /* 
245  * called from STG-land to exit the program
246  */
247
248 void  
249 stg_exit(I_ n)
250 {
251 #if 0 /* def PAR */
252   par_exit(n);
253 #else
254   exit(n);
255 #endif
256 }
257