summaryrefslogtreecommitdiff
path: root/rts/RtsMain.c
blob: 48df8e9db7843e9a89256ae4e746747bba058ed3 (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
/* -----------------------------------------------------------------------------
 *
 * (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"
#include "Excn.h"

#ifdef DEBUG
# include "Printer.h"   /* for printing        */
#endif

// Hack: we assume that we're building a batch-mode system unless
// INTERPRETER is set
 
#ifndef INTERPRETER /* Hack */

// 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.
// 
// NOTE: This function is marked as _noreturn_ in Main.h

int hs_main ( int argc, char *argv[],       // program args
              StgClosure *main_closure,     // closure for Main.main
              RtsConfig rts_config)         // RTS configuration
              
{
    BEGIN_WINDOWS_VEH_HANDLER

    int exit_status;
    SchedulerStatus status;

    hs_init_ghc(&argc, &argv, rts_config);

    // 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;
    // 
    // 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, main_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");
    }

    END_WINDOWS_VEH_HANDLER

    shutdownHaskellAndExit(exit_status, 0 /* !fastExit */);
    // No code beyond this point. Dead code elimination will remove it 
}
# endif /* BATCH_MODE */