fc31f165a3553f264987de47617e4474fdd78a98
[ghc-hetmet.git] / ghc / rts / RtsStartup.c
1 /* -----------------------------------------------------------------------------
2  * $Id: RtsStartup.c,v 1.8 1999/03/03 19:10:37 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 #ifndef aix_TARGET_OS /* AIX gives link errors with this as a const (RO assembler section) */
34 const 
35 #endif 
36   StgClosure *PrelBase_Bool_closure_tbl[] = {
37 #ifndef HAVE_WIN32_DLL_SUPPORT
38     &False_closure,
39     &True_closure
40 #else
41     &dummy_ret_closure,
42     &dummy_ret_closure
43 #endif
44 };
45
46 /*
47  * Flag Structure
48  */
49 struct RTS_FLAGS RtsFlags;
50
51 extern void startupHaskell(int argc, char *argv[])
52 {
53     static int rts_has_started_up = 0;
54     int i;
55
56     /* To avoid repeated initialisations of the RTS */
57    if (rts_has_started_up)
58      return;
59    else
60      rts_has_started_up=1;
61
62 #if defined(PAR)
63     int nPEs = 0;                   /* Number of PEs */
64 #endif
65
66     /* The very first thing we do is grab the start time...just in case we're
67      * collecting timing statistics.
68      */
69     start_time();
70
71 #ifdef PAR
72 /*
73  *The parallel system needs to be initialised and synchronised before
74  *the program is run.  
75  */
76     if (*argv[0] == '-') {     /* Look to see whether we're the Main Thread */
77         IAmMainThread = rtsTrue;
78         argv++; argc--;                 /* Strip off flag argument */
79 /*      fprintf(stderr, "I am Main Thread\n"); */
80     }
81     /* 
82      * Grab the number of PEs out of the argument vector, and
83      * eliminate it from further argument processing.
84      */
85     nPEs = atoi(argv[1]);
86     argv[1] = argv[0];
87     argv++; argc--;
88     initEachPEHook();                  /* HWL: hook to be execed on each PE */
89     SynchroniseSystem();
90 #endif
91
92     /* Set the RTS flags to default values. */
93     initRtsFlagsDefaults();
94
95     /* Call the user hook to reset defaults, if present */
96     defaultsHook();
97
98     /* Parse the flags, separating the RTS flags from the programs args */
99     setupRtsFlags(&argc, argv, &rts_argc, rts_argv);
100     prog_argc = argc;
101     prog_argv = argv;
102
103 #if defined(PAR)
104    /* Initialise the parallel system -- before initHeap! */
105     initParallelSystem();
106    /* And start GranSim profiling if required: omitted for now
107     *if (Rtsflags.ParFlags.granSimStats)
108     *init_gr_profiling(rts_argc, rts_argv, prog_argc, prog_argv);
109     */
110 #endif  /* PAR */
111
112     /* initialize the storage manager */
113     initStorage();
114
115     /* initialise the stable pointer table */
116     initStablePtrTable();
117
118 #if defined(PROFILING) || defined(DEBUG)
119     initProfiling();
120 #endif
121
122     /* Initialise the scheduler */
123     initScheduler();
124
125     /* Initialise the stats department */
126     initStats();
127
128 #if 0
129     initUserSignals();
130 #endif
131  
132     /* When the RTS and Prelude live in separate DLLs,
133        we need to patch up the char- and int-like tables
134        that the RTS keep after both DLLs have been loaded,
135        filling in the tables with references to where the
136        static info tables have been loaded inside the running
137        process.
138        
139        Ditto for Bool closure tbl.
140     */
141 #ifdef HAVE_WIN32_DLL_SUPPORT
142     for(i=0;i<=255;i++)
143        (CHARLIKE_closure[i]).header.info = (const StgInfoTable*)&Czh_static_info;
144
145     for(i=0;i<=32;i++)
146        (INTLIKE_closure[i]).header.info = (const StgInfoTable*)&Izh_static_info;
147        
148     PrelBase_Bool_closure_tbl[0] = (const StgClosure*)&False_closure;
149     PrelBase_Bool_closure_tbl[1] = (const StgClosure*)&True_closure;
150 #endif
151     /* Record initialization times */
152     end_init();
153 }
154
155 void
156 shutdownHaskell(void)
157 {
158   /* Finalize any remaining weak pointers */
159   finalizeWeakPointersNow();
160
161 #if defined(GRAN)
162   #error FixMe.
163   if (!RTSflags.GranFlags.granSimStats_suppressed)
164     end_gr_simulation();
165 #endif
166
167   /* clean up things from the storage manager's point of view */
168   exitStorage();
169
170 #if defined(PROFILING) || defined(DEBUG)
171   endProfiling();
172 #endif
173
174 #if defined(PROFILING) 
175   report_ccs_profiling( );
176 #endif
177
178 #if defined(TICKY_TICKY)
179   if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
180 #endif
181
182   /*
183     This fflush is important, because: if "main" just returns,
184     then we will end up in pre-supplied exit code that will close
185     streams and flush buffers.  In particular we have seen: it
186     will close fd 0 (stdin), then flush fd 1 (stdout), then <who
187     cares>...
188     
189     But if you're playing with sockets, that "close fd 0" might
190     suggest to the daemon that all is over, only to be presented
191     with more stuff on "fd 1" at the flush.
192     
193     The fflush avoids this sad possibility.
194    */
195   fflush(stdout);
196 }
197
198
199 /* 
200  * called from STG-land to exit the program cleanly 
201  */
202
203 void  
204 stg_exit(I_ n)
205 {
206 #ifdef PAR
207   par_exit(n);
208 #else
209   OnExitHook();
210   exit(n);
211 #endif
212 }