/* * 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 ←JBLEN /* needs to be big enough */ # 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. */ bool XR←StackPushTest(/* int nbytes */); /* Return TRUE if it's possible to push nbytes onto the current stack without causing a thread stack overflow. */ #endif ←P←THREADS←H