/* -----------------------------------------------------------------------------
- * $Id: PrimOps.hc,v 1.21 1999/03/05 10:21:27 sof Exp $
+ * $Id: PrimOps.hc,v 1.31 1999/10/13 16:39:23 simonmar Exp $
*
* (c) The GHC Team, 1998-1999
*
#include "Storage.h"
#include "BlockAlloc.h" /* tmp */
#include "StablePriv.h"
+#include "HeapStackCheck.h"
+#include "StgRun.h"
/* ** temporary **
# define RET_NP(a,b) PUSH_N(3,a); PUSH_P(1,b); PUSHED(3)
# define RET_PPP(a,b,c) PUSH_P(3,a); PUSH_P(2,b); PUSH_P(1,c); PUSHED(3)
-# define RET_NNP(a,b,c) PUSH_N(6,a); PUSH_N(4,b); PUSH_N(2,c); PUSHED(6)
+# define RET_NNP(a,b,c) PUSH_N(5,a); PUSH_N(3,b); PUSH_P(1,c); PUSHED(5)
# define RET_NNNP(a,b,c,d) PUSH_N(7,a); PUSH_N(5,b); PUSH_N(3,c); PUSH_P(1,d); PUSHED(7)
# define RET_NPNP(a,b,c,d) PUSH_N(6,a); PUSH_P(4,b); PUSH_N(3,c); PUSH_P(1,d); PUSHED(6)
/* Args: R1.p = initialisation value */
FB_
- HP_CHK_GEN(sizeofW(StgMutVar), R1_PTR, newMutVarzh_fast,);
+ HP_CHK_GEN_TICKY(sizeofW(StgMutVar), R1_PTR, newMutVarzh_fast,);
TICK_ALLOC_PRIM(sizeofW(StgHeader)+1,1, 0); /* hack, dependent on rep. */
CCS_ALLOC(CCCS,sizeofW(StgMutVar));
StgForeignObj *result;
FB_
- HP_CHK_GEN(sizeofW(StgForeignObj), NO_PTRS, makeForeignObjzh_fast,);
+ HP_CHK_GEN_TICKY(sizeofW(StgForeignObj), NO_PTRS, makeForeignObjzh_fast,);
TICK_ALLOC_PRIM(sizeofW(StgHeader),
sizeofW(StgForeignObj)-sizeofW(StgHeader), 0);
CCS_ALLOC(CCCS,sizeofW(StgForeignObj)); /* ccs prof */
StgWeak *w;
FB_
- HP_CHK_GEN(sizeofW(StgWeak), R1_PTR|R2_PTR|R3_PTR, mkWeakzh_fast,);
+ HP_CHK_GEN_TICKY(sizeofW(StgWeak), R1_PTR|R2_PTR|R3_PTR, mkWeakzh_fast,);
TICK_ALLOC_PRIM(sizeofW(StgHeader)+1, // +1 is for the link field
sizeofW(StgWeak)-sizeofW(StgHeader)-1, 0);
CCS_ALLOC(CCCS,sizeofW(StgWeak)); /* ccs prof */
FB_
val = R1.i;
- HP_CHK_GEN(sizeofW(StgArrWords)+1, NO_PTRS, int2Integerzh_fast,);
+ HP_CHK_GEN_TICKY(sizeofW(StgArrWords)+1, NO_PTRS, int2Integerzh_fast,);
TICK_ALLOC_PRIM(sizeofW(StgArrWords),1,0);
CCS_ALLOC(CCCS,sizeofW(StgArrWords)+1); /* ccs prof */
- p = stgCast(StgArrWords*,Hp)-1;
+ p = (StgArrWords *)Hp - 1;
SET_ARR_HDR(p, &ARR_WORDS_info, CCCS, 1);
/* mpz_set_si is inlined here, makes things simpler */
FB_
val = R1.w;
- HP_CHK_GEN(sizeofW(StgArrWords)+1, NO_PTRS, word2Integerzh_fast,)
+ HP_CHK_GEN_TICKY(sizeofW(StgArrWords)+1, NO_PTRS, word2Integerzh_fast,)
TICK_ALLOC_PRIM(sizeofW(StgArrWords),1,0);
CCS_ALLOC(CCCS,sizeofW(StgArrWords)+1); /* ccs prof */
- p = stgCast(StgArrWords*,Hp)-1;
+ p = (StgArrWords *)Hp - 1;
SET_ARR_HDR(p, &ARR_WORDS_info, CCCS, 1);
if (val != 0) {
/* minimum is one word */
words_needed = 1;
}
- HP_CHK_GEN(sizeofW(StgArrWords)+words_needed, NO_PTRS, int64ToIntegerzh_fast,)
+ HP_CHK_GEN_TICKY(sizeofW(StgArrWords)+words_needed, NO_PTRS, int64ToIntegerzh_fast,)
TICK_ALLOC_PRIM(sizeofW(StgArrWords),words_needed,0);
CCS_ALLOC(CCCS,sizeofW(StgArrWords)+words_needed); /* ccs prof */
- p = stgCast(StgArrWords*,(Hp-words_needed+1))-1;
+ p = (StgArrWords *)(Hp-words_needed+1) - 1;
SET_ARR_HDR(p, &ARR_WORDS_info, CCCS, words_needed);
if ( val < 0LL ) {
} else {
words_needed = 1;
}
- HP_CHK_GEN(sizeofW(StgArrWords)+words_needed, NO_PTRS, word64ToIntegerzh_fast,)
+ HP_CHK_GEN_TICKY(sizeofW(StgArrWords)+words_needed, NO_PTRS, word64ToIntegerzh_fast,)
TICK_ALLOC_PRIM(sizeofW(StgArrWords),words_needed,0);
CCS_ALLOC(CCCS,sizeofW(StgArrWords)+words_needed); /* ccs prof */
- p = stgCast(StgArrWords*,(Hp-words_needed+1))-1;
+ p = (StgArrWords *)(Hp-words_needed+1) - 1;
SET_ARR_HDR(p, &ARR_WORDS_info, CCCS, words_needed);
hi = (W_)((LW_)val / 0x100000000ULL);
/* arguments: F1 = Float# */
arg = F1;
- HP_CHK_GEN(sizeof(StgArrWords)+1, NO_PTRS, decodeFloatzh_fast,);
+ HP_CHK_GEN_TICKY(sizeofW(StgArrWords)+1, NO_PTRS, decodeFloatzh_fast,);
TICK_ALLOC_PRIM(sizeofW(StgArrWords),1,0);
CCS_ALLOC(CCCS,sizeofW(StgArrWords)+1); /* ccs prof */
/* Be prepared to tell Lennart-coded __decodeFloat */
/* where mantissa._mp_d can be put (it does not care about the rest) */
- p = stgCast(StgArrWords*,Hp)-1;
+ p = (StgArrWords *)Hp - 1;
SET_ARR_HDR(p,&ARR_WORDS_info,CCCS,1)
mantissa._mp_d = (void *)BYTE_ARR_CTS(p);
}
#endif /* !FLOATS_AS_DOUBLES */
-#define DOUBLE_MANTISSA_SIZE (sizeof(StgDouble)/sizeof(W_))
-#define ARR_SIZE (sizeof(StgArrWords) + DOUBLE_MANTISSA_SIZE)
+#define DOUBLE_MANTISSA_SIZE (sizeofW(StgDouble))
+#define ARR_SIZE (sizeofW(StgArrWords) + DOUBLE_MANTISSA_SIZE)
FN_(decodeDoublezh_fast)
{ MP_INT mantissa;
/* arguments: D1 = Double# */
arg = D1;
- HP_CHK_GEN(ARR_SIZE, NO_PTRS, decodeDoublezh_fast,);
- TICK_ALLOC_PRIM(sizeof(StgArrWords),DOUBLE_MANTISSA_SIZE,0);
+ HP_CHK_GEN_TICKY(ARR_SIZE, NO_PTRS, decodeDoublezh_fast,);
+ TICK_ALLOC_PRIM(sizeofW(StgArrWords),DOUBLE_MANTISSA_SIZE,0);
CCS_ALLOC(CCCS,ARR_SIZE); /* ccs prof */
/* Be prepared to tell Lennart-coded __decodeDouble */
/* where mantissa.d can be put (it does not care about the rest) */
- p = stgCast(StgArrWords*,Hp-ARR_SIZE+1);
+ p = (StgArrWords *)(Hp-ARR_SIZE+1);
SET_ARR_HDR(p, &ARR_WORDS_info, CCCS, DOUBLE_MANTISSA_SIZE);
mantissa._mp_d = (void *)BYTE_ARR_CTS(p);
FB_
/* args: R1 = closure to spark */
- if (closure_SHOULD_SPARK(stgCast(StgClosure*,R1.p))) {
+ MAYBE_GC(R1_PTR, forkzh_fast);
- MAYBE_GC(R1_PTR, forkzh_fast);
-
- /* create it right now, return ThreadID in R1 */
- R1.t = RET_STGCALL2(StgTSO *, createIOThread,
- RtsFlags.GcFlags.initialStkSize, R1.cl);
+ /* create it right now, return ThreadID in R1 */
+ R1.t = RET_STGCALL2(StgTSO *, createIOThread,
+ RtsFlags.GcFlags.initialStkSize, R1.cl);
- /* switch at the earliest opportunity */
- context_switch = 1;
- }
+ /* switch at the earliest opportunity */
+ context_switch = 1;
JMP_(ENTRY_CODE(Sp[0]));
FE_
}
+FN_(yieldzh_fast)
+{
+ FB_
+ JMP_(stg_yield_noregs);
+ FE_
+}
+
FN_(killThreadzh_fast)
{
FB_
- /* args: R1.p = TSO to kill */
+ /* args: R1.p = TSO to kill, R2.p = Exception */
/* The thread is dead, but the TSO sticks around for a while. That's why
* we don't have to explicitly remove it from any queues it might be on.
*/
- STGCALL1(deleteThread, (StgTSO *)R1.p);
- /* We might have killed ourselves. In which case, better return to the
- * scheduler...
+ /* We might have killed ourselves. In which case, better be *very*
+ * careful. If the exception killed us, then return to the scheduler.
+ * If the exception went to a catch frame, we'll just continue from
+ * the handler.
*/
- if ((StgTSO *)R1.p == CurrentTSO) {
- JMP_(stg_stop_thread_entry); /* leave semi-gracefully */
+ if (R1.t == CurrentTSO) {
+ SaveThreadState(); /* inline! */
+ STGCALL2(raiseAsync, R1.t, R2.cl);
+ if (CurrentTSO->whatNext == ThreadKilled) {
+ R1.w = ThreadYielding;
+ JMP_(StgReturn);
+ }
+ LoadThreadState();
+ if (CurrentTSO->whatNext == ThreadEnterGHC) {
+ R1.w = Sp[0];
+ Sp++;
+ JMP_(GET_ENTRY(R1.cl));
+ } else {
+ barf("killThreadzh_fast");
+ }
+ } else {
+ STGCALL2(raiseAsync, R1.t, R2.cl);
}
JMP_(ENTRY_CODE(Sp[0]));
FB_
/* args: none */
- HP_CHK_GEN(sizeofW(StgMVar), NO_PTRS, newMVarzh_fast,);
+ HP_CHK_GEN_TICKY(sizeofW(StgMVar), NO_PTRS, newMVarzh_fast,);
TICK_ALLOC_PRIM(sizeofW(StgMutVar)-1, // consider head,tail,link as admin wds
1, 0);
CCS_ALLOC(CCCS,sizeofW(StgMVar)); /* ccs prof */
mvar = (StgMVar *) (Hp - sizeofW(StgMVar) + 1);
- SET_INFO(mvar,&EMPTY_MVAR_info);
+ SET_HDR(mvar,&EMPTY_MVAR_info,CCCS);
mvar->head = mvar->tail = (StgTSO *)&END_TSO_QUEUE_closure;
mvar->value = (StgClosure *)&END_TSO_QUEUE_closure;
mvar->tail->link = CurrentTSO;
}
CurrentTSO->link = (StgTSO *)&END_TSO_QUEUE_closure;
+ CurrentTSO->why_blocked = BlockedOnMVar;
+ CurrentTSO->block_info.closure = (StgClosure *)mvar;
mvar->tail = CurrentTSO;
BLOCK(R1_PTR, takeMVarzh_fast);
FN_(putMVarzh_fast)
{
StgMVar *mvar;
- StgTSO *tso;
FB_
/* args: R1 = MVar, R2 = value */
mvar = (StgMVar *)R1.p;
if (GET_INFO(mvar) == &FULL_MVAR_info) {
- fflush(stdout);
fprintf(stderr, "putMVar#: MVar already full.\n");
stg_exit(EXIT_FAILURE);
}
SET_INFO(mvar,&FULL_MVAR_info);
mvar->value = R2.cl;
- /* wake up the first thread on the queue,
- * it will continue with the takeMVar operation and mark the MVar
- * empty again.
+ /* wake up the first thread on the queue, it will continue with the
+ * takeMVar operation and mark the MVar empty again.
*/
- tso = mvar->head;
- if (tso != (StgTSO *)&END_TSO_QUEUE_closure) {
- PUSH_ON_RUN_QUEUE(tso);
- mvar->head = tso->link;
- tso->link = (StgTSO *)&END_TSO_QUEUE_closure;
+ if (mvar->head != (StgTSO *)&END_TSO_QUEUE_closure) {
+ ASSERT(mvar->head->why_blocked == BlockedOnMVar);
+ mvar->head = RET_STGCALL1(StgTSO *,unblockOne,mvar->head);
if (mvar->head == (StgTSO *)&END_TSO_QUEUE_closure) {
mvar->tail = (StgTSO *)&END_TSO_QUEUE_closure;
}
StgStableName *sn_obj;
FB_
- HP_CHK_GEN(sizeofW(StgStableName), R1_PTR, makeStableNamezh_fast,);
+ HP_CHK_GEN_TICKY(sizeofW(StgStableName), R1_PTR, makeStableNamezh_fast,);
TICK_ALLOC_PRIM(sizeofW(StgHeader),
sizeofW(StgStableName)-sizeofW(StgHeader), 0);
CCS_ALLOC(CCCS,sizeofW(StgStableName)); /* ccs prof */
RET_P(sn_obj);
}
+/* -----------------------------------------------------------------------------
+ Thread I/O blocking primitives
+ -------------------------------------------------------------------------- */
+
+FN_(waitReadzh_fast)
+{
+ FB_
+ /* args: R1.i */
+ ASSERT(CurrentTSO->why_blocked == NotBlocked);
+ CurrentTSO->why_blocked = BlockedOnRead;
+ CurrentTSO->block_info.fd = R1.i;
+ PUSH_ON_BLOCKED_QUEUE(CurrentTSO);
+ JMP_(stg_block_noregs);
+ FE_
+}
+
+FN_(waitWritezh_fast)
+{
+ FB_
+ /* args: R1.i */
+ ASSERT(CurrentTSO->why_blocked == NotBlocked);
+ CurrentTSO->why_blocked = BlockedOnWrite;
+ CurrentTSO->block_info.fd = R1.i;
+ PUSH_ON_BLOCKED_QUEUE(CurrentTSO);
+ JMP_(stg_block_noregs);
+ FE_
+}
+
+FN_(delayzh_fast)
+{
+ FB_
+ /* args: R1.i */
+ ASSERT(CurrentTSO->why_blocked == NotBlocked);
+ CurrentTSO->why_blocked = BlockedOnDelay;
+
+ /* Add on ticks_since_select, since these will be subtracted at
+ * the next awaitEvent call.
+ */
+ CurrentTSO->block_info.delay = R1.i + ticks_since_select;
+
+ PUSH_ON_BLOCKED_QUEUE(CurrentTSO);
+ JMP_(stg_block_noregs);
+ FE_
+}
+
#endif /* COMPILER */