/*
* Threads.h -- stubbed out PCR version
*/
#ifndef ←P←THREADS←H
#define ←P←THREADS←H
#include "BasicTypes.h"
#include <setjmp.h>
/*
* These #defines are also in portbasics.h for C code generated by mimosa
*/
#define XR←setjmp(jb) setjmp((jb))
#define XR←longjmp(jb, rv) longjmp((jb), (rv))
#define XR←Thread struct XR←ThreadRep * /* breaks recursion in dcls */
/*
* THE thread for pPCR
*/
extern struct XR←ThreadRep theOnlyThread;
extern XR←Thread XR←currThread;
/*
* Time
*
* ... for cv timeouts, pausing, etc.
*/
typedef int XR←DBMsg;
/* bogus declaration for type of XR←CallDebugger() */
typedef unsigned XR←Ticks;
#define XR←TICKS←PER←SECOND 20
#define XR←MSECS←PER←TICK (1000/XR←TICKS←PER←SECOND)
#define XR←USECS←PER←TICK (1000000/XR←TICKS←PER←SECOND)
#define XR←WAIT←FOREVER ((XR←Ticks) 0)
#define XR←END←OF←TIME ((XR←Ticks)(0xffffffff))
#define XR←DEFAULT←TMP←DIRECTORY "/tmp/"
/* Priority */
typedef unsigned XR←Pri;
typedef struct XR←MLRep {
XR←Thread ml←holder; /* holds mon←lock */
} *XR←ML;
/*
* Condition Variables (CV's)
*/
typedef struct XR←CVRep {
/* declarations deleted for psuedo-threads work */
XR←Ticks cv←timeout; /* timeout for waiting threads */
bool cv←abortable; /* aborts enabled? */
bool cv←wakeupWaiting; /* a wakeup is waiting */
} *XR←CV;
/*
* context save/restore
*/
#if defined(sparc)
# define JMPBUFSIZE 3 /* could be 2 ... */
# define XR←PC←FROM←JMP←BUF(b) (((XR←Pointer *)(b->jb←data))[0])
# define XR←FP←FROM←JMP←BUF(b) --> not used on sparc <--
# define XR←SP←FROM←JMP←BUF(b) (((XR←Pointer *)(b->jb←data))[2])
#endif
typedef struct XR←JmpBufRep {
unsigned jb←data[JMPBUFSIZE];
} *XR←JmpBuf;
/*
* signal/error interface
*
*
* A handler proc is invoked
* - as a result of a trap (in Unix, one of a collection of signals)
* - explicitly by XR←CallHandler(...).
*
* When it is invoked:
* It starts with an empty stack.
* It can call XR←RestartHandlee(...) instead of returning.
* It can terminate the thread by calling XR←Exit.
* IF the handlee is prepared to resume, the handler can resume it
* by just returning.
*
* A handler proc is registered with each thread, and is inherited across
* XR←Fork calls.
*
* It is okay to register NIL; a NIL handler just calls the debugger.
*/
/* Args to Unix signal handler -- see <sys/signal.h> */
typedef struct XR←TrapArgsRep {
int ta←sig;
int ta←code;
struct sigcontext *ta←scp;
XR←Pointer ta←addr;
} *XR←TrapArgs;
/* type code for handler */
typedef unsigned XR←HandlerWhich;
/* 0 => not a handler call */
/* low values are reserved for machine- or OS- traps */
/* low-order bit => not resumable */
# define XR←HANDLER←WHICH←NULL 0
# define XR←HANDLER←WHICH←MK←FATAL(which) ((which) | 0x1)
# define XR←HANDLER←WHICH←IS←FATAL(which) ((which) & 0x1)
# define XR←HANDLER←WHICH←TRAP←UNIX (0x2)
# define XR←HANDLER←WHICH←TRAP←UNIX←FATAL \
XR←HANDLER←WHICH←MK←FATAL(XR←HANDLER←WHICH←TRAP←UNIX)
# define XR←HANDLER←WHICH←STACK←OVERFLOW \
XR←HANDLER←WHICH←MK←FATAL(1022)
#define XR←HANDLER←WHICH←TRAP←LIM ((XR←HandlerWhich)(1024))
/* registered handler proc */
typedef void (*XR←HandlerProc)(/*
XR←Thread handlee, -- obsolete, always XR←currThread
XR←HandlerWhich which, -- exception type code
XR←Pointer arg -- XR←TrapArgs for trap, else arbitrary
XR←Pointer clientData -- client data registered with proc
*/);
/* XR←HandlerData is private */
typedef struct XR←HandlerDataRep {
XR←HandlerProc hd←proc; /* registered handler proc */
XR←Pointer hd←clientData; /* passed to proc when invoked */
XR←HandlerWhich hd←which; /* saved XR←HandlerProc `which' argument */
XR←Pointer hd←arg; /* saved XR←HandlerProc `arg' argument */
struct XR←JmpBufRep
hd←resume; /* resume after trap or CallDebugger ... */
unsigned hd←result; /* ... by XR←longjmp(&hd←resume, hd←result) */
} * XR←HandlerData;
/* Thread Data Structure, sort of */
typedef struct XR←ThreadRep {
int t←this←is←only←a←dummy;
#undef XR←Thread
} * XR←Thread;
/*
* Checked Thread Data Structure -- includes ref and generation number
*/
typedef struct XR←CTRep {
XR←Thread ct←thread; /* -> thread */
unsigned ct←gen; /* generation number */
} *XR←CT;
/*
* function declarations
*/
extern XR←Ticks
XR←TicksSinceBoot (/* */);
/*
Return time in ticks since boot.
Wraparound is ignored.
*/
extern XR←Ticks
XR←MsecToTicks (/* msec */);
/*
unsigned msec;
Convert milliseconds to ticks.
Rounds up.
Overflow if msec > LAST(unsigned)-1000.
*/
extern unsigned
XR←TicksToMsec (/* ticks */);
/*
XR←Ticks ticks;
Convert ticks to milliseconds.
Undefined if it would overflow.
*/
extern void
XR←InitializeMonitor (/* ml */);
/*
XR←ML ml;
Initialize `ml'.
Call only once, before handing out the object.
*/
extern void
XR←MonitorEntry (/* XR←ML ml */);
extern void
XR←MonitorExit (/* XR←ML ml */);
extern void
XR←InitializeCondition (/* cv, timeout */);
/*
XR←CV cv;
XR←Ticks timeout;
Initialize `cv'.
Call only once per variable.
*/
extern void
XR←SetTimeout (/* cv, timeout */);
/*
XR←CV cv;
XR←Ticks timeout;
Set the timeout associated with `cv'.
Has no effect on currently waiting threads.
*/
extern void
XR←DisableTimeout (/* cv */);
/*
XR←CV cv;
Disable timeouts for `cv'.
Has no effect on currently waiting threads.
*/
extern void
XR←EnableAborts (/* cv */);
/*
XR←CV cv;
Enable aborts on `cv'.
No effect on threads currently waiting.
*/
extern void
XR←DisableAborts (/* cv */);
/*
XR←CV cv;
Disable aborts on `cv'.
No effect on threads currently waiting.
*/
extern int
XR←WaitCV (/* cv, ml */);
/*
XR←CV cv;
XR←ML ml;
Wait for `cv'.
Assumes `ml' is held; releases it while waiting.
If `ml' is NIL, that's okay - this is a wait on an icv.
Return 0 if okay, -1 if ABORTED.
*/
extern void
XR←Notify (/* cv */);
/*
XR←CV cv;
Notify `cv'.
*/
extern void
XR←Broadcast (/* cv */);
/*
XR←CV cv;
Broadcast `cv'.
*/
extern XR←DBMsg
XR←CallDebugger(/* XR←Pointer arg */);
/*
Equivalent to XR←CallDebugger2(arg, XR←DB←MSG←CLIENT←REQUEST).
*/
extern XR←Pointer
XR←ExtensionFree (/* x */);
/*
XR←Pointer x;
Assuming x is the address of a frame extension allocated with
XR←ExtensionAlloc, free it and return NIL.
*/
extern XR←Pri
XR←GetPriority ();
/*
Return priority of current thread.
*/
extern void
XR←SetPriority (/* pri */);
/*
XR←Pri pri;
Set priority of current thread.
*/
extern void
XR←Yield (/* */);
/*
Yield processor.
*/
extern void
XR←GetCurrent (/* result */);
/*
struct XR←CTRep *result;
Return the current thread in *result.
*/
extern void
XR←Fork (/*
struct XR←CTRep *result,
XR←MesaProc mp
*/);
extern XR←Pointer
XR←JoinCT (/* ct */);
/*
XR←CT ct;
JOIN with `ct' returning (pointer to) its results.
The caller is presumed to know how many results to expect.
If cp is an invalid thread, return ((XR←Pointer)(-1)), which is
guaranteed not to be a valid pointer.
*/
extern int
XR←PauseAbortable (/* ticks */);
/*
XR←Ticks ticks;
Pause the specified number of ticks, with aborts enabled.
Ticks may be XR←WAIT←FOREVER.
Return 0 ordinarily, or -1 if aborted.
*/
extern bool
XR←AbortPending ();
/*
Check whether an abort has been requested.
This does not clear the p←abortRequest flag.
*/
extern int
XR←CancelAbort (/* ct */);
/*
XR←CT ct;
Cancel any abort request for `ct' (i.e. clear the t←abortRequest flag).
If `ct' == NIL it means the current thread.
Return 0 if okay, or -1 if `ct' is invalid.
*/
extern int
XR←DetachCT (/* ct */);
/*
XR←CT ct;
Detach `ct'.
Return 0 if okay, or -1 if `ct' is invalid.
*/
extern int
XR←AbortCT (/* ct */);
/*
XR←CT ct;
Abort `ct'.
Return 0 if okay, or -1 if `ct' is invalid.
*/
extern int
XR←ValidateCT (/* ct */);
/*
XR←CT ct;
Return 0 if okay, -1 if `ct' is invalid.
*/
/*
* Terminate the world ...
*/
extern void
XR←ExitWorld (/* int status */);
/*
Terminate PCR; in Unix(tm) this looks like
←exit(status);
to the invoker of PCR.
Tries to free all allocated resources
(e.g. system semaphores, swap file, ...).
*/
extern void
XR←RestartHandlee(/* XR←Thread t, XR←JmpBuf where, unsigned result */);
extern XR←Thread
XR←GetNextHandlee(/* XR←Thread t */);
extern void
XR←RegisterThreadStartProc (/* startProc */);
/*
XR←MesaProc startProc;
Register startProc as the "start proc" for this thread and its
descendants.
Ordinarily, the effect of
XR←Fork(result, forkProc);
is
result = (*forkProc->mp←proc)(forkProc);
After RegisterThreadStartProc(startProc) the effect will be
result = (*startProc->mp←proc)(forkProc, startProc);
allowing the startProc to catch uncaught signals, etc.
It is okay to register NIL.
*/
#endif ←P←THREADS←H