/* -----------------------------------------------------------------------------
- * $Id: RtsStartup.c,v 1.70 2003/01/30 10:19:07 simonmar Exp $
*
* (c) The GHC Team, 1998-2002
*
#include "RtsAPI.h"
#include "RtsUtils.h"
#include "RtsFlags.h"
+#include "OSThreads.h"
#include "Storage.h" /* initStorage, exitStorage */
-#include "StablePriv.h" /* initStablePtrTable */
#include "Schedule.h" /* initScheduler */
#include "Stats.h" /* initStats */
+#include "STM.h" /* initSTM */
#include "Signals.h"
-#include "Itimer.h"
+#include "RtsSignals.h"
+#include "Timer.h" /* startTimer, stopTimer */
#include "Weak.h"
#include "Ticky.h"
#include "StgRun.h"
-#include "StgStartup.h"
#include "Prelude.h" /* fixupRTStoPreludeRefs */
#include "HsFFI.h"
#include "Linker.h"
#include "ThreadLabels.h"
+#include "BlockAlloc.h"
#if defined(RTS_GTK_FRONTPANEL)
#include "FrontPanel.h"
# include "LLC.h"
#endif
+#if defined(mingw32_HOST_OS)
+#include "win32/AsyncIO.h"
+#endif
+
#include <stdlib.h>
-// Flag Structure
-struct RTS_FLAGS RtsFlags;
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
// Count of how many outstanding hs_init()s there have been.
static int hs_init_count = 0;
+// Here we save the terminal settings on the standard file
+// descriptors, if we need to change them (eg. to support NoBuffering
+// input).
+static void *saved_termios[3] = {NULL,NULL,NULL};
+
+void*
+__hscore_get_saved_termios(int fd)
+{
+ return (0 <= fd && fd < (int)(sizeof(saved_termios) / sizeof(*saved_termios))) ?
+ saved_termios[fd] : NULL;
+}
+
+void
+__hscore_set_saved_termios(int fd, void* ts)
+{
+ if (0 <= fd && fd < (int)(sizeof(saved_termios) / sizeof(*saved_termios))) {
+ saved_termios[fd] = ts;
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ Initialise floating point unit on x86 (currently disabled. why?)
+ (see comment in ghc/compiler/nativeGen/MachInstrs.lhs).
+ -------------------------------------------------------------------------- */
+
+#define X86_INIT_FPU 0
+
+#if X86_INIT_FPU
+static void
+x86_init_fpu ( void )
+{
+ __volatile unsigned short int fpu_cw;
+
+ // Grab the control word
+ __asm __volatile ("fnstcw %0" : "=m" (fpu_cw));
+
+#if 0
+ printf("fpu_cw: %x\n", fpu_cw);
+#endif
+
+ // Set bits 8-9 to 10 (64-bit precision).
+ fpu_cw = (fpu_cw & 0xfcff) | 0x0200;
+
+ // Store the new control word back
+ __asm __volatile ("fldcw %0" : : "m" (fpu_cw));
+}
+#endif
+
/* -----------------------------------------------------------------------------
Starting up the RTS
-------------------------------------------------------------------------- */
/* Parse the flags, separating the RTS flags from the programs args */
if (argc != NULL && argv != NULL) {
setupRtsFlags(argc, *argv, &rts_argc, rts_argv);
- prog_argc = *argc;
- prog_argv = *argv;
+ setProgArgv(*argc,*argv);
}
#if defined(PAR)
/* NB: this really must be done after processing the RTS flags */
IF_PAR_DEBUG(verbose,
- fprintf(stderr, "==== Synchronising system (%d PEs)\n", nPEs));
+ debugBelch("==== Synchronising system (%d PEs)\n", nPEs));
synchroniseSystem(); // calls initParallelSystem etc
#endif /* PAR */
+ /* Perform initialisation of adjustor thunk layer. */
+ initAdjustor();
+
/* initialise scheduler data structures (needs to be done before
* initStorage()).
*/
/* initialise the stable pointer table */
initStablePtrTable();
+#if defined(DEBUG)
/* initialise thread label table (tso->char*) */
initThreadLabelTable();
+#endif
#if defined(PROFILING) || defined(DEBUG)
initProfiling1();
#endif
/* start the virtual timer 'subsystem'. */
- startVirtTimer(TICK_MILLISECS);
+ startTimer(TICK_MILLISECS);
/* Initialise the stats department */
initStats();
-#if !defined(mingw32_TARGET_OS) && !defined(PAR)
+#if defined(RTS_USER_SIGNALS)
/* Initialise the user signal handler set */
initUserSignals();
/* Set up handler to run on SIGINT, etc. */
initDefaultHandlers();
#endif
+#if defined(mingw32_HOST_OS)
+ startupAsyncIO();
+#endif
+
#ifdef RTS_GTK_FRONTPANEL
if (RtsFlags.GcFlags.frontpanel) {
initFrontPanel();
}
#endif
+#if X86_INIT_FPU
+ x86_init_fpu();
+#endif
+
/* Record initialization times */
stat_endInit();
}
startupHaskell(int argc, char *argv[], void (*init_root)(void))
{
hs_init(&argc, &argv);
- hs_add_root(init_root);
-}
-
-
-/* -----------------------------------------------------------------------------
- Getting/Setting the program's arguments.
-
- These are used by System.Environment.
- -------------------------------------------------------------------------- */
-
-void
-getProgArgv(int *argc, char **argv[])
-{
- *argc = prog_argc;
- *argv = prog_argv;
+ if(init_root)
+ hs_add_root(init_root);
}
-void
-setProgArgv(int argc, char *argv[])
-{
- /* Usually this is done by startupHaskell, so we don't need to call this.
- However, sometimes Hugs wants to change the arguments which Haskell
- getArgs >>= ... will be fed. So you can do that by calling here
- _after_ calling startupHaskell.
- */
- prog_argc = argc;
- prog_argv = argv;
-}
/* -----------------------------------------------------------------------------
Per-module initialisation
hs_add_root(void (*init_root)(void))
{
bdescr *bd;
-#ifdef SMP
- Capability cap;
-#else
-#define cap MainCapability
-#endif
nat init_sp;
+ Capability *cap = &MainCapability;
if (hs_init_count <= 0) {
barf("hs_add_root() must be called after hs_init()");
}
- init_sp = 0;
- bd = allocGroup(INIT_STACK_BLOCKS);
+ /* The initialisation stack grows downward, with sp pointing
+ to the last occupied word */
+ init_sp = INIT_STACK_BLOCKS*BLOCK_SIZE_W;
+ bd = allocGroup_lock(INIT_STACK_BLOCKS);
init_stack = (F_ *)bd->start;
- init_stack[init_sp++] = (F_)stg_init_ret;
+ init_stack[--init_sp] = (F_)stg_init_finish;
if (init_root != NULL) {
- init_stack[init_sp++] = (F_)init_root;
+ init_stack[--init_sp] = (F_)init_root;
}
- cap.r.rSp = (P_)(init_stack + init_sp);
- StgRun((StgFunPtr)stg_init, &cap.r);
+ cap->r.rSp = (P_)(init_stack + init_sp);
+ StgRun((StgFunPtr)stg_init, &cap->r);
- freeGroup(bd);
+ freeGroup_lock(bd);
#if defined(PROFILING) || defined(DEBUG)
// This must be done after module initialisation.
/* stop all running tasks */
exitScheduler();
-#if !defined(GRAN)
- /* Finalize any remaining weak pointers */
- finalizeWeakPointersNow();
-#endif
-
#if defined(GRAN)
/* end_gr_simulation prints global stats if requested -- HWL */
if (!RtsFlags.GranFlags.GranSimStats.Suppressed)
#endif
/* stop the ticker */
- stopVirtTimer();
+ stopTimer();
/* reset the standard file descriptors to blocking mode */
resetNonBlockingFd(0);
resetNonBlockingFd(1);
resetNonBlockingFd(2);
+#if HAVE_TERMIOS_H
+ // Reset the terminal settings on the standard file descriptors,
+ // if we changed them. See System.Posix.Internals.tcSetAttr for
+ // more details, including the reason we termporarily disable
+ // SIGTTOU here.
+ {
+ int fd;
+ sigset_t sigset, old_sigset;
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGTTOU);
+ sigprocmask(SIG_BLOCK, &sigset, &old_sigset);
+ for (fd = 0; fd <= 2; fd++) {
+ struct termios* ts = (struct termios*)__hscore_get_saved_termios(fd);
+ if (ts != NULL) {
+ tcsetattr(fd,TCSANOW,ts);
+ }
+ }
+ sigprocmask(SIG_SETMASK, &old_sigset, NULL);
+ }
+#endif
+
#if defined(PAR)
/* controlled exit; good thread! */
shutdownParallelSystem(0);
#if defined(TICKY_TICKY)
if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
#endif
+
+#if defined(mingw32_HOST_OS)
+ shutdownAsyncIO();
+#endif
}
// Compatibility interfaces
return;
exit_started=rtsTrue;
- IF_PAR_DEBUG(verbose, fprintf(stderr,"==-- stg_exit %d on [%x]...", n, mytid));
+ IF_PAR_DEBUG(verbose, debugBelch("==-- stg_exit %d on [%x]...", n, mytid));
shutdownParallelSystem(n);
#endif
exit(n);
}
-