blob: df637169f8eb98e0027751b8e9621f6c8e6be2aa (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
/* -----------------------------------------------------------------------------
*
* (c) The GHC Team 1998-2000
*
* Main function for a standalone Haskell program.
*
* ---------------------------------------------------------------------------*/
#define COMPILING_RTS_MAIN
#include "PosixSource.h"
#include "Rts.h"
#include "RtsAPI.h"
#include "RtsUtils.h"
#include "Prelude.h"
#include "Task.h"
#if defined(mingw32_HOST_OS)
#include "win32/seh_excn.h"
#endif
#ifdef DEBUG
# include "Printer.h" /* for printing */
#endif
#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif
/* Annoying global vars for passing parameters to real_main() below
* This is to get around problem with Windows SEH, see hs_main(). */
static int progargc;
static char **progargv;
static StgClosure *progmain_closure; /* This will be ZCMain_main_closure */
static RtsConfig rtsconfig;
/* Hack: we assume that we're building a batch-mode system unless
* INTERPRETER is set
*/
#ifndef INTERPRETER /* Hack */
static void real_main(void) GNUC3_ATTRIBUTE(__noreturn__);
static void real_main(void)
{
int exit_status;
SchedulerStatus status;
hs_init_ghc(&progargc, &progargv, rtsconfig);
/* kick off the computation by creating the main thread with a pointer
to mainIO_closure representing the computation of the overall program;
then enter the scheduler with this thread and off we go;
the same for GranSim (we have only one instance of this code)
in a parallel setup, where we have many instances of this code
running on different PEs, we should do this only for the main PE
(IAmMainThread is set in startupHaskell)
*/
/* ToDo: want to start with a larger stack size */
{
Capability *cap = rts_lock();
rts_evalLazyIO(&cap,progmain_closure, NULL);
status = rts_getSchedStatus(cap);
rts_unlock(cap);
}
/* check the status of the entire Haskell computation */
switch (status) {
case Killed:
errorBelch("main thread exited (uncaught exception)");
exit_status = EXIT_KILLED;
break;
case Interrupted:
errorBelch("interrupted");
exit_status = EXIT_INTERRUPTED;
break;
case HeapExhausted:
exit_status = EXIT_HEAPOVERFLOW;
break;
case Success:
exit_status = EXIT_SUCCESS;
break;
default:
barf("main thread completed with invalid status");
}
shutdownHaskellAndExit(exit_status, 0 /* !fastExit */);
}
/* The rts entry point from a compiled program using a Haskell main
* function. This gets called from a tiny main function generated by
* GHC and linked into each compiled Haskell program that uses a
* Haskell main function.
*
* We expect the caller to pass ZCMain_main_closure for
* main_closure. The reason we cannot refer to this symbol directly
* is because we're inside the rts and we do not know for sure that
* we'll be using a Haskell main function.
*/
int hs_main (int argc, char *argv[], // program args
StgClosure *main_closure, // closure for Main.main
RtsConfig rts_config) // RTS configuration
{
/* We do this dance with argc and argv as otherwise the SEH exception
stuff (the BEGIN/END CATCH below) on Windows gets confused */
progargc = argc;
progargv = argv;
progmain_closure = main_closure;
rtsconfig = rts_config;
#if defined(mingw32_HOST_OS) && defined(i386_HOST_ARCH)
BEGIN_CATCH
#endif
real_main();
#if defined(mingw32_HOST_OS) && defined(i386_HOST_ARCH)
END_CATCH
#endif
}
# endif /* BATCH_MODE */
|