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