/* -----------------------------------------------------------------------------
- * $Id: PrimOps.hc,v 1.47 2000/03/20 09:42:49 andy Exp $
+ * $Id: PrimOps.hc,v 1.57 2000/11/07 13:30:41 simonmar Exp $
*
* (c) The GHC Team, 1998-2000
*
#include "StablePriv.h"
#include "HeapStackCheck.h"
#include "StgRun.h"
-#include "ITimer.h"
+#include "Itimer.h"
#include "Prelude.h"
/* ** temporary **
FE_ \
}
-newByteArray(Char, sizeof(C_))
-newByteArray(Int, sizeof(I_));
-newByteArray(Word, sizeof(W_));
-newByteArray(Addr, sizeof(P_));
-newByteArray(Float, sizeof(StgFloat));
-newByteArray(Double, sizeof(StgDouble));
-newByteArray(StablePtr, sizeof(StgStablePtr));
+newByteArray(Char, 1)
+/* Char arrays really contain only 8-bit bytes for compatibility. */
+newByteArray(Int, sizeof(I_))
+newByteArray(Word, sizeof(W_))
+newByteArray(Addr, sizeof(P_))
+newByteArray(Float, sizeof(StgFloat))
+newByteArray(Double, sizeof(StgDouble))
+newByteArray(StablePtr, sizeof(StgStablePtr))
FN_(newArrayzh_fast)
{
-------------------------------------------------------------------------- */
#ifndef PAR
-FN_(makeForeignObjzh_fast)
+FN_(mkForeignObjzh_fast)
{
/* R1.p = ptr to foreign object,
*/
StgForeignObj *result;
FB_
- HP_CHK_GEN_TICKY(sizeofW(StgForeignObj), NO_PTRS, makeForeignObjzh_fast,);
+ HP_CHK_GEN_TICKY(sizeofW(StgForeignObj), NO_PTRS, mkForeignObjzh_fast,);
TICK_ALLOC_PRIM(sizeofW(StgHeader),
sizeofW(StgForeignObj)-sizeofW(StgHeader), 0);
CCS_ALLOC(CCCS,sizeofW(StgForeignObj)); /* ccs prof */
FE_
}
-FN_(addr2Integerzh_fast)
-{
- MP_INT result;
- char *str;
- FB_
-
- MAYBE_GC(NO_PTRS,addr2Integerzh_fast);
-
- /* args: R1 :: Addr# */
- str = R1.a;
-
- /* Perform the operation */
- if (RET_STGCALL3(int, mpz_init_set_str,&result,(str),/*base*/10))
- abort();
-
- /* returns (# size :: Int#,
- data :: ByteArray#
- #)
- */
- TICK_RET_UNBOXED_TUP(2);
- RET_NP(result._mp_size,
- result._mp_d - sizeofW(StgArrWords));
- FE_
-}
/*
* 'long long' primops for converting to/from Integers.
FE_ \
}
+#define GMP_TAKE1_RET1(name,mp_fun) \
+FN_(name) \
+{ \
+ MP_INT arg1, result; \
+ I_ s1; \
+ StgArrWords* d1; \
+ FB_ \
+ \
+ /* call doYouWantToGC() */ \
+ MAYBE_GC(R2_PTR, name); \
+ \
+ d1 = (StgArrWords *)R2.p; \
+ s1 = R1.i; \
+ \
+ arg1._mp_alloc = d1->words; \
+ arg1._mp_size = (s1); \
+ arg1._mp_d = (unsigned long int *) (BYTE_ARR_CTS(d1)); \
+ \
+ STGCALL1(mpz_init,&result); \
+ \
+ /* Perform the operation */ \
+ STGCALL2(mp_fun,&result,&arg1); \
+ \
+ TICK_RET_UNBOXED_TUP(2); \
+ RET_NP(result._mp_size, \
+ result._mp_d-sizeofW(StgArrWords)); \
+ FE_ \
+}
+
#define GMP_TAKE2_RET2(name,mp_fun) \
FN_(name) \
{ \
GMP_TAKE2_RET1(quotIntegerzh_fast, mpz_tdiv_q);
GMP_TAKE2_RET1(remIntegerzh_fast, mpz_tdiv_r);
GMP_TAKE2_RET1(divExactIntegerzh_fast, mpz_divexact);
+GMP_TAKE2_RET1(andIntegerzh_fast, mpz_and);
+GMP_TAKE2_RET1(orIntegerzh_fast, mpz_ior);
+GMP_TAKE2_RET1(xorIntegerzh_fast, mpz_xor);
+GMP_TAKE1_RET1(complementIntegerzh_fast, mpz_com);
GMP_TAKE2_RET2(quotRemIntegerzh_fast, mpz_tdiv_qr);
GMP_TAKE2_RET2(divModIntegerzh_fast, mpz_fdiv_qr);
-#ifndef FLOATS_AS_DOUBLES
FN_(decodeFloatzh_fast)
{
MP_INT mantissa;
RET_NNP(exponent,mantissa._mp_size,p);
FE_
}
-#endif /* !FLOATS_AS_DOUBLES */
#define DOUBLE_MANTISSA_SIZE (sizeofW(StgDouble))
#define ARR_SIZE (sizeofW(StgArrWords) + DOUBLE_MANTISSA_SIZE)
FE_
}
+FN_(tryTakeMVarzh_fast)
+{
+ StgMVar *mvar;
+ StgClosure *val;
+ const StgInfoTable *info;
+
+ FB_
+ /* args: R1 = MVar closure */
+
+ mvar = (StgMVar *)R1.p;
+
+#ifdef SMP
+ info = LOCK_CLOSURE(mvar);
+#else
+ info = GET_INFO(mvar);
+#endif
+
+ if (info == &EMPTY_MVAR_info) {
+
+#ifdef SMP
+ /* unlock the MVar */
+ mvar->header.info = &EMPTY_MVAR_info;
+#endif
+
+ /* HACK: we need a pointer to pass back, so we abuse NO_FINALIZER_closure */
+ RET_NP(0, &NO_FINALIZER_closure);
+ }
+
+ val = mvar->value;
+ mvar->value = (StgClosure *)&END_TSO_QUEUE_closure;
+
+ /* do this last... we might have locked the MVar in the SMP case,
+ * and writing the info pointer will unlock it.
+ */
+ SET_INFO(mvar,&EMPTY_MVAR_info);
+
+ TICK_RET_UNBOXED_TUP(1);
+ RET_NP(1,val);
+ FE_
+}
+
FN_(putMVarzh_fast)
{
StgMVar *mvar;
if (mvar->head == (StgTSO *)&END_TSO_QUEUE_closure) {
mvar->tail = (StgTSO *)&END_TSO_QUEUE_closure;
}
+
+ /* unlocks the MVar in the SMP case */
+ SET_INFO(mvar,&FULL_MVAR_info);
+
+ /* yield, to give the newly woken thread a chance to take the MVar */
+ JMP_(stg_yield_noregs);
}
/* unlocks the MVar in the SMP case */
SET_INFO(mvar,&FULL_MVAR_info);
- /* ToDo: yield here for better communication performance? */
JMP_(ENTRY_CODE(Sp[0]));
FE_
}
FN_(delayzh_fast)
{
+ StgTSO *t, *prev;
+ nat target;
FB_
/* args: R1.i */
ASSERT(CurrentTSO->why_blocked == NotBlocked);
ACQUIRE_LOCK(&sched_mutex);
- /* Add on ticks_since_select, since these will be subtracted at
- * the next awaitEvent call.
- */
-#if defined(HAVE_SETITIMER)
- CurrentTSO->block_info.delay = R1.i + ticks_since_select;
-#else
- CurrentTSO->block_info.target = R1.i + getourtimeofday();
-#endif
+ target = (R1.i / (TICK_MILLISECS*1000)) + timestamp + ticks_since_timestamp;
+ CurrentTSO->block_info.target = target;
- APPEND_TO_BLOCKED_QUEUE(CurrentTSO);
+ /* Insert the new thread in the sleeping queue. */
+ prev = NULL;
+ t = sleeping_queue;
+ while (t != END_TSO_QUEUE && t->block_info.target < target) {
+ prev = t;
+ t = t->link;
+ }
+
+ CurrentTSO->link = t;
+ if (prev == NULL) {
+ sleeping_queue = CurrentTSO;
+ } else {
+ prev->link = CurrentTSO;
+ }
RELEASE_LOCK(&sched_mutex);
JMP_(stg_block_noregs);
FE_
}
-