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