RtsStartup.c 5.9 KB
Newer Older
1
/* -----------------------------------------------------------------------------
2
 * $Id: RtsStartup.c,v 1.29 2000/02/17 17:19:42 simonmar Exp $
3
4
 *
 * (c) The GHC Team, 1998-1999
5
6
7
8
9
10
11
12
13
14
 *
 * Main function for a standalone Haskell program.
 *
 * ---------------------------------------------------------------------------*/

#include "Rts.h"
#include "RtsAPI.h"
#include "RtsUtils.h"
#include "RtsFlags.h"  
#include "Storage.h"    /* initStorage, exitStorage */
15
#include "StablePriv.h" /* initStablePtrTable */
16
17
#include "Schedule.h"   /* initScheduler */
#include "Stats.h"      /* initStats */
18
19
#include "Signals.h"
#include "Itimer.h"
20
#include "Weak.h"
21
#include "Ticky.h"
22

23
#if defined(PROFILING) || defined(DEBUG)
24
# include "ProfRts.h"
25
# include "ProfHeap.h"
26
27
#endif

28
29
30
31
32
33
#if defined(GRAN)
#include "GranSimRts.h"
#include "ParallelRts.h"
#endif

#if defined(PAR)
34
35
36
37
38
39
40
41
42
43
#include "ParInit.h"
#include "Parallel.h"
#include "LLC.h"
#endif

/*
 * Flag Structure
 */
struct RTS_FLAGS RtsFlags;

sof's avatar
sof committed
44
static int rts_has_started_up = 0;
45
46
47
#if defined(PAR)
static ullong startTime = 0;
#endif
sof's avatar
sof committed
48

sof's avatar
sof committed
49
50
void
startupHaskell(int argc, char *argv[])
51
{
52
#ifdef ENABLE_WIN32_DLL_SUPPORT
sof's avatar
sof committed
53
    int i;
54
#endif
sof's avatar
sof committed
55
56
57
58
59
60
61

    /* To avoid repeated initialisations of the RTS */
   if (rts_has_started_up)
     return;
   else
     rts_has_started_up=1;

62
63
64
65
66
67
68
    /* The very first thing we do is grab the start time...just in case we're
     * collecting timing statistics.
     */
    start_time();

#ifdef PAR
/*
69
70
 * The parallel system needs to be initialised and synchronised before
 * the program is run.  
71
 */
72
    fprintf(stderr, "startupHaskell: argv[0]=%s\n", argv[0]);
73
74
75
    if (*argv[0] == '-') {     /* Look to see whether we're the Main Thread */
	IAmMainThread = rtsTrue;
        argv++; argc--;			/* Strip off flag argument */
76
77
	// IF_PAR_DEBUG(verbose,
		     fprintf(stderr, "[%x] I am Main Thread\n", mytid);
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
    }
    /* 
     * Grab the number of PEs out of the argument vector, and
     * eliminate it from further argument processing.
     */
    nPEs = atoi(argv[1]);
    argv[1] = argv[0];
    argv++; argc--;
    initEachPEHook();                  /* HWL: hook to be execed on each PE */
#endif

    /* Set the RTS flags to default values. */
    initRtsFlagsDefaults();

    /* Call the user hook to reset defaults, if present */
    defaultsHook();

    /* Parse the flags, separating the RTS flags from the programs args */
    setupRtsFlags(&argc, argv, &rts_argc, rts_argv);
    prog_argc = argc;
    prog_argv = argv;

100
101
102
103
#if defined(PAR)
    /* NB: this really must be done after processing the RTS flags */
    fprintf(stderr, "Synchronising system (%d PEs)\n", nPEs);
    SynchroniseSystem();             // calls initParallelSystem etc
104
105
#endif	/* PAR */

106
107
108
109
110
    /* initialise scheduler data structures (needs to be done before
     * initStorage()).
     */
    initScheduler();

111
112
113
114
115
116
117
118
119
120
#if defined(GRAN)
    /* And start GranSim profiling if required: */
    if (RtsFlags.GranFlags.GranSimStats.Full)
      init_gr_simulation(rts_argc, rts_argv, prog_argc, prog_argv);
#elif defined(PAR)
    /* And start GUM profiling if required: */
    if (RtsFlags.ParFlags.ParStats.Full)
      init_gr_simulation(rts_argc, rts_argv, prog_argc, prog_argv);
#endif	/* PAR || GRAN */

121
122
123
124
125
126
127
128
129
130
    /* initialize the storage manager */
    initStorage();

    /* initialise the stable pointer table */
    initStablePtrTable();

#if defined(PROFILING) || defined(DEBUG)
    initProfiling();
#endif

131
132
133
134
    /* start the ticker */
    install_vtalrm_handler();
    initialize_virtual_timer(TICK_MILLISECS);

135
136
137
138
    /* start our haskell execution tasks */
#ifdef SMP
    startTasks();
#endif
139
140
141
142

    /* Initialise the stats department */
    initStats();

sof's avatar
sof committed
143
#if !defined(mingw32_TARGET_OS) && !defined(PAR)
sof's avatar
sof committed
144
    /* Initialise the user signal handler set */
145
    initUserSignals();
sof's avatar
sof committed
146
147
    /* Set up handler to run on SIGINT */
    init_shutdown_handler();
sof's avatar
sof committed
148
#endif
sof's avatar
sof committed
149
150
151
152
153
154
155
156
 
    /* When the RTS and Prelude live in separate DLLs,
       we need to patch up the char- and int-like tables
       that the RTS keep after both DLLs have been loaded,
       filling in the tables with references to where the
       static info tables have been loaded inside the running
       process.
    */
sof's avatar
sof committed
157
#ifdef ENABLE_WIN32_DLL_SUPPORT
sof's avatar
sof committed
158
159
160
161
162
163
164
    for(i=0;i<=255;i++)
       (CHARLIKE_closure[i]).header.info = (const StgInfoTable*)&Czh_static_info;

    for(i=0;i<=32;i++)
       (INTLIKE_closure[i]).header.info = (const StgInfoTable*)&Izh_static_info;
       
#endif
165
166
167
168
    /* Record initialization times */
    end_init();
}

