1 /* -----------------------------------------------------------------------------
2 * $Id: StgStartup.hc,v 1.2 1998/12/02 13:28:55 simonm Exp $
4 * Code for starting, stopping and restarting threads.
6 * ---------------------------------------------------------------------------*/
9 #include "StgRun.h" /* StgReturn */
10 #include "StgStartup.h"
13 * This module contains the two entry points and the final exit point
14 * to/from the Haskell world. We can enter either by:
16 * a) returning to the address on the top of the stack, or
17 * b) entering the closure on the top of the stack
19 * the function stg_stop_thread_entry is the final exit for a
20 * thread: it is the last return address on the stack. It returns
21 * to the scheduler marking the thread as finished.
24 #define CHECK_SENSIBLE_REGS() \
25 ASSERT(Hp != (P_)0); \
26 ASSERT(Sp != (P_)0); \
27 ASSERT(Su != (StgUpdateFrame *)0); \
28 ASSERT(SpLim != (P_)0); \
29 ASSERT(HpLim != (P_)0); \
30 ASSERT(Sp <= (P_)Su); \
31 ASSERT(SpLim - RESERVED_STACK_WORDS <= Sp); \
34 /* -----------------------------------------------------------------------------
35 Returning from the STG world.
37 This is a polymorphic return address, meaning that any old constructor
38 can be returned, we don't care (actually, it's probably going to be
39 an IOok constructor, which will indirect through the vector table
41 -------------------------------------------------------------------------- */
43 EXTFUN(stg_stop_thread_entry);
46 #define STOP_THREAD_BITMAP 1
48 #define STOP_THREAD_BITMAP 0
51 /* VEC_POLY_INFO expects to see these names - but they should all be the same. */
52 #define stg_stop_thread_0_entry stg_stop_thread_entry
53 #define stg_stop_thread_1_entry stg_stop_thread_entry
54 #define stg_stop_thread_2_entry stg_stop_thread_entry
55 #define stg_stop_thread_3_entry stg_stop_thread_entry
56 #define stg_stop_thread_4_entry stg_stop_thread_entry
57 #define stg_stop_thread_5_entry stg_stop_thread_entry
58 #define stg_stop_thread_6_entry stg_stop_thread_entry
59 #define stg_stop_thread_7_entry stg_stop_thread_entry
61 VEC_POLY_INFO_TABLE(stg_stop_thread,STOP_THREAD_BITMAP,0,0,0,STOP_FRAME);
63 STGFUN(stg_stop_thread_entry)
70 * The top-top-level closures (e.g., "main") are of type "IO a".
71 * When entered, they perform an IO action and return an 'a' in R1.
73 * We save R1 on top of the stack where the scheduler can find it,
74 * tidy up the registers and return to the scheduler.
77 /* Move Su just off the end of the stack, we're about to spam the
78 * STOP_FRAME with the return value.
80 Su = stgCast(StgUpdateFrame*,Sp+1);
81 *stgCast(StgClosure**,Sp) = R1.cl;
83 SaveThreadState(); /* inline! */
85 /* R1 contains the return value of the thread */
86 R1.p = (P_)ThreadFinished;
92 /* -----------------------------------------------------------------------------
93 Start a thread from the scheduler by returning to the address on
94 the top of the stack (and popping the address). This is used for
95 returning to the slow entry point of a function after a garbage collection
96 or re-schedule. The slow entry point expects the stack to contain the
97 pending arguments only.
98 -------------------------------------------------------------------------- */
100 STGFUN(stg_returnToStackTop)
104 CHECK_SENSIBLE_REGS();
110 /* -----------------------------------------------------------------------------
111 Start a thread from the scheduler by entering the closure pointed
112 to by the word on the top of the stack.
113 -------------------------------------------------------------------------- */
115 STGFUN(stg_enterStackTop)
119 CHECK_SENSIBLE_REGS();
120 /* don't count this enter for ticky-ticky profiling */
123 JMP_(GET_ENTRY(R1.cl));
128 /* -----------------------------------------------------------------------------
129 Special STG entry points for module registration.
130 -------------------------------------------------------------------------- */
134 STGFUN(stg_register_ret)
146 PUSH_REGISTER_STACK(stg_register_ret);
147 PUSH_REGISTER_STACK(_regPrelude);
152 /* PrelGHC doesn't really exist... */
154 START_REGISTER_CCS(_regPrelGHC);