1 \section[stable-ptr-ops]{Stable Pointer Operations}
3 The code that implements @performIO@ is mostly in
4 @ghc/runtime/c-as-asm/PerformIO.lhc@. However, this code can be
5 called from the C world so it goes in a @.lc@ file.
7 This code is based heavily on the code in @ghc/runtime/main/main.lc@.
9 It is used to call a (stable pointer to a) function of type
10 @IoWorld -> PrimIntAndIoWorld@ (ie @PrimIO_Int#@).
12 (I doubt very much that this works at the moment - and we're going to
13 change it to take/return a byte array anyway. Code in PerformIO.lhc
21 extern StgPtr unstable_Closure;
23 extern int CStackDelta;
29 enterStablePtr(stableIndex, startCode)
30 StgStablePtr stableIndex;
34 = _deRefStablePointer(stableIndex, StorageMgrInfo.StablePointerTable);
36 /* ToDo: Set arity to right value - if necessary */
38 /* Inactive code for computing the chunk of C stack we have allocated
39 since initially leaving Haskell land.
41 #if 0 && defined(CONCURRENT) && defined(i386_TARGET_ARCH)
42 __asm__ volatile ("mov %%esp,%0" : "=m" (CurrentRegTable->rWrapReturn));
43 CStackDelta=(int)(((unsigned int)CurrentRegTable->rCstkptr - (unsigned int)CurrentRegTable->rWrapReturn) / sizeof(W_));
44 CurrentTSOinC=CurrentTSO;
46 fprintf(stderr,"enterStablePtr: current: %#x c-entry: %#x (delta %d)\n", CurrentRegTable->rWrapReturn, CurrentRegTable->rCstkptr, CStackDelta);
47 __asm__ volatile ("mov %%esp,%0" : "=m" (CurrentRegTable->rWrapReturn));
48 CStackDelta=(int)(((unsigned int)CurrentRegTable->rCstkptr - (unsigned int)CurrentRegTable->rWrapReturn) / sizeof(W_));
52 * Combining Concurrent Haskell and stable pointers poses a headache or
53 * two. If the thread that jumps into Haskell causes a context switch,
54 * we're in deep trouble, as miniInterpret() is used to enter the threaded world,
55 * which stash away return address and callee-saves registers on the C
58 * If the thread should happen to context switch, the scheduler is
59 * currently coded to use longjmp() to jump from the rescheduling
60 * code to the main scheduler loop. i.e., we unwind chunks of the
61 * C stack, including the return address++ the thread left there
62 * before entering the stable pointer.
64 * Ideally, we would like to impose no restrictions on the use of
65 * stable pointers with Concurrent Haskell, but currently we
66 * do turn off heap check context switching when a thread jumps into
67 * Haskell from C. This reduces the `risk' of a context switch, but
68 * doesn't solve the problem - a thread that blocks will still
69 * force a re-schedule. To cope with this situation, we use a counter
70 * to keep track of whether any threads have entered Haskell from C.
71 * If any have, we avoid longjmp()ing in the RTS to preserve the region
72 * of the C stack that the thread expects to be there when it exits.
74 * This scheme is a hack (no, really!) to get Haskell callbacks to work
75 * with Concurrent Haskell. It is currently only supported for x86 platforms
76 * (due to use of asm to get at stack pointer in PerformIO.lhc)
78 * ToDo: do Right in the new RTS.
80 #if defined(CONCURRENT) && defined(i386_TARGET_ARCH)
82 miniInterpret(startCode);
85 miniInterpret(startCode);
88 #if 0 && defined(DEBUG)
89 if (CurrentTSO == CurrentTSOinC) {
92 /* C stack should have been reconstructed by now (we'll soon find out..) */
95 __asm__ volatile ("mov %%esp,%0" : "=m" (p));
96 fprintf(stderr,"enterStablePtr-end: current: %#x c-entry: %#x\n", p, CurrentRegTable->rCstkptr);
103 EXTFUN(startPerformIO);
105 extern void checkInCCallGC(STG_NO_ARGS);
108 performIO(stableIndex)
109 StgStablePtr stableIndex;
112 enterStablePtr( stableIndex, (StgFunPtr) startPerformIO );
115 extern StgInt enterInt_Result;
116 EXTFUN(startEnterInt);
119 enterInt(stableIndex)
120 StgStablePtr stableIndex;
123 enterStablePtr( stableIndex, (StgFunPtr) startEnterInt );
124 return enterInt_Result;
127 extern StgFloat enterFloat_Result;
128 EXTFUN(startEnterFloat);
131 enterFloat(stableIndex)
132 StgStablePtr stableIndex;
135 enterStablePtr( stableIndex, (StgFunPtr) startEnterFloat );
136 return enterFloat_Result;
142 deRefStablePointer(stableIndex)
143 StgStablePtr stableIndex;
145 return _deRefStablePointer(stableIndex, StorageMgrInfo.StablePointerTable);
149 Despite the file name, we have a little ForeignObj operation here - not
150 worth putting in a file by itself.
162 And some code that HAS NO RIGHT being here.
165 StgStablePtr softHeapOverflowHandler = -1;
168 catchSoftHeapOverflow( newHandler, deltaLimit )
169 StgStablePtr newHandler;
172 StgStablePtr oldHandler = softHeapOverflowHandler;
174 /* If we're in a _ccall_GC_ then HpLim will be stored in SAVE_HpLim
175 which provides an easy way of changing it. */
178 StorageMgrInfo.hardHpOverflowSize += deltaLimit;
179 SAVE_HpLim -= deltaLimit;
181 if (StorageMgrInfo.hardHpOverflowSize < 0) {
182 fprintf(stderr, "Error: Setting Hard Heap Overflow Size to negative value!\n");
186 softHeapOverflowHandler = newHandler;
191 getSoftHeapOverflowHandler(STG_NO_ARGS)
193 return (StgInt) softHeapOverflowHandler;