/* * sThreadsDynamicEnvironment.c -- stubbed out PCR, based on * Mike Agostino's pseudoPCR */ #include <xr/ThreadsDynamicEnvironment.h> #include <xr/sMisc.h> XR←DynFrame SPCR←dynEnv = 0; static int XR←unwindFrameKeyValueIsMyAddress; XR←Pointer XR←UnwindFrameKey = (XR←Pointer) (&XR←unwindFrameKeyValueIsMyAddress); XR←DynFrame XR←GetDynamicEnvironment() { return (SPCR←dynEnv); } XR←DynFrame XR←GetDynamicEnvironmentOf(thread) XR←Thread thread; { if (thread != XR←currThread) { SPCR←error("XR←GetDynamicEnvironmentOf(bad thread)"); } return (SPCR←dynEnv); } void XR←SetDynamicEnvironment(f) XR←DynFrame f; { SPCR←dynEnv = f; } XR←DynFrame XR←LookupInDynamicEnvironment(key, de) XR←Pointer key; XR←DynFrame de; { XR←DynFrame f; for (f = de; f != NIL; f = f->df←link) { if (((unsigned) f) & 0x3) { SPCR←error("link on dynamic chain was not 4-byte aligned ptr"); } if (f->df←key == key) return f; } return NIL; } static unsigned EnvironmentLength(de) XR←DynFrame de; { unsigned len = 0; while (de != NIL) { len++; de = de->df←link; } return len; } XR←DynFrame XR←FirstCommonParent(de1, de2) XR←DynFrame de1, de2; { unsigned len1 = EnvironmentLength(de1); unsigned len2 = EnvironmentLength(de2); while (len1 > len2) { de1 = de1->df←link; len1--; }; while (len2 > len1) { de2 = de2->df←link; len2--; }; /* de1 and de2 are now the same length */ while (de1 != de2) { de1 = de1->df←link; de2 = de2->df←link; }; return de1; } int XR←UnwindTo(target) XR←DynFrame target; { XR←Pointer myKey = XR←UnwindFrameKey; XR←DynFrame de = XR←GetDynamicEnvironment(); XR←DynFrame f; for (f = de; (f != NIL) && (f != target); f = f->df←link) ; if (f == NIL) return -1; for (f = de; f != target; f = f->df←link) { if (f->df←key == myKey) { XR←UnwindFrame uf = (XR←UnwindFrame) f; XR←MesaProc unwinder = uf->uf←unwinder; if (unwinder != NIL) { XR←SetDynamicEnvironment(uf->uf←link); (*(unwinder->mp←proc))(unwinder); } } } XR←SetDynamicEnvironment(target); return 0; } int XR←RewindTo(target) XR←DynFrame target; { extern void DoRewind(/* end, f, key */); XR←DynFrame de = XR←GetDynamicEnvironment(); XR←DynFrame f; for (f = target; (f != NIL) && (f != de); f = f->df←link) ; if (f == NIL) return -1; DoRewind(de, target, XR←UnwindFrameKey); XR←SetDynamicEnvironment(target); return 0; } #define REWIND←BATCH 32 static void DoRewind(end, f, key) /* call all rewinders in (end..f] in that order */ XR←DynFrame end, f; XR←Pointer key; { XR←DynFrame stack[REWIND←BATCH]; int i = 0; for(;;) { if( f == NIL ) XR←Panic("DoRewind 0"); if( f == end ) break; if( f->df←key == key ) { if( i == REWIND←BATCH ) { DoRewind(end, f, key); break; } else { stack[i] = f; i++; } } f = f->df←link; } while( i > 0 ) { XR←UnwindFrame uf; XR←MesaProc rewinder; i -= 1; uf = (XR←UnwindFrame)(stack[i]); if( (rewinder = uf->uf←rewinder) != NIL ) { XR←SetDynamicEnvironment(uf->uf←link); (*(rewinder->mp←proc))(rewinder); } } }