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