/*
* sThreads.c -- stubbed out PCR
*
* July 6, 1993 - mfp
* XR←PauseAbortable fixed to set the return value as specified in Threads.h
*/
#include <xr/Threads.h>
#include <xr/ThreadsDynamicEnvironment.h>
#include <xr/sMisc.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
#include <stdlib.h>
#include <errno.h>
extern char **envp;
static long bootTime;
struct XR←ThreadRep theOnlyThread;
XR←Thread XR←currThread = &theOnlyThread;
void
SPCR←Init() {
extern int SPCR←debugMessages;
(void) time(&bootTime);
if (getenv("SPCR←DEBUG")) SPCR←debugMessages = 1;
GC←register←displacement(8);
}
struct cu←info {
void (**cu←proc)();
XR←Pointer cu←data;
};
struct cu←info * cleanupInfo;
static void generic←cu←proc()
{
(**(cleanupInfo -> cu←proc))(cleanupInfo -> cu←data);
}
int
XR←RegisterTerminationCleanupProc(proc, clientData)
void (**proc)();
XR←Pointer clientData;
{
cleanupInfo = (struct cu←info *)
GC←malloc(sizeof (struct cu←info));
if (cleanupInfo == 0) {
errno = ENOMEM;
return(-1);
}
cleanupInfo -> cu←proc = proc;
cleanupInfo -> cu←data = clientData;
return(atexit(generic←cu←proc));
}
XR←Ticks
XR←TicksSinceBoot() {
return (time(0) - bootTime) * XR←TICKS←PER←SECOND;
}
#undef XR←TicksToMsec
unsigned
XR←TicksToMsec(ticks)
XR←Ticks ticks;
{
return ticks * XR←MSECS←PER←TICK;
}
#undef XR←MsecToTicks
XR←Ticks
XR←MsecToTicks(msec)
unsigned msec;
{
return msec / XR←MSECS←PER←TICK;
}
void
XR←InitializeCondition(cv, timeout)
XR←CV cv;
XR←Ticks timeout;
{
cv->cv←timeout = timeout;
SPCR←NotImplemented("InitializeCondition");
}
void
XR←InitializeMonitor(ml)
XR←ML ml;
{
ml->ml←holder = 0;
}
void
XR←MonitorEntry(ml)
XR←ML ml;
{
if (ml->ml←holder) {
SPCR←error("Deadlock!\n");
}
ml->ml←holder = XR←currThread;
}
void
XR←MonitorExit(ml)
XR←ML ml;
{
ml->ml←holder = 0;
}
void
XR←SetTimeout(cv, timeout)
XR←CV cv;
XR←Ticks timeout;
{
cv->cv←timeout = timeout;
}
void
XR←DisableTimeout(cv)
XR←CV cv;
{
cv->cv←timeout = XR←WAIT←FOREVER;
}
void
XR←DisableAborts(cv)
XR←CV cv;
{
}
void
XR←EnableAborts(cv)
XR←CV cv;
{
cv->cv←abortable = TRUE;
}
bool
XR←AbortPending ()
{
return( FALSE );
}
int
XR←WaitCV(cv, ml)
XR←CV cv;
XR←ML ml;
{
if (cv->cv←timeout != XR←WAIT←FOREVER)
sleep(XR←TicksToMsec(cv->cv←timeout)/1000);
else {
SPCR←error("Waiting forever w/o timeout in a single-process world");
}
return 0;
}
int
XR←ValidateCT(ct)
XR←CT ct;
{
return (ct->ct←thread == XR←currThread) ? 0 : -1;
}
void
XR←Notify(cv)
XR←CV cv;
{
}
void
XR←Broadcast(ct)
XR←CT ct;
{
}
void
XR←UplevelSetjmp(jb)
XR←JmpBuf jb;
{
SPCR←NotImplemented("XR←UplevelSetJmp");
}
XR←DBMsg
XR←CallDebugger(arg)
XR←Pointer arg;
{
SPCR←error("Debugger Called\n");
}
XR←Pointer
XR←ExtensionFree(x)
XR←Pointer x;
{
return NIL;
}
static current←pri = 3; /* NORMAL */
#undef XR←GetPriority
XR←Pri
XR←GetPriority() {
return(current←pri);
}
void
XR←SetPriority(pri)
XR←Pri pri;
{
current←pri = pri;
}
void
XR←Yield() {
}
void
XR←GetCurrent(result)
struct XR←CTRep *result;
{
result->ct←thread = XR←currThread;
result -> ct←gen = 1;
}
void
XR←Fork(result, mp)
struct XR←CTRep *result;
XR←MesaProc mp;
{
SPCR←NotImplemented("XR←Fork");
}
XR←Pointer
XR←JoinCT(ct)
XR←CT ct;
{
SPCR←NotImplemented("XR←JoinCT");
return -1;
}
int
XR←PauseAbortable(ticks)
XR←Ticks ticks;
{
struct timeval timeout;
unsigned long msec = XR←TicksToMsec(ticks);
timeout.tv←sec = msec/1000;
timeout.tv←usec = (msec % 1000) * 1000;
return (select(0,0,0,0, &timeout));
}
int
XR←CancelAbort(ct)
XR←CT ct;
{
return 0;
}
int
XR←DetachCT(ct)
XR←CT ct;
{
SPCR←NotImplemented("XR←DetachCT");
return 0;
}
int
XR←AbortCT(ct)
XR←CT ct;
{
SPCR←NotImplemented("XR←AbortCT");
return 0;
}
void
XR←ExitWorld(status)
int status;
{
←exit(status);
}
void
XR←RestartHandlee(t, where, result) /* !!!! no declaration in .h */
XR←Thread t;
jmp←buf where;
unsigned result;
{
if( t == NIL ) t = XR←currThread;
else if( t != XR←currThread ) {
SPCR←error("Current Thread isn't only thread!");
}
if( where == NIL ) {
SPCR←error("Handlee jumpbuf is NIL!");
}
XR←longjmp( where, result );
}
XR←Thread
XR←GetNextHandlee(t) /* !!!! no declaration in .h */
XR←Thread t;
{
if( t == NIL ) return ( XR←currThread );
SPCR←error("XR←GetNextHandlee called with thread != NIL!");
}
#undef XR←RegisterThreadStartProc
void
XR←RegisterThreadStartProc(startProc)
XR←MesaProc startProc;
{
}
/*
* Per thread data access and set routines
* Using a global variable rather than adding a field to the thread
* data structure because perThread data in a single threaded world
* might as well be perWorld data
*/
XR←Pointer t←perThreadData = 0;
XR←Pointer
XR←GetThreadProperty()
{
return t←perThreadData;
}
void
XR←SetThreadProperty(p)
XR←Pointer p;
{
t←perThreadData = p;
}