/*
 * 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