StgStartup.cmm 5.62 KB
Newer Older
1
/* -----------------------------------------------------------------------------
2
 *
Gabor Greif's avatar
Gabor Greif committed
3
 * (c) The GHC Team, 1998-2012
4 5 6
 *
 * Code for starting, stopping and restarting threads.
 *
7 8 9 10
 * This file is written in a subset of C--, extended with various
 * features specific to GHC.  It is compiled by GHC directly.  For the
 * syntax of .cmm files, see the parser in ghc/compiler/cmm/CmmParse.y.
 *
11 12
 * ---------------------------------------------------------------------------*/

13
#include "Cmm.h"
14 15 16 17 18 19 20 21 22 23 24 25 26

/*
 * This module contains the two entry points and the final exit point
 * to/from the Haskell world.  We can enter either by:
 *
 *   a) returning to the address on the top of the stack, or
 *   b) entering the closure on the top of the stack
 *
 * the function stg_stop_thread_entry is the final exit for a
 * thread: it is the last return address on the stack.  It returns
 * to the scheduler marking the thread as finished.
 */

Simon Marlow's avatar
Simon Marlow committed
27 28 29 30 31
#define CHECK_SENSIBLE_REGS()                           \
    ASSERT(Hp != 0);                                    \
    ASSERT(HpAlloc == 0);                               \
    ASSERT(Sp != 0);                                    \
    ASSERT(SpLim != 0);                                 \
32
    ASSERT(SpLim - WDS(RESERVED_STACK_WORDS) <= Sp);
33 34 35 36 37

/* -----------------------------------------------------------------------------
   Returning from the STG world.
   -------------------------------------------------------------------------- */

Gabor Greif's avatar
Gabor Greif committed
38
INFO_TABLE_RET(stg_stop_thread, STOP_FRAME,
39
               W_ info_ptr,
Simon Marlow's avatar
Simon Marlow committed
40
               PROF_HDR_FIELDS(W_,p1,p2))
41
/* no return list: explicit stack layout */
42
{
43
    /*
44
       The final exit.
45

46 47
       The top-top-level closures (e.g., "main") are of type "IO a".
       When entered, they perform an IO action and return an 'a' in R1.
48

49 50
       We save R1 on top of the stack where the scheduler can find it,
       tidy up the registers and return to the scheduler.
51

52
       We Leave the stack looking like this:
53 54

                +----------------+
55
                |      -------------------> return value
56 57 58 59
                +----------------+
                | stg_enter_info |
                +----------------+

60 61 62 63 64
       The stg_enter_info is just a dummy info table so that the
       garbage collector can understand the stack (there must always
       be an info table on top of the stack).
    */

65
    // See Note [Unwinding foreign exports on x86-64].
Ben Gamari's avatar
Ben Gamari committed
66
#if defined(x86_64_HOST_ARCH)
67
    unwind UnwindReturnReg = STG_RUN_JMP;
68 69
#else
    // FIXME: Fill in for other platforms
70
    unwind UnwindReturnReg = return;
71 72
#endif

73 74 75 76 77 78 79 80
    Sp = Sp + SIZEOF_StgStopFrame - WDS(2);
    Sp(1) = R1;
    Sp(0) = stg_enter_info;

    StgTSO_what_next(CurrentTSO) = ThreadComplete::I16;

    SAVE_THREAD_STATE();

81 82 83
    /* The return code goes in BaseReg->rRet, and BaseReg is returned in R1 */
    StgRegTable_rRet(BaseReg) = ThreadFinished;
    R1 = BaseReg;
84

85
    jump StgReturn [R1];
86 87 88 89
}

/* -----------------------------------------------------------------------------
   Start a thread from the scheduler by returning to the address on
90 91
   the top of the stack.  This is used for all entries to STG code
   from C land.
92 93 94

   On the way back, we (usually) pass through stg_returnToSched which saves
   the thread's state away nicely.
95 96
   -------------------------------------------------------------------------- */

97
stg_returnToStackTop /* no args: explicit stack layout */
98
{
99
  LOAD_THREAD_STATE();
100
  CHECK_SENSIBLE_REGS();
101
  jump %ENTRY_CODE(Sp(0)) [];
102 103
}

104
stg_returnToSched /* no args: explicit stack layout */
105
{
106 107
  W_ r1;
  r1 = R1; // foreign calls may clobber R1
108
  SAVE_THREAD_STATE();
109
  foreign "C" threadPaused(MyCapability() "ptr", CurrentTSO);
110 111
  R1 = r1;
  jump StgReturn [R1];
112 113
}

Gabor Greif's avatar
Gabor Greif committed
114
// A variant of stg_returnToSched that doesn't call threadPaused() on the
115 116 117
// current thread.  This is used for switching from compiled execution to the
// interpreter, where calling threadPaused() on every switch would be too
// expensive.
118 119 120
//
// See Note [avoiding threadPaused] in Interpreter.c
//
121
stg_returnToSchedNotPaused /* no args: explicit stack layout */
122 123
{
  SAVE_THREAD_STATE();
124
  jump StgReturn [R1];
125 126
}

127 128 129 130
// A variant of stg_returnToSched, but instead of returning directly to the
// scheduler, we jump to the code fragment pointed to by R2.  This lets us
// perform some final actions after making the thread safe, such as unlocking
// the MVar on which we are about to block in SMP mode.
131
stg_returnToSchedButFirst /* no args: explicit stack layout */
132
{
133 134 135 136
  W_ r1, r2, r3;
  r1 = R1;
  r2 = R2;
  r3 = R3;
137
  SAVE_THREAD_STATE();
138
  // foreign calls may clobber R1/R2/.., so we save them above
139
  foreign "C" threadPaused(MyCapability() "ptr", CurrentTSO);
140 141 142 143
  R1 = r1;
  R2 = r2;
  R3 = r3;
  jump R2 [R1,R3];
144 145
}

146
stg_threadFinished /* no args: explicit stack layout */
147 148 149
{
  StgRegTable_rRet(BaseReg) = ThreadFinished;
  R1 = BaseReg;
150
  jump StgReturn [R1];
151
}
152

153 154
/* -----------------------------------------------------------------------------
    Strict IO application - performing an IO action and entering its result.
155

156 157 158 159 160 161
    rts_evalIO() lets you perform Haskell IO actions from outside of
    Haskell-land, returning back to you their result. Want this result
    to be evaluated to WHNF by that time, so that we can easily get at
    the int/char/whatever using the various get{Ty} functions provided
    by the RTS API.

Gabor Greif's avatar
Gabor Greif committed
162 163
    stg_forceIO takes care of this, performing the IO action and entering
    the results that comes back.
Simon Marlow's avatar
Simon Marlow committed
164

165 166
    ------------------------------------------------------------------------- */

167 168
INFO_TABLE_RET(stg_forceIO, RET_SMALL, P_ info_ptr)
    return (P_ ret)
169
{
170
    ENTER(ret);
171
}
Ben Gamari's avatar
Ben Gamari committed
172 173 174 175 176 177

/* Called when compiled with -falignment-sanitisation on alignment failure */
stg_badAlignment_entry
{
  foreign "C" barf();
}