remove empty dir
[ghc-hetmet.git] / rts / StgStartup.cmm
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 1998-2004
4  *
5  * Code for starting, stopping and restarting threads.
6  *
7  * This file is written in a subset of C--, extended with various
8  * features specific to GHC.  It is compiled by GHC directly.  For the
9  * syntax of .cmm files, see the parser in ghc/compiler/cmm/CmmParse.y.
10  *
11  * ---------------------------------------------------------------------------*/
12
13 #include "Cmm.h"
14
15 /*
16  * This module contains the two entry points and the final exit point
17  * to/from the Haskell world.  We can enter either by:
18  *
19  *   a) returning to the address on the top of the stack, or
20  *   b) entering the closure on the top of the stack
21  *
22  * the function stg_stop_thread_entry is the final exit for a
23  * thread: it is the last return address on the stack.  It returns
24  * to the scheduler marking the thread as finished.
25  */
26
27 #define CHECK_SENSIBLE_REGS() \
28     ASSERT(Hp != 0);                    \
29     ASSERT(Sp != 0);                    \
30     ASSERT(SpLim != 0);                 \
31     ASSERT(HpLim != 0);                 \
32     ASSERT(SpLim - WDS(RESERVED_STACK_WORDS) <= Sp); \
33     ASSERT(HpLim >= Hp);
34
35 /* -----------------------------------------------------------------------------
36    Returning from the STG world.
37
38    This is a polymorphic return address, meaning that any old constructor
39    can be returned, we don't care (actually, it's probably going to be
40    an IOok constructor, which will indirect through the vector table
41    slot 0).
42    -------------------------------------------------------------------------- */
43
44 #if defined(PROFILING)
45 #define STOP_THREAD_BITMAP 3
46 #define STOP_THREAD_WORDS  2
47 #else
48 #define STOP_THREAD_BITMAP 0
49 #define STOP_THREAD_WORDS  0
50 #endif
51
52 /* A polymorhpic return address, where all the vector slots point to the
53    direct entry point. */
54 INFO_TABLE_RET( stg_stop_thread, STOP_THREAD_WORDS, STOP_THREAD_BITMAP,
55                 STOP_FRAME, 
56                 RET_LBL(stg_stop_thread),
57                 RET_LBL(stg_stop_thread),
58                 RET_LBL(stg_stop_thread),
59                 RET_LBL(stg_stop_thread),
60                 RET_LBL(stg_stop_thread),
61                 RET_LBL(stg_stop_thread),
62                 RET_LBL(stg_stop_thread),
63                 RET_LBL(stg_stop_thread) )
64 {
65     /* 
66        The final exit.
67       
68        The top-top-level closures (e.g., "main") are of type "IO a".
69        When entered, they perform an IO action and return an 'a' in R1.
70       
71        We save R1 on top of the stack where the scheduler can find it,
72        tidy up the registers and return to the scheduler.
73       
74        We Leave the stack looking like this:
75       
76                 +----------------+
77                 |      -------------------> return value
78                 +----------------+
79                 | stg_enter_info |
80                 +----------------+
81       
82        The stg_enter_info is just a dummy info table so that the
83        garbage collector can understand the stack (there must always
84        be an info table on top of the stack).
85     */
86
87     Sp = Sp + SIZEOF_StgStopFrame - WDS(2);
88     Sp(1) = R1;
89     Sp(0) = stg_enter_info;
90
91     StgTSO_what_next(CurrentTSO) = ThreadComplete::I16;
92
93     SAVE_THREAD_STATE();
94
95     /* The return code goes in BaseReg->rRet, and BaseReg is returned in R1 */
96     StgRegTable_rRet(BaseReg) = ThreadFinished;
97     R1 = BaseReg;
98
99     jump StgReturn;
100 }
101
102 /* -----------------------------------------------------------------------------
103    Start a thread from the scheduler by returning to the address on
104    the top of the stack.  This is used for all entries to STG code
105    from C land.
106
107    On the way back, we (usually) pass through stg_returnToSched which saves
108    the thread's state away nicely.
109    -------------------------------------------------------------------------- */
110
111 stg_returnToStackTop
112 {
113   LOAD_THREAD_STATE();
114   CHECK_SENSIBLE_REGS();
115   jump %ENTRY_CODE(Sp(0));
116 }
117
118 stg_returnToSched
119 {
120   SAVE_THREAD_STATE();
121   foreign "C" threadPaused(MyCapability() "ptr", CurrentTSO);
122   jump StgReturn;
123 }
124
125 // A variant of stg_returntToSched that doesn't call threadPaused() on the
126 // current thread.  This is used for switching from compiled execution to the
127 // interpreter, where calling threadPaused() on every switch would be too
128 // expensive.
129 stg_returnToSchedNotPaused
130 {
131   SAVE_THREAD_STATE();
132   jump StgReturn;
133 }
134
135 // A variant of stg_returnToSched, but instead of returning directly to the
136 // scheduler, we jump to the code fragment pointed to by R2.  This lets us
137 // perform some final actions after making the thread safe, such as unlocking
138 // the MVar on which we are about to block in SMP mode.
139 stg_returnToSchedButFirst
140 {
141   SAVE_THREAD_STATE();
142   foreign "C" threadPaused(MyCapability() "ptr", CurrentTSO);
143   jump R2;
144 }
145
146 /* -----------------------------------------------------------------------------
147     Strict IO application - performing an IO action and entering its result.
148     
149     rts_evalIO() lets you perform Haskell IO actions from outside of
150     Haskell-land, returning back to you their result. Want this result
151     to be evaluated to WHNF by that time, so that we can easily get at
152     the int/char/whatever using the various get{Ty} functions provided
153     by the RTS API.
154
155     forceIO takes care of this, performing the IO action and entering the
156     results that comes back.
157     ------------------------------------------------------------------------- */
158
159 INFO_TABLE_RET( stg_forceIO, 0/*size*/, 0/*bitmap*/, RET_SMALL)
160
161 #ifdef REG_R1
162 {
163   Sp_adj(1);
164   ENTER();
165 }
166 #else
167 {
168   R1 = Sp(0);
169   Sp_adj(2);
170   ENTER();
171 }
172 #endif
173
174 /* -----------------------------------------------------------------------------
175     Non-strict IO application.
176
177     This stack frame works like stg_forceIO_info except that it
178     doesn't evaluate the return value.  We need the layer because the
179     return convention for an IO action differs depending on whether R1
180     is a register or not.
181     ------------------------------------------------------------------------- */
182
183 INFO_TABLE_RET( stg_noforceIO, 0/*size*/, 0/*bitmap*/, RET_SMALL )
184
185 #ifdef REG_R1
186 {
187   Sp_adj(1);
188   jump %ENTRY_CODE(Sp(0));
189 }
190 #else
191 {
192   R1 = Sp(0);
193   Sp_adj(2);
194   jump %ENTRY_CODE(Sp(0));
195 }
196 #endif
197
198 /* -----------------------------------------------------------------------------
199    Special STG entry points for module registration.
200    -------------------------------------------------------------------------- */
201
202 stg_init_finish
203 {
204   jump StgReturn;
205 }
206
207 /* On entry to stg_init:
208  *    init_stack[0] = &stg_init_ret;
209  *    init_stack[1] = __stginit_Something;
210  */
211 stg_init
212 {
213   W_ next;
214   Sp = W_[BaseReg + OFFSET_StgRegTable_rSp];
215   next = W_[Sp];
216   Sp_adj(1);
217   jump next;
218 }