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