[project @ 1999-09-13 11:02:08 by sof]
[ghc-hetmet.git] / ghc / rts / RtsStartup.c
1 /* -----------------------------------------------------------------------------
2  * $Id: RtsStartup.c,v 1.19 1999/09/13 11:02:08 sof 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 #if !defined(mingw32_TARGET_OS) && !defined(PAR)
127     initUserSignals();
128 #endif
129  
130     /* When the RTS and Prelude live in separate DLLs,
131        we need to patch up the char- and int-like tables
132        that the RTS keep after both DLLs have been loaded,
133        filling in the tables with references to where the
134        static info tables have been loaded inside the running
135        process.
136     */
137 #ifdef ENABLE_WIN32_DLL_SUPPORT
138     for(i=0;i<=255;i++)
139        (CHARLIKE_closure[i]).header.info = (const StgInfoTable*)&Czh_static_info;
140
141     for(i=0;i<=32;i++)
142        (INTLIKE_closure[i]).header.info = (const StgInfoTable*)&Izh_static_info;
143        
144 #endif
145     /* Record initialization times */
146     end_init();
147 }
148
149 /*
150  * Shutting down the RTS - two ways of doing this, one which
151  * calls exit(), one that doesn't.
152  *
153  * (shutdownHaskellAndExit() is called by System.exitWith).
154  */
155 void
156 shutdownHaskellAndExit(int n)
157 {
158   OnExitHook();
159   shutdownHaskell();
160   stg_exit(n);
161 }
162
163 void
164 shutdownHaskell(void)
165 {
166   if (!rts_has_started_up)
167      return;
168
169   /* Finalize any remaining weak pointers */
170   finalizeWeakPointersNow();
171
172 #if defined(GRAN)
173   #error FixMe.
174   if (!RTSflags.GranFlags.granSimStats_suppressed)
175     end_gr_simulation();
176 #endif
177
178   /* clean up things from the storage manager's point of view */
179   exitStorage();
180
181   /* stop the ticker */
182   initialize_virtual_timer(0);
183
184 #if defined(PROFILING) || defined(DEBUG)
185   endProfiling();
186 #endif
187
188 #if defined(PROFILING) 
189   report_ccs_profiling( );
190 #endif
191
192 #if defined(TICKY_TICKY)
193   if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
194 #endif
195
196   rts_has_started_up=0;
197 }
198
199
200 /* 
201  * called from STG-land to exit the program
202  */
203
204 void  
205 stg_exit(I_ n)
206 {
207 #ifdef PAR
208   par_exit(n);
209 #else
210   exit(n);
211 #endif
212 }
213