/* begincopyright
  Copyright (c) 1988 Xerox Corporation. All rights reserved.
  Use and copying of this software and preparation of derivative works based
  upon this software are permitted. Any distribution of this software or
  derivative works must comply with all applicable United States export
  control laws. This software is made available AS IS, and Xerox Corporation
  makes no warranty about the software, its performance or its conformity to
  any specification. Any person obtaining a copy of this software is requested
  to send their name and post office or electronic mail address to:
    PCR Coordinator
    Xerox PARC
    3333 Coyote Hill Rd.
    Palo Alto, CA 94304
  endcopyright */

/*
 * ThreadsSignalsPrivate.h
 *
 * Demers, February 26, 1990 4:58:54 pm PST
 * Boehm, October 29, 1992 2:17:14 pm PST
 *
 * Unix signal definitions for VPs and IOPs
 */


#ifndef	←XR←THREADS←SIGNALS←PRIVATE←
#define ←XR←THREADS←SIGNALS←PRIVATE← 1

#ifndef NSIG
# include <sys/signal.h>
#endif

/*
 * For each interrupt (Unix signal) we provide:
 *
 *   A Unix signum to send to generate the interrupt:
 *
 *     XR←SIG←XXX
 *
 *   A list of Unix signals to be interpreted as this interrupt when received:
 *
 *     XR←XXX←SIGS
 *
 *   Indication whether this interrupt is disabled by other handlers:
 *
 *     XR←XXX←HELD
 *
 *   Indication that this interrupt is handled on separate stack in the VP's:
 *
 *     XR←XXX←ONSTACK
 *
 *   Interrupt handler procedure:
 *
 *     extern int XR←XxxSigHandler();
 *
 *   Initialization proc for handler:
 *
 *     extern void XR←XxxSigHandlerInit( installed );
 *     bool installed;
 *
 *     This is called twice - 
 *       before installation of the sigHandler (with installed == FALSE)
 *       after installation of the sigHandler (with installed == TRUE)
 */

extern void XR←NullSigHandlerInit(/* installed */);	/* does nothing */



/*
 * Resched
 *
 * The general paradigm is to store some state and then wake up
 *   a processor by sending it a resched signal, at which point
 *   it notices the stored state and acts on it.
 * Held by other sigHandlers.
 *
 * IOP:
 *   Runs on ordinary stack -- but it's the Unix stack, which
 *     is grown automatically, so no stack overflow worries.
 *   This is how orders are passed to the IOP.
 *
 * VP:
 *   Runs on ordinary (process) stack, so it must be careful about
 *     stack overflow.
 *   Often results in a thread switch.
 */

#define XR←SIG←RESCHED		SIGUSR1
#define XR←RESCHED←SIGS		{ SIGUSR1, 0 }
#define XR←RESCHED←HELD		TRUE
#define XR←RESCHED←ONSTACK	FALSE

extern void XR←ReschedSigHandler();
#define XR←ReschedSigHandlerInit	XR←NullSigHandlerInit

/*
 * Memerr
 *
 * Stack overflow, segmentation violation, etc.
 * Not held by other sigHandlers.
 *
 * IOP:
 *   Panic
 *
 * VP:
 *   Runs on sigHandler stack.
 */

#define XR←SIG←MEMERR		SIGBUS
#define XR←MEMERR←SIGS		{ SIGBUS, SIGSEGV, 0 }		
#define XR←MEMERR←HELD		FALSE
#define XR←MEMERR←ONSTACK	TRUE

extern void XR←MemerrSigHandler();
#define XR←MemerrSigHandlerInit	XR←NullSigHandlerInit

/*
 * Traps
 *
 * Floating point exceptions, etc.
 * Not held by other sigHandlers.
 *
 * IOP:
 *   Panic
 *
 * VP:
 *   Runs on ordinary (thread) stack.
 *   The sigHandler typically never returns; it just translates the trap
 *     to a Mesa ERROR.  This may eventually cause stack overflow, which
 *     get caught in the normal way ... BUT it CAN return, thus must
 *     run on ordinary stack.
 *   If it occurs inside another sigHandler, it should Panic
 */

#define XR←SIG←TRAP		SIGFPE
#define XR←TRAP←SIGS		{ SIGTRAP, SIGIOT, SIGEMT, SIGFPE, 0 }
#define XR←TRAP←HELD		FALSE
#define XR←TRAP←ONSTACK		FALSE 

extern void XR←TrapSigHandler();
#define XR←TrapSigHandlerInit	XR←NullSigHandlerInit


/*
 * Illegal ops
 *
 * Illegal stack, illegal instruction, privileged instruction, illegal trap
 * Not held by other sigHandlers.
 *
 * IOP:
 *   Panic
 *
 * VP:
 *   Runs on handler stack.
 *   If it occurs inside another sigHandler, it should Panic
 */

