/* Sun-$Revision: 23.6 $ */
/* Copyright 1992-9 Sun Microsystems, Inc. and Stanford University.
See the LICENSE file for license information. */
# pragma interface
// a portable interface to OS signals
// Self signals are passed up to self scheduler
// SelfSignal's are the ones that the Self scheduler gets to get
enum SelfSignal {
sigint,
sigquit, sigio, siguser1, siguser2, sigpipe, sigterm, sigurg,
sigchild, sighup, sigwinch, sigrealtimer,
sigcputimer, last_real_SelfSignal = sigcputimer,
sigunknown, // not really a Self signal; must be last
last_SelfSignal = sigunknown
};
// First, a simple data structure to track which self signals are pending
class PendingSelfSignals /* AllStatic */ {
public:
static const int n_SelfSignals = last_SelfSignal + 1;
static const int n_real_SelfSignals = last_real_SelfSignal + 1;
private:
static VMStringsIndex _name [n_real_SelfSignals]; // index into VMString[]
static smi _count[n_real_SelfSignals]; // number of outstanding signals
static bool _are_any_pending; // summary
static bool _know_if_any_pending; // true if field above is valid
static void check(SelfSignal s) { UsedOnlyInAssert(s); assert( 0 <= s && s <= last_real_SelfSignal, "signal out of bounds"); }
public:
static void init();
static stringOop name( SelfSignal s) { check(s); return VMString[_name[s]]; }
static smi count( SelfSignal s) { check(s); return _count[s]; }
static void reset( SelfSignal s, smi c = 0) { check(s); _count[s] = c; _know_if_any_pending = false;}
static void increment( SelfSignal s) { check(s); ++_count[s]; _know_if_any_pending = _are_any_pending = true; }
static smi Self_result_size();
static void pass_to_Self(oop resultArg);
static bool are_any_pending();
static smi keyboard_signals() { return count(sigint) + count(sigquit); }
static void reset_keyboard_signals(smi i = 0) { _count[sigint] = _count[sigquit] = i; }
};
class OSToSelfSignalMapper /* AllStatic */ {
private:
static SelfSignal _map[Last_OS_Signal];
public:
static void init();
static void init_platform();
static SelfSignal map(int32 s) {
assert( 0 <= s && s < Last_OS_Signal, "out of range");
return _map[s];
}
};
class SignalInterface /* AllStatic */ {
// State:
private:
static bool _block_self_signals; // don't deliver signals to Self
static bool _initializing; // in the midst of it
static bool _is_in_map_load;
// Public interface:
public:
// Initialization;
static void initialize( bool ctrlC = true); // called from OS::init and run_the_VM
static bool is_initializing() { return _initializing; }
// Blocking signals:
static void block_self_signals() { _block_self_signals = true; }
static void unblock_self_signals() { _block_self_signals = false; }
static bool are_self_signals_blocked() { return _block_self_signals; }
friend bool BlockSignals_prim(bool); // Self-level primitive
// Some platforms have a separate signal stack.
// is_on... returns true if such a stack exists and VM is currently running on it.
// is_off... returns true if such a stack exists and VM is currently NOT running on it.
// ( TERNARY logic; return false if not applicable )
static bool is_on_signal_stack(char* sp = NULL);
static bool is_off_signal_stack(char* sp = NULL);
// Similar to is_on... this test returns true if we are handling a signal resulting
// from a map load. (Self uses load alignment signals to trap a load of an int map.)
static bool is_in_map_load() { return _is_in_map_load; }
// Self code may ask for a signal in real or CPU time.
// The timers get their basic signals from here, then call back into here
// to pass their signals to Self:
static void Self_real_timer_tick();
static void Self_CPU_timer_tick();
// Called from Platform code with Unix-like arguments
static void handle_signal(int ossig, char* addr = 0, int32 code = 0);
// When the VM has nothing to do, wait for any signal:
// Caller checks preemptCause
static void wait_for_any(); // Wait for any signal to come in
// And some miscellany:
static void flush_input_after_ctrl_c(); // Returning to Self prompt, discard ^c's
static void simulate_fatal_signal();
// Internal methods:
private:
// Initialization (per-platform)
static void initialize_platform(bool ctrlC);
// Self uses illegal-instruction-oidal traps to optimize map loads and uplevel traps
static bool is_map_load_signal(int sig);
static bool is_uplevel_trap(int code );
// Handle a signal normally passed on to Self code:
static void handle_Self_signal( SelfSignal ssig); // Also called from itimer.c at timer interrupts
static void safely_handle_Self_signal( SelfSignal ssig ); // helper for above
// Handle an OS signal not passed on to Self code
static void handle_OS_signal(int32 ossig, char* addr = 0, int32 code = 0);
// Handle an OS signal for SIC not passed on to Self code, return true if handled
static bool handle_SIC_OS_signal(int32 ossig, char* addr, int32 code);
# include "_sig_pd.h.incl"
};