/* Copyright (c) 1993 Xerox Corporation. All rights reserved. */ /* $Id$ $Date$ * * Basic public type definitions for PCR threads * */ #ifndef ←←PCR←Th←h #define ←←PCR←Th←h 1 #include <config/PCR←Arch.h> #include <config/PCR←StdDefs.h> #include <sig/PCR←Sig.h> #include <th/PCR←ThTypes.h> /* * Monitor Locks * * MLs are opaque but clients may allocate and initialize them. */ extern struct PCR←Th←MLRep const PCR←Th←ML←readonlyNull; extern void PCR←Th←ML←Init(PCR←Th←ML *ml); /* * Condition variables * * CVs are opaque but clients may allocate and initialize them. */ extern struct PCR←Th←CVRep const PCR←Th←CV←readonlyNull; extern void PCR←Th←CV←Init(PCR←Th←CV *cv); /* * Priority * * Client priorities must lie between userBackground and userForeground. */ extern const PCR←Th←Pri PCR←Th←Pri←readonlyUserBackground; extern const PCR←Th←Pri PCR←Th←Pri←readonlyUserNormal; extern const PCR←Th←Pri PCR←Th←Pri←readonlyUserForeground; extern const PCR←Th←Pri PCR←Th←Pri←readonlyStopped; extern const PCR←Th←Pri PCR←Th←Pri←readonlyIdle; /* * * Control of waiting primitives * */ /* timeout */ extern PCR←Msec PCR←Th←WakeMsec(PCR←Msec interval); /* Compute wakeup time (msec since boot or PCR←Msec←waitForever) from interval (or PCR←Msec←waitForever) */ extern PCR←Msec PCR←Th←MsecSinceBoot(void); /* Equivalent to PCR←Th←WakeMsec(0) */ extern PCR←Msec volatile PCR←SigGlue←msecSinceBoot; #define PCR←Th←←MsecSinceBoot() PCR←SigGlue←msecSinceBoot #define PCR←Th←MsecSinceBoot PCR←Th←←MsecSinceBoot /* sig mask */ # define PCR←allSigsBlocked (&PCR←sigset←t←readonlyFull) # define PCR←noSigsBlocked (&PCR←sigset←t←readonlyEmpty) # define PCR←sigsBlockedUnchanged NIL /********************************************************* Public Procedures /*********************************************************/ /* * Monitor entry/exit */ extern PCR←ERes PCR←Th←ML←TestAndLock( PCR←Th←ML *ml, const PCR←sigset←t *sigMask, PCR←Msec wakeup ); /* Acquire lock. The existence of a pending signal (or arrival of a signal) not blocked by sigMask results in failure (EINTR). Success: (lock has been acquired, sigmask unchanged) PCR←ERes←okay Failure: (lock has not been acquired, sigmask unchanged) PCR←ETIMEDOUT EINTR NOTE: this differs from the Cedar semantics. It is something of an experiment, but since we'll need to wrap this procedure for Cedar anyway ... */ extern void PCR←Th←ML←Acquire(PCR←Th←ML *ml); /* Equivalent to (but faster than) (void)PCR←Th←ML←TestAndLock( ml, PCR←allSigsBlocked, PCR←waitForever ) */ extern PCR←ERes PCR←Th←ML←Try(PCR←Th←ML *ml); /* Equivalent to (but faster than) (void)PCR←Th←ML←TestAndLock( ml, PCR←sigsBlockedUnchanged, PCR←dontWait ) */ extern void PCR←Th←ML←Release(PCR←Th←ML *ml); /* Release lock. */ /* * Condition wait/notify */ extern PCR←ERes PCR←Th←CV←Wait( PCR←Th←CV *cv, PCR←Th←ML *ml, const PCR←sigset←t *sigMask, PCR←Msec wakeup ); /* Atomically release *ml (if not NIL) and - if cv has been sticky-notified, return PCR←ERes←okay immediately - otherwise wait for the cv to be notified. This is not an interruption point, but the existence of a pending signal (or arrival of a signal) not blocked by sigMask results in failure (EINTR). Success: PCR←ERes←okay Failure: PCR←ETIMEDOUT EINTR NOTE: this differs from the Cedar semantics, particularly in not ever re-acquiring the ml. It is something of an experiment, but since we'll need to wrap this procedure for Cedar anyway ... */ extern void PCR←Th←CV←Notify( PCR←Th←CV *cv ); /* Notify cv. */ extern void PCR←Th←CV←StickyNotify( PCR←Th←CV *cv ); /* Do "sticky" notify of cv -- one notification will be remembered if it occurs before the corresponding wait. This behavior is analogous to a binary semaphore. */ extern void PCR←Th←CV←Reset( PCR←Th←CV *cv ); /* Discard any remembered sticky notify on cv. It is okay to do this even if there are threads waiting on the condition. */ extern void PCR←Th←CV←Broadcast( PCR←Th←CV *cv ); /* Broadcast cv -- notify every thread currently waiting on it. */ /* * Thread manipulation */ extern PCR←Th←T * (PCR←Th←CurrThread(void)); /* Return the current thread. */ extern PCR←Th←T * (PCR←Th←Fork ( PCR←ProcPtr proc, PCR←Any data )); /* Fork a thread running (*proc)(data). Return PCR←Th←T for child thread. If insufficient resources are available return NIL. */ extern PCR←ERes PCR←Th←T←Join( PCR←Th←T *t, int *codep, PCR←Any *valp, const PCR←sigset←t *sigMask, PCR←Msec wakeup ); /* JOIN with `t'. If codep != NIL, store exit code of t there. If valp != NIL, store exit val of t there. (See PCR←Exit below). A pending signal (or arrival of a signal) not blocked by sigMask results in failure (EINTR). Success: PCR←ERes←okay Failure: EFAULT or EINVAL -- t not a valid thread pointer; PCR←ETIMEDOUT EINTR NOTE: there may be multiple joiners with a thread. */ extern PCR←ERes PCR←Th←Pause( const PCR←sigset←t *sigMask, PCR←Msec wakeup ); /* Pause until the specified wakeup time, or until a signal is delivered. This is not an interruption point, but the existence of a pending signal (or arrival of a signal) not blocked by sigMask results in failure (EINTR). Result is always "failure": PCR←ETIMEDOUT if timeout reached, EINTR signal pending/arrived. */ extern void PCR←Th←Exit(int code, PCR←Any val); /* Terminate current thread, passing code and val to any joiners (see PCR←Th←T←Join above). This unwinds the stack -- see PCR←ThUWProt.h */ extern PCR←ERes PCR←Th←SetPri( const PCR←Th←Pri *pri, PCR←Th←Pri *old ); /* Get/set scheduling priority. Success: (if pri != NIL priority of current thread changed to *pri) (if old != NIL old priority stored in *old) 0 NOTE: pri and old may be equal pointers -- *pri is retrieved before *old is stored. */ extern void PCR←Th←T←YieldTo ( PCR←Th←T *t ); /* Yield processor to `t' (t invalid or NIL => let scheduler decide). */ /* * Signal handling */ extern PCR←ERes PCR←Th←SetSigMask( const PCR←sigset←t *mask, PCR←sigset←t *old ); /* If old != NIL, return current sigmask in *old. If mask != NIL, update sigmask from it. Success: PCR←ERes←okay Failure: EFAULT if mask or old not valid */ extern PCR←ERes PCR←Th←SetSigAction( int sig, const PCR←Sig←Action *act, PCR←Sig←Action *old ); /* If act != NIL, set signal action for specified signal in current thread. If old != NIL, store previous action there. Success: PCR←ERes←okay Failure: EINVAL -- bad signal number EFAULT -- bad act pointer */ extern PCR←ERes PCR←Th←SetSigActions( const PCR←sigset←t * sigsp, const PCR←Sig←Action *act ); /* Equivalent to an atomic loop of SetSigAction calls for each member of *sigsp. */ extern PCR←ERes PCR←Th←T←SendSigs ( PCR←Th←T *t, const PCR←sigset←t *sigs ); /* Send specified signals to t. Success: 0 Failure: EFAULT or EINVAL if t not a valid thread pointer; ESRCH if t already finished. */ extern PCR←ERes PCR←Th←T←SigsPending ( PCR←Th←T *t, PCR←sigset←t /* result */ * pending ); /* Determine the set of signals pending for t. Success: PCR←ERes←okay. Failure: EFAULT or EINVAL if t not a valid thread pointer; EINVAL if signo not valid; ESRCH if t already finished. */ extern PCR←ERes PCR←Th←T←CancelSigs ( PCR←Th←T *t, const PCR←sigset←t *sigs ); /* Cancel any of the specified signal requests for t. Success: PCR←ERes←okay Failure: EFAULT or EINVAL if t not a valid thread pointer; ESRCH if t already finished. */ /* stack size queries */ extern unsigned long PCR←Th←GuessFrameBytes(void *p); /* If p is address of first variable in caller's frame, return approximate size in bytes of caller's frame. If p is NIL, return approximate size in bytes of min-size frame. */ extern unsigned long PCR←Th←GuessRemainingStackBytes(PCR←Th←T *t); /* Guess approximate number of stack bytes remaining available to thread t (NIL => current thread). */ extern PCR←Bool PCR←Th←EnoughStackBytes(unsigned long size); /* Return PCR←Bool←true if at least size stack bytes are available to the current thread. This is the fastest way to do such a check for the current thread. */ #endif /* ! ←←PCR←Th←h */ /* $Log$ */