/* 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 #include #include #include /* * 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$ */