[project @ 1999-11-02 15:05:38 by simonmar]
[ghc-hetmet.git] / ghc / rts / RtsStartup.c
1 /* -----------------------------------------------------------------------------
2  * $Id: RtsStartup.c,v 1.22 1999/11/02 15:06:01 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   /* Finalize any remaining weak pointers */
178   finalizeWeakPointersNow();
179
180 #if defined(GRAN)
181   #error FixMe.
182   if (!RTSflags.GranFlags.granSimStats_suppressed)
183     end_gr_simulation();
184 #endif
185
186   /* stop all running tasks */
187   exitScheduler();
188
189   /* clean up things from the storage manager's point of view */
190   exitStorage();
191
192   /* stop the ticker */
193   initialize_virtual_timer(0);
194   
195 #if defined(PROFILING) || defined(DEBUG)
196   endProfiling();
197 #endif
198
199 #if defined(PROFILING) 
200   report_ccs_profiling( );
201 #endif
202
203 #if defined(TICKY_TICKY)
204   if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
205 #endif
206
207   rts_has_started_up=0;
208 }
209
210
211 /* 
212  * called from STG-land to exit the program
213  */
214
215 void  
216 stg_exit(I_ n)
217 {
218 #ifdef PAR
219   par_exit(n);
220 #else
221   exit(n);
222 #endif
223 }
224