sof's avatar
sof committed
169
170
171
172
173
174
175
176
177
/*
 * Shutting down the RTS - two ways of doing this, one which
 * calls exit(), one that doesn't.
 *
 * (shutdownHaskellAndExit() is called by System.exitWith).
 */
void
shutdownHaskellAndExit(int n)
{
178
  OnExitHook();
sof's avatar
sof committed
179
180
181
182
  shutdownHaskell();
  stg_exit(n);
}

183
184
185
void
shutdownHaskell(void)
{
sof's avatar
sof committed
186
187
188
  if (!rts_has_started_up)
     return;

189
190
191
  /* start timing the shutdown */
  stat_startExit();

192
#if !defined(GRAN)
193
194
  /* Finalize any remaining weak pointers */
  finalizeWeakPointersNow();
195
#endif
196
197

#if defined(GRAN)
198
199
  /* end_gr_simulation prints global stats if requested -- HWL */
  if (!RtsFlags.GranFlags.GranSimStats.Suppressed)
200
201
202
    end_gr_simulation();
#endif

203
204
205
  /* stop all running tasks */
  exitScheduler();

206
207
  /* stop the ticker */
  initialize_virtual_timer(0);
sof's avatar
sof committed
208
  
209
210
211
212
213
  /* reset the standard file descriptors to blocking mode */
  resetNonBlockingFd(0);
  resetNonBlockingFd(1);
  resetNonBlockingFd(2);

214
215
216
217
218
219
220
221
  /* stop timing the shutdown, we're about to print stats */
  stat_endExit();

  /* clean up things from the storage manager's point of view.
   * also outputs the stats (+RTS -s) info.
   */
  exitStorage();

222
223
224
225
226
#if defined(PROFILING) || defined(DEBUG)
  endProfiling();
#endif

#if defined(PROFILING) 
227
  report_ccs_profiling();
228
229
230
#endif

#if defined(TICKY_TICKY)
231
  if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
232
233
#endif

sof's avatar
sof committed
234
  rts_has_started_up=0;
235

236
237
238
239
240
#if defined(PAR)
  shutdownParallelSystem(0);
#endif

}
241
242

/* 
243
 * called from STG-land to exit the program
244
245
246
247
248
 */

void  
stg_exit(I_ n)
{
249
#if 0 /* def PAR */
250
251
252
253
254
  par_exit(n);
#else
  exit(n);
#endif
}
255