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