/*
* 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);
}
}
}