/* Max number of callers for context in a suppression. */
#define VG_N_SUPP_CALLERS 4
-/* Valgrind's signal stack size, in words */
-#define VG_SIGSTACK_SIZE_W 10000
-
/* Useful macros */
/* a - alignment - must be a power of 2 */
#define ROUNDDN(p, a) ((Addr)(p) & ~((a)-1))
/* The scheduler. */
-extern VgSchedReturnCode VG_(scheduler) ( Int* exit_code );
+extern VgSchedReturnCode VG_(scheduler) ( Int* exit_code,
+ ThreadId* last_run_thread );
extern void VG_(scheduler_init) ( void );
extern void VG_(synth_fault_mapping)(ThreadId tid, Addr addr);
extern void VG_(synth_fault_perms) (ThreadId tid, Addr addr);
+extern void VG_(get_sigstack_bounds)( Addr* low, Addr* high );
/* ---------------------------------------------------------------------
Exports of vg_mylibc.c
extern void VG_(unimplemented) ( Char* msg )
__attribute__((__noreturn__));
-/* Similarly, we have to ask for signals to be delivered on an alternative
- stack, since it is possible, although unlikely, that we'll have to run
- client code from inside the Valgrind-installed signal handler. If this
- happens it will be done by vg_deliver_signal_immediately(). */
-extern UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
-
/* Valgrind's argc and argv */
extern Int VG_(vg_argc);
extern Char **VG_(vg_argv);
/* Counts downwards in vg_run_innerloop. */
extern UInt VG_(dispatch_ctr);
-/* This is the ThreadId of the last thread the scheduler ran. */
-extern ThreadId VG_(last_run_tid);
-
/* If we're doing the default action of a fatal signal */
extern jmp_buf* VG_(fatal_signal_jmpbuf_ptr);
extern Int VG_(fatal_sigNo); /* the fatal signal */
/* ---------------------------------------------------------------------
Running stuff
------------------------------------------------------------------ */
-/* Our signal delivery stack. */
-UInt VG_(sigstack)[VG_SIGSTACK_SIZE_W];
/* jmp_buf for fatal signals; VG_(fatal_signal_jmpbuf_ptr) is NULL until
the time is right that it can be used. */
/* 64-bit counter for the number of basic blocks done. */
ULong VG_(bbs_done);
-/* This is the ThreadId of the last thread the scheduler ran. */
-ThreadId VG_(last_run_tid) = 0;
-
/* Tell the logging mechanism whether we are logging to a file
descriptor or a socket descriptor. */
Bool VG_(logging_to_filedes) = True;
Int exitcode = 0;
vki_rlimit zero = { 0, 0 };
Int padfile;
+ ThreadId last_run_tid = 0; // Last thread the scheduler ran.
+
//============================================================
// Nb: startup is complex. Prerequisites are shown at every step.
VG_(fatal_signal_jmpbuf_ptr) = &fatal_signal_jmpbuf;
if (__builtin_setjmp(VG_(fatal_signal_jmpbuf_ptr)) == 0) {
- src = VG_(scheduler)( &exitcode );
+ src = VG_(scheduler)( &exitcode, &last_run_tid );
} else {
src = VgSrc_FatalSig;
}
/* We're exiting, so nuke all the threads and clean up the proxy LWPs */
vg_assert(src == VgSrc_FatalSig ||
- VG_(threads)[VG_(last_run_tid)].status == VgTs_Runnable ||
- VG_(threads)[VG_(last_run_tid)].status == VgTs_WaitJoiner);
+ VG_(threads)[last_run_tid].status == VgTs_Runnable ||
+ VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
//--------------------------------------------------------------
//--------------------------------------------------------------
switch (src) {
case VgSrc_ExitSyscall: /* the normal way out */
- vg_assert(VG_(last_run_tid) > 0 && VG_(last_run_tid) < VG_N_THREADS);
+ vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
VG_(proxy_shutdown)();
/* The thread's %EBX at the time it did __NR_exit() will hold
{
ExeContext *ec;
Addr esp, ebp;
- Addr stacktop;
+ Addr stacktop, sigstack_low, sigstack_high;
asm("movl %%ebp, %0; movl %%esp, %1" : "=r" (ebp), "=r" (esp));
stacktop = VG_(valgrind_end);
- if (esp >= (Addr)&VG_(sigstack)[0] &&
- esp < (Addr)&VG_(sigstack)[VG_SIGSTACK_SIZE_W])
- stacktop = (Addr)&VG_(sigstack)[VG_SIGSTACK_SIZE_W];
+ VG_(get_sigstack_bounds)( &sigstack_low, &sigstack_high );
+ if (esp >= sigstack_low && esp < sigstack_high)
+ stacktop = sigstack_high;
ec = VG_(get_ExeContext2)(ret, ebp, esp, stacktop);
* One thread asks to shutdown Valgrind
* The specified number of basic blocks has gone by.
*/
-VgSchedReturnCode VG_(scheduler) ( Int* exitcode )
+VgSchedReturnCode VG_(scheduler) ( Int* exitcode, ThreadId* last_run_tid )
{
ThreadId tid, tid_next;
UInt trc;
/* Start with the root thread. tid in general indicates the
currently runnable/just-finished-running thread. */
- VG_(last_run_tid) = tid = 1;
+ *last_run_tid = tid = 1;
/* This is the top level scheduler loop. It falls into three
phases. */
/* Actually run thread tid. */
while (True) {
- VG_(last_run_tid) = tid;
+ *last_run_tid = tid;
/* For stats purposes only. */
n_scheduling_events_MINOR++;
#define DEBUG_SIGNALS
-/*
- - The following causes an infinite loop: start Hugs, Feb 2001
- version, and do Control-C at the prompt. There is an infinite
- series of sigints delivered (to the client); but also seemingly
- to valgrind, which is very strange. I don't know why.
-
- [I haven't re-tested this, but this is likely fixed - JSGF]
-*/
-
-
/* ---------------------------------------------------------------------
Forwards decls.
------------------------------------------------------------------ */
static Bool is_correct_sigmask(void);
static const Char *signame(Int sigNo);
+/* ---------------------------------------------------------------------
+ Signal stack
+ ------------------------------------------------------------------ */
+
+/* Valgrind's signal stack size, in words */
+#define VG_SIGSTACK_SIZE_W 10000
+
+/* We have to ask for signals to be delivered on an alternative
+ stack, since it is possible, although unlikely, that we'll have to run
+ client code from inside the Valgrind-installed signal handler. */
+static Addr sigstack[VG_SIGSTACK_SIZE_W];
+
+extern void VG_(get_sigstack_bounds)( Addr* low, Addr* high )
+{
+ *low = (Addr) & sigstack[0];
+ *high = (Addr) & sigstack[VG_SIGSTACK_SIZE_W];
+}
+
/* ---------------------------------------------------------------------
HIGH LEVEL STUFF TO DO WITH SIGNALS: POLICY (MOSTLY)
------------------------------------------------------------------ */
/* Sanity check. Ensure we're really running on the signal stack
we asked for. */
if (!(
- ((Char*)(&(VG_(sigstack)[0])) <= (Char*)(&dummy_local))
+ ((Char*)(&(sigstack[0])) <= (Char*)(&dummy_local))
&&
- ((Char*)(&dummy_local) < (Char*)(&(VG_(sigstack)[VG_SIGSTACK_SIZE_W])))
+ ((Char*)(&dummy_local) < (Char*)(&(sigstack[VG_SIGSTACK_SIZE_W])))
)
) {
VG_(message)(Vg_DebugMsg,
"rebuild your prog without -p/-pg");
}
- vg_assert((Char*)(&(VG_(sigstack)[0])) <= (Char*)(&dummy_local));
- vg_assert((Char*)(&dummy_local) < (Char*)(&(VG_(sigstack)[VG_SIGSTACK_SIZE_W])));
+ vg_assert((Char*)(&(sigstack[0])) <= (Char*)(&dummy_local));
+ vg_assert((Char*)(&dummy_local) < (Char*)(&(sigstack[VG_SIGSTACK_SIZE_W])));
/* Special fault-handling case. We can now get signals which can
act upon and immediately restart the faulting instruction.
VG_(proxy_setsigmask)(1);
/* Register an alternative stack for our own signal handler to run on. */
- altstack_info.ss_sp = &(VG_(sigstack)[0]);
+ altstack_info.ss_sp = &(sigstack[0]);
altstack_info.ss_size = VG_SIGSTACK_SIZE_W * sizeof(UInt);
altstack_info.ss_flags = 0;
ret = VG_(ksigaltstack)(&altstack_info, NULL);