diff options
Diffstat (limited to 'src/runtime/rcoexpr.r')
-rw-r--r-- | src/runtime/rcoexpr.r | 315 |
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 */ |