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