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