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