#define XR←SIG←ILL		SIGILL
#define XR←ILL←SIGS		{ SIGILL, 0 }
#define XR←ILL←HELD		FALSE
#define XR←ILL←ONSTACK		TRUE 

extern void XR←IllSigHandler();
#define XR←IllSigHandlerInit	XR←NullSigHandlerInit


/*
 * termination / exit -- used to shut down the XR world
 */

#define XR←SIG←EXIT		SIGTERM
#define XR←EXIT←SIGS		{ SIGTERM, 0 }
#define XR←EXIT←HELD		TRUE
#define XR←EXIT←ONSTACK		FALSE 

extern void XR←ExitSigHandler();
#define XR←ExitSigHandlerInit	XR←NullSigHandlerInit


/*
 * Child termination -- used by UIO IOP for Spawn
 */

#define XR←SIG←CHILD		SIGCHLD
#define XR←CHILD←SIGS		{ SIGCHLD, 0 }
#define XR←CHILD←HELD		TRUE
#define XR←CHILD←ONSTACK	FALSE 

extern void XR←ChildSigHandler();
#define XR←ChildSigHandlerInit	XR←NullSigHandlerInit


/*
 * Urgent data -- used by UIO IOP for network streams
 */

#define XR←SIG←URGENT←DATA	SIGURG
#define XR←URGENT←DATA←SIGS	{ SIGURG, 0 }
#define XR←URGENT←DATA←HELD	TRUE
#define XR←URGENT←DATA←ONSTACK	FALSE 

extern void XR←UrgentDataSigHandler();
#define XR←UrgentDataSigHandlerInit	XR←NullSigHandlerInit


/*
 * Alarm
 *
 * "Hardware" clock.
 *
 * Runs on handler stack.
 * If the timeout queue is nonempty, set sa←doTimeouts and request
 *   resched for lowest priority processor.
 */

#define XR←SIG←ALARM		SIGALRM
#define XR←ALARM←SIGS		{ SIGALRM, 0 }
#define XR←ALARM←HELD		TRUE
#define XR←ALARM←ONSTACK	TRUE

extern void XR←AlarmSigHandler();
extern void XR←AlarmSigHandlerInit(/* installed */);


/*
 * Interrupts for DebugTool
 *
 * The INTR signal is just passed to ThreadsDebugTool.
 * The TTIN signal tells the stdio module that the tty got preempted by
 *   ThreadsDebugTool.
 */

#define XR←SIG←INTR		SIGINT
#define XR←INTR←SIGS		{ SIGINT, SIGQUIT, 0 }
#define XR←INTR←HELD		TRUE
#define XR←INTR←ONSTACK		TRUE

extern void XR←IntrSigHandler();
#define XR←IntrSigHandlerInit	XR←NullSigHandlerInit


#define XR←SIG←TTIN		SIGTTIN
#define XR←TTIN←SIGS		{ SIGTTIN, 0 }
#define XR←TTIN←HELD		TRUE
#define XR←TTIN←ONSTACK		TRUE

extern void XR←TtinSigHandler();
#define XR←TtinSigHandlerInit	XR←NullSigHandlerInit


/*
 * Interrupts that should get default handlers
 */

#define XR←DEFAULTED←SIGS	{ SIGTSTP, SIGCONT, 0 }

/*
 * Size of per process signal stack
 */

#define XR←SIG←STACK←SIZE	(8*1024)
#define XR←SIG←STACK←ALIGNMENT	8

/*
 * Utilities
 */

extern void
XR←InstallSigHandlers ();
/*
    Install handlers for all interrupts.
    Called after differentiating between vps and iops.
    It's the responsibility of each handler to do the right thing
      as a function of what kind of processor it's running on.
*/

extern void
XR←SigStack(/* onStack */);
/*
    bool onStack;

    Assert we're running on handler stack (onStack == TRUE) or not.
*/


typedef unsigned XR←SignalState;

extern XR←SignalState
XR←DisableSignals ();
/*
    Mask signals for critical section.  Return previous signal state.
*/

extern XR←SignalState
XR←EnableSignals ();
/*
    Enable signals.  Return previous signal state.
*/

extern XR←SignalState
XR←SetSignalState (/*
    XR←SignalState state
*/);
/*
    Set specified signal state.  Return previous signal state.
*/

extern void
XR←WaitForSignal ();
/*
    Atomically enable all signals and wait for one. 
*/


/*
 * t←Errno locking
 *
 * Used in handlers (so per-thread errno value isn't trashed
 *   by asynchronous signals)
 */

#define XR←LockErrno() XR←currThread->t←errnoLock += 1

#define XR←UnlockErrno() XR←currThread->t←errnoLock -= 1


#endif ←XR←THREADS←SIGNALS←PRIVATE←