summaryrefslogtreecommitdiff
path: root/src/runtime/rcoexpr.r
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/rcoexpr.r')
-rw-r--r--src/runtime/rcoexpr.r315
1 files changed, 315 insertions, 0 deletions
diff --git a/src/runtime/rcoexpr.r b/src/runtime/rcoexpr.r
new file mode 100644
index 0000000..4036ef6
--- /dev/null
+++ b/src/runtime/rcoexpr.r
@@ -0,0 +1,315 @@
+/*
+ * File: rcoexpr.r -- co_init, co_chng
+ */
+
+#if COMPILER
+static continuation coexpr_fnc; /* function to call after switching stacks */
+#endif /* COMPILER */
+
+/*
+ * co_init - use the contents of the refresh block to initialize the
+ * co-expression.
+ */
+void co_init(sblkp)
+struct b_coexpr *sblkp;
+{
+#ifndef Coexpr
+ syserr("co_init() called, but co-expressions not implemented");
+#else /* Coexpr */
+ register word *newsp;
+ register struct b_refresh *rblkp;
+ register dptr dp, dsp;
+ int frame_size;
+ word stack_strt;
+ int na, nl, nt, i;
+
+ /*
+ * Get pointer to refresh block.
+ */
+ rblkp = (struct b_refresh *)BlkLoc(sblkp->freshblk);
+
+#if COMPILER
+ na = rblkp->nargs; /* number of arguments */
+ nl = rblkp->nlocals; /* number of locals */
+ nt = rblkp->ntemps; /* number of temporaries */
+
+ /*
+ * The C stack must be aligned on the correct boundary. For up-growing
+ * stacks, the C stack starts after the initial procedure frame of
+ * the co-expression block. For down-growing stacks, the C stack starts
+ * at the last word of the co-expression block.
+ */
+#ifdef UpStack
+ frame_size = sizeof(struct p_frame) + sizeof(struct descrip) * (nl + na +
+ nt - 1) + rblkp->wrk_size;
+ stack_strt = (word)((char *)&sblkp->pf + frame_size + StackAlign*WordSize);
+#else /* UpStack */
+ stack_strt = (word)((char *)sblkp + stksize - WordSize);
+#endif /* UpStack */
+ sblkp->cstate[0] = stack_strt & ~(WordSize * StackAlign - 1);
+
+ sblkp->es_argp = &sblkp->pf.tend.d[nl + nt]; /* args follow temporaries */
+
+#else /* COMPILER */
+
+ na = (rblkp->pfmkr).pf_nargs + 1; /* number of arguments */
+ nl = (int)rblkp->numlocals; /* number of locals */
+
+ /*
+ * The interpreter stack starts at word after co-expression stack block.
+ * C stack starts at end of stack region on machines with down-growing C
+ * stacks and somewhere in the middle of the region.
+ *
+ * The C stack is aligned on a doubleword boundary. For up-growing
+ * stacks, the C stack starts in the middle of the stack portion
+ * of the static block. For down-growing stacks, the C stack starts
+ * at the last word of the static block.
+ */
+
+ newsp = (word *)((char *)sblkp + sizeof(struct b_coexpr));
+
+#ifdef UpStack
+ sblkp->cstate[0] =
+ ((word)((char *)sblkp + (stksize - sizeof(*sblkp))/2)
+ &~((word)WordSize*StackAlign-1));
+#else /* UpStack */
+ sblkp->cstate[0] =
+ ((word)((char *)sblkp + stksize - WordSize)
+ &~((word)WordSize*StackAlign-1));
+#endif /* UpStack */
+
+ sblkp->es_argp = (dptr)newsp; /* args are first thing on stack */
+
+#endif /* COMPILER */
+
+ /*
+ * Copy arguments onto new stack.
+ */
+ dsp = sblkp->es_argp;
+ dp = rblkp->elems;
+ for (i = 1; i <= na; i++)
+ *dsp++ = *dp++;
+
+ /*
+ * Set up state variables and initialize procedure frame.
+ */
+#if COMPILER
+ sblkp->es_pfp = &sblkp->pf;
+ sblkp->es_tend = &sblkp->pf.tend;
+ sblkp->pf.old_pfp = NULL;
+ sblkp->pf.rslt = NULL;
+ sblkp->pf.succ_cont = NULL;
+ sblkp->pf.tend.previous = NULL;
+ sblkp->pf.tend.num = nl + na + nt;
+ sblkp->es_actstk = NULL;
+#else /* COMPILER */
+ *((struct pf_marker *)dsp) = rblkp->pfmkr;
+ sblkp->es_pfp = (struct pf_marker *)dsp;
+ sblkp->es_tend = NULL;
+ dsp = (dptr)((word *)dsp + Vwsizeof(*pfp));
+ sblkp->es_ipc.opnd = rblkp->ep;
+ sblkp->es_gfp = 0;
+ sblkp->es_efp = 0;
+ sblkp->es_ilevel = 0;
+#endif /* COMPILER */
+ sblkp->tvalloc = NULL;
+
+ /*
+ * Copy locals into the co-expression.
+ */
+#if COMPILER
+ dsp = sblkp->pf.tend.d;
+#endif /* COMPILER */
+ for (i = 1; i <= nl; i++)
+ *dsp++ = *dp++;
+
+#if COMPILER
+ /*
+ * Initialize temporary variables.
+ */
+ for (i = 1; i <= nt; i++)
+ *dsp++ = nulldesc;
+#else /* COMPILER */
+ /*
+ * Push two null descriptors on the stack.
+ */
+ *dsp++ = nulldesc;
+ *dsp++ = nulldesc;
+
+ sblkp->es_sp = (word *)dsp - 1;
+#endif /* COMPILER */
+
+#endif /* Coexpr */
+ }
+
+/*
+ * co_chng - high-level co-expression context switch.
+ */
+int co_chng(ncp, valloc, rsltloc, swtch_typ, first)
+struct b_coexpr *ncp;
+struct descrip *valloc; /* location of value being transmitted */
+struct descrip *rsltloc;/* location to put result */
+int swtch_typ; /* A_Coact, A_Coret, A_Cofail, or A_MTEvent */
+int first;
+{
+#ifndef Coexpr
+ syserr("co_chng() called, but co-expressions not implemented");
+#else /* Coexpr */
+ register struct b_coexpr *ccp;
+ static int coexp_act; /* used to pass signal across activations */
+ /* back to whomever activates, if they care */
+
+ ccp = (struct b_coexpr *)BlkLoc(k_current);
+
+#if !COMPILER
+#ifdef EventMon
+ switch(swtch_typ) {
+ /*
+ * A_MTEvent does not generate an event.
+ */
+ case A_MTEvent:
+ break;
+ case A_Coact:
+ EVValX(ncp,E_Coact);
+ if (!is:null(curpstate->eventmask)) {
+ curpstate->parent->eventsource.dword = D_Coexpr;
+ BlkLoc(curpstate->parent->eventsource) = (union block *)ncp;
+ }
+ break;
+ case A_Coret:
+ EVValX(ncp,E_Coret);
+ if (!is:null(curpstate->eventmask)) {
+ curpstate->parent->eventsource.dword = D_Coexpr;
+ BlkLoc(curpstate->parent->eventsource) = (union block *)ncp;
+ }
+ break;
+ case A_Cofail:
+ EVValX(ncp,E_Cofail);
+ if (!is:null(curpstate->eventmask) && ncp->program == curpstate) {
+ curpstate->parent->eventsource.dword = D_Coexpr;
+ BlkLoc(curpstate->parent->eventsource) = (union block *)ncp;
+ }
+ break;
+ }
+#endif /* EventMon */
+#endif /* COMPILER */
+
+ /*
+ * Determine if we need to transmit a value.
+ */
+ if (valloc != NULL) {
+
+#if !COMPILER
+ /*
+ * Determine if we need to dereference the transmitted value.
+ */
+ if (Var(*valloc))
+ retderef(valloc, (word *)glbl_argp, sp);
+#endif /* COMPILER */
+
+ if (ncp->tvalloc != NULL)
+ *ncp->tvalloc = *valloc;
+ }
+ ncp->tvalloc = NULL;
+ ccp->tvalloc = rsltloc;
+
+ /*
+ * Save state of current co-expression.
+ */
+ ccp->es_pfp = pfp;
+ ccp->es_argp = glbl_argp;
+ ccp->es_tend = tend;
+
+#if !COMPILER
+ ccp->es_efp = efp;
+ ccp->es_gfp = gfp;
+ ccp->es_ipc = ipc;
+ ccp->es_sp = sp;
+ ccp->es_ilevel = ilevel;
+#endif /* COMPILER */
+
+#if COMPILER
+ if (line_info) {
+ ccp->file_name = file_name;
+ ccp->line_num = line_num;
+ file_name = ncp->file_name;
+ line_num = ncp->line_num;
+ }
+#endif /* COMPILER */
+
+#if COMPILER
+ if (debug_info)
+#endif /* COMPILER */
+ if (k_trace)
+#ifdef EventMon
+ if (swtch_typ != A_MTEvent)
+#endif /* EventMon */
+ cotrace(ccp, ncp, swtch_typ, valloc);
+
+ /*
+ * Establish state for new co-expression.
+ */
+ pfp = ncp->es_pfp;
+ tend = ncp->es_tend;
+
+#if !COMPILER
+ efp = ncp->es_efp;
+ gfp = ncp->es_gfp;
+ ipc = ncp->es_ipc;
+ sp = ncp->es_sp;
+ ilevel = (int)ncp->es_ilevel;
+#endif /* COMPILER */
+
+#if !COMPILER
+#ifdef MultiThread
+ /*
+ * Enter the program state of the co-expression being activated
+ */
+ ENTERPSTATE(ncp->program);
+#endif /* MultiThread */
+#endif /* COMPILER */
+
+ glbl_argp = ncp->es_argp;
+ BlkLoc(k_current) = (union block *)ncp;
+
+#if COMPILER
+ coexpr_fnc = ncp->fnc;
+#endif /* COMPILER */
+
+#ifdef EventMon
+ /*
+ * From here on out, A_MTEvent looks like a A_Coact.
+ */
+ if (swtch_typ == A_MTEvent)
+ swtch_typ = A_Coact;
+#endif /* EventMon */
+
+ coexp_act = swtch_typ;
+ coswitch(ccp->cstate, ncp->cstate,first);
+ return coexp_act;
+#endif /* Coexpr */
+ }
+
+#ifdef Coexpr
+/*
+ * new_context - determine what function to call to execute the new
+ * co-expression; this completes the context switch.
+ */
+void new_context(fsig,cargp)
+int fsig;
+dptr cargp;
+ {
+#if COMPILER
+ (*coexpr_fnc)();
+#else /* COMPILER */
+ interp(fsig, cargp);
+#endif /* COMPILER */
+ }
+#else /* Coexpr */
+/* dummy new_context if co-expressions aren't supported */
+void new_context(fsig,cargp)
+int fsig;
+dptr cargp;
+ {
+ }
+#endif /* Coexpr */