1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Thread scheduling. scheduler.c ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Valgrind, a dynamic binary instrumentation 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown framework. 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Copyright (C) 2000-2011 Julian Seward 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jseward@acm.org 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Overview 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Valgrind tries to emulate the kernel's threading as closely as 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown possible. The client does all threading via the normal syscalls 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (on Linux: clone, etc). Valgrind emulates this by creating exactly 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the same process structure as would be created without Valgrind. 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown There are no extra threads. 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The main difference is that Valgrind only allows one client thread 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to run at once. This is controlled with the CPU Big Lock, 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "the_BigLock". Any time a thread wants to run client code or 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown manipulate any shared state (which is anything other than its own 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState entry), it must hold the_BigLock. 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown When a thread is about to block in a blocking syscall, it releases 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the_BigLock, and re-takes it when it becomes runnable again (either 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown because the syscall finished, or we took a signal). 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(scheduler) therefore runs in each thread. It returns only when 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the thread is exiting, either because it exited itself, or it was 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown told to exit by another thread. 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is almost entirely OS-independent. The details of how 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the OS handles threading and signalling are abstracted away and 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown implemented elsewhere. [Some of the functions have worked their 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown way back for the moment, until we do an OS port in earnest...] 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h" 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuglog.h" 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h" 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vkiscnums.h" // __NR_sched_yield 64b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_threadstate.h" 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h" 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_clreq.h" // for VG_USERREQ__* 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_dispatch.h" 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_errormgr.h" // For VG_(get_n_errs_found)() 70b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_gdbserver.h" // for VG_(gdbserver) and VG_(gdbserver_activity) 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h" 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h" 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h" 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcproc.h" 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcsignal.h" 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_darwin) 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mach.h" 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_machine.h" 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mallocfree.h" 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h" 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_replacemalloc.h" 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_signals.h" 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_stacks.h" 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_stacktrace.h" // For VG_(get_and_pp_StackTrace)() 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syscall.h" 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syswrap.h" 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h" 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_translate.h" // For VG_(translate)() 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_transtab.h" 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuginfo.h" // VG_(di_notify_pdb_debuginfo) 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_sema.h" 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_scheduler.h" // self 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_redir.h" 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Types and globals for the scheduler. 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ThreadId and ThreadState are defined elsewhere*/ 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Defines the thread-scheduling timeslice, in terms of the number of 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown basic blocks we attempt to run each thread for. Smaller values 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown give finer interleaving but much increased scheduling overheads. */ 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SCHEDULING_QUANTUM 100000 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* If False, a fault is Valgrind-internal (ie, a bug) */ 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(in_generated_code) = False; 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Counts downwards in VG_(run_innerloop). */ 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt VG_(dispatch_ctr); 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 64-bit counter for the number of basic blocks done. */ 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong bbs_done = 0; 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Counter to see if vgdb activity is to be verified. 118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov When nr of bbs done reaches vgdb_next_poll, scheduler will 119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov poll for gdbserver activity. VG_(force_vgdb_poll) and 120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(disable_vgdb_poll) allows the valgrind core (e.g. m_gdbserver) 121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov to control when the next poll will be done. */ 122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic ULong vgdb_next_poll; 123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Forwards */ 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_client_request ( ThreadId tid ); 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void scheduler_sanity ( ThreadId tid ); 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mostly_clear_thread_record ( ThreadId tid ); 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Stats. */ 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong n_scheduling_events_MINOR = 0; 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong n_scheduling_events_MAJOR = 0; 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Sanity checking counts. */ 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt sanity_fast_count = 0; 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt sanity_slow_count = 0; 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(print_scheduler_stats)(void) 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "scheduler: %'llu jumps (bb entries).\n", bbs_done ); 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "scheduler: %'llu/%'llu major/minor sched events.\n", 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_scheduling_events_MAJOR, n_scheduling_events_MINOR); 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " sanity: %d cheap, %d expensive checks.\n", 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sanity_fast_count, sanity_slow_count ); 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* CPU semaphore, so that threads can run exclusively */ 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic vg_sema_t the_BigLock; 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Base address of the NaCl sandbox. 153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovUWord nacl_head; 154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Path to NaCl nexe. 156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovchar *nacl_file; 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Helper functions for the scheduler. 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid print_sched_event ( ThreadId tid, Char* what ) 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, " SCHED[%d]: %s\n", tid, what ); 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* For showing SB counts, if the user asks to see them. */ 169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define SHOW_SBCOUNT_EVERY (20ULL * 1000 * 1000) 170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic ULong bbs_done_lastcheck = 0; 171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic 173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid maybe_show_sb_counts ( void ) 174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Long delta = bbs_done - bbs_done_lastcheck; 176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(delta >= 0); 177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (UNLIKELY(delta >= SHOW_SBCOUNT_EVERY)) { 178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(umsg)("%'lld superblocks executed\n", bbs_done); 179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov bbs_done_lastcheck = bbs_done; 180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownHChar* name_of_sched_event ( UInt event ) 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (event) { 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_SYSCALL: return "SYSCALL"; 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_INT32: return "INT32"; 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_INT128: return "INT128"; 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_INT129: return "INT129"; 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_INT130: return "INT130"; 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_SYSENTER: return "SYSENTER"; 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_CLIENTREQ: return "CLIENTREQ"; 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_YIELD: return "YIELD"; 195f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov case VEX_TRC_JMP_YIELD_NOREDIR: return "YIELD_NOREDIR"; 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_NODECODE: return "NODECODE"; 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_MAPFAIL: return "MAPFAIL"; 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_NOREDIR: return "NOREDIR"; 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_EMWARN: return "EMWARN"; 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_TINVAL: return "TINVAL"; 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_TRC_INVARIANT_FAILED: return "INVFAILED"; 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_TRC_INNER_COUNTERZERO: return "COUNTERZERO"; 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_TRC_INNER_FASTMISS: return "FASTMISS"; 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_TRC_FAULT_SIGNAL: return "FAULTSIGNAL"; 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: return "??UNKNOWN??"; 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Allocate a completely empty ThreadState record. */ 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownThreadId VG_(alloc_ThreadState) ( void ) 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 1; i < VG_N_THREADS; i++) { 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(threads)[i].status == VgTs_Empty) { 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[i].status = VgTs_Init; 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[i].exitreason = VgSrc_None; 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return i; 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("vg_alloc_ThreadState: no free slots available\n"); 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("Increase VG_N_THREADS, rebuild and try again.\n"); 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("VG_N_THREADS is too low"); 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Mark a thread as Runnable. This will block until the_BigLock is 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown available, so that we get exclusive access to all the shared 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown structures and the CPU. Up until we get the_BigLock, we must not 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown touch any shared state. 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown When this returns, we'll actually be running. 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(acquire_BigLock)(ThreadId tid, HChar* who) 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst; 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_sched)) { 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar buf[100]; 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(strlen)(who) <= 100-50); 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf, "waiting for lock (%s)", who); 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown print_sched_event(tid, buf); 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First, acquire the_BigLock. We can't do anything else safely 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown prior to this point. Even doing debug printing prior to this 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown point is, technically, wrong. */ 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(sema_down)(&the_BigLock, False/*not LL*/); 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(tid); 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tst->status != VgTs_Runnable); 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->status = VgTs_Runnable; 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(running_tid) != VG_INVALID_THREADID) 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("tid %d found %d running\n", tid, VG_(running_tid)); 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(running_tid) == VG_INVALID_THREADID); 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(running_tid) = tid; 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Addr gsp = VG_(get_SP)(tid); 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(unknown_SP_update)(gsp, gsp, 0/*unknown origin*/); 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_sched)) { 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar buf[150]; 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(strlen)(who) <= 150-50); 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf, " acquired lock (%s)", who); 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown print_sched_event(tid, buf); 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Set a thread into a sleeping state, and give up exclusive access to 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the CPU. On return, the thread must be prepared to block until it 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is ready to run again (generally this means blocking in a syscall, 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but it may mean that we remain in a Runnable state and we're just 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown yielding the CPU to another thread). 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(release_BigLock)(ThreadId tid, ThreadStatus sleepstate, HChar* who) 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tst->status == VgTs_Runnable); 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sleepstate == VgTs_WaitSys || 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sleepstate == VgTs_Yielding); 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->status = sleepstate; 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(running_tid) == tid); 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(running_tid) = VG_INVALID_THREADID; 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_sched)) { 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char buf[200]; 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(strlen)(who) <= 200-100); 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf, "releasing lock (%s) -> %s", 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown who, VG_(name_of_ThreadStatus)(sleepstate)); 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown print_sched_event(tid, buf); 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Release the_BigLock; this will reschedule any runnable 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread. */ 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(sema_up)(&the_BigLock, False/*not LL*/); 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* See pub_core_scheduler.h for description */ 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(acquire_BigLock_LL) ( HChar* who ) 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(sema_down)(&the_BigLock, True/*LL*/); 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* See pub_core_scheduler.h for description */ 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(release_BigLock_LL) ( HChar* who ) 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(sema_up)(&the_BigLock, True/*LL*/); 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Clear out the ThreadState and release the semaphore. Leaves the 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState in VgTs_Zombie state, so that it doesn't get 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reallocated until the caller is really ready. */ 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(exit_thread)(ThreadId tid) 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_exiting)(tid)); 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mostly_clear_thread_record(tid); 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(running_tid) = VG_INVALID_THREADID; 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There should still be a valid exitreason for this thread */ 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[tid].exitreason != VgSrc_None); 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_sched)) 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown print_sched_event(tid, "release lock in VG_(exit_thread)"); 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(sema_up)(&the_BigLock, False/*not LL*/); 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* If 'tid' is blocked in a syscall, send it SIGVGKILL so as to get it 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown out of the syscall and onto doing the next thing, whatever that is. 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If it isn't blocked in a syscall, has no effect on the thread. */ 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(get_thread_out_of_syscall)(ThreadId tid) 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!VG_(is_running_thread)(tid)); 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(threads)[tid].status == VgTs_WaitSys) { 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) { 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "get_thread_out_of_syscall zaps tid %d lwp %d\n", 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, VG_(threads)[tid].os_state.lwpid); 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_darwin) 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme use mach primitives on darwin? 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme thread_abort_safely? 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme race for thread with WaitSys set but not in syscall yet? 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern kern_return_t thread_abort(mach_port_t); 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread_abort(VG_(threads)[tid].os_state.lwpid); 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __attribute__((unused)) 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int r = VG_(tkill)(VG_(threads)[tid].os_state.lwpid, VG_SIGVGKILL); 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* JRS 2009-Mar-20: should we assert for r==0 (tkill succeeded)? 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown I'm really not sure. Here's a race scenario which argues 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that we shoudn't; but equally I'm not sure the scenario is 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown even possible, because of constraints caused by the question 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of who holds the BigLock when. 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Target thread tid does sys_read on a socket and blocks. This 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown function gets called, and we observe correctly that tid's 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown status is WaitSys but then for whatever reason this function 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goes very slowly for a while. Then data arrives from 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wherever, tid's sys_read returns, tid exits. Then we do 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tkill on tid, but tid no longer exists; tkill returns an 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown error code and the assert fails. */ 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* vg_assert(r == 0); */ 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Yield the CPU for a short time to let some other thread run. 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(vg_yield)(void) 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid = VG_(running_tid); 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tid != VG_INVALID_THREADID); 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[tid].os_state.lwpid == VG_(gettid)()); 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(release_BigLock)(tid, VgTs_Yielding, "VG_(vg_yield)"); 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Tell the kernel we're yielding. 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(do_syscall0)(__NR_sched_yield); 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(acquire_BigLock)(tid, "VG_(vg_yield)"); 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set the standard set of blocked signals, used whenever we're not 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown running a client syscall. */ 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void block_signals(void) 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t mask; 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigfillset)(&mask); 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Don't block these because they're synchronous */ 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&mask, VKI_SIGSEGV); 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&mask, VKI_SIGBUS); 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&mask, VKI_SIGFPE); 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&mask, VKI_SIGILL); 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&mask, VKI_SIGTRAP); 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Can't block these anyway */ 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&mask, VKI_SIGSTOP); 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&mask, VKI_SIGKILL); 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, NULL); 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void os_state_clear(ThreadState *tst) 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.lwpid = 0; 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.threadgroup = 0; 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no other fields to clear */ 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.post_mach_trap_fn = NULL; 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.pthread = 0; 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.func_arg = 0; 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&tst->os_state.child_go, 0, sizeof(tst->os_state.child_go)); 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&tst->os_state.child_done, 0, sizeof(tst->os_state.child_done)); 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.wq_jmpbuf_valid = False; 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.remote_port = 0; 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.msgh_id = 0; 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&tst->os_state.mach_args, 0, sizeof(tst->os_state.mach_args)); 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void os_state_init(ThreadState *tst) 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.valgrind_stack_base = 0; 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.valgrind_stack_init_SP = 0; 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown os_state_clear(tst); 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid mostly_clear_thread_record ( ThreadId tid ) 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t savedmask; 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tid >= 0 && tid < VG_N_THREADS); 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(cleanup_thread)(&VG_(threads)[tid].arch); 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].tid = tid; 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Leave the thread in Zombie, so that it doesn't get reallocated 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown until the caller is finally done with the thread stack. */ 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].status = VgTs_Zombie; 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigemptyset)(&VG_(threads)[tid].sig_mask); 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigemptyset)(&VG_(threads)[tid].tmp_sig_mask); 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown os_state_clear(&VG_(threads)[tid]); 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* start with no altstack */ 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].altstack.ss_sp = (void *)0xdeadbeef; 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].altstack.ss_size = 0; 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].altstack.ss_flags = VKI_SS_DISABLE; 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(clear_out_queued_signals)(tid, &savedmask); 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].sched_jmpbuf_valid = False; 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Called in the child after fork. If the parent has multiple 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown threads, then we've inherited a VG_(threads) array describing them, 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but only the thread which called fork() is actually alive in the 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown child. This functions needs to clean up all those other thread 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown structures. 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Whichever tid in the parent which called fork() becomes the 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown master_tid in the child. That's because the only living slot in 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads) in the child after fork is VG_(threads)[tid], and it 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown would be too hard to try to re-number the thread and relocate the 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread state down to VG_(threads)[1]. 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This function also needs to reinitialize the_BigLock, since 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown otherwise we may end up sharing its state with the parent, which 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown would be deeply confusing. 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void sched_fork_cleanup(ThreadId me) 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid; 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(running_tid) == me); 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_darwin) 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme hack reset Mach ports 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(mach_init)(); 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[me].os_state.lwpid = VG_(gettid)(); 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[me].os_state.threadgroup = VG_(getpid)(); 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* clear out all the unused thread slots */ 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (tid = 1; tid < VG_N_THREADS; tid++) { 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tid != me) { 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mostly_clear_thread_record(tid); 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].status = VgTs_Empty; 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(clear_syscallInfo)(tid); 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* re-init and take the sema */ 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(sema_deinit)(&the_BigLock); 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(sema_init)(&the_BigLock); 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(sema_down)(&the_BigLock, False/*not LL*/); 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* First phase of initialisation of the scheduler. Initialise the 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bigLock, zeroise the VG_(threads) structure and decide on the 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId of the root thread. 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownThreadId VG_(scheduler_init_phase1) ( void ) 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid_main; 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1,"sched","sched_init_phase1\n"); 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(sema_init)(&the_BigLock); 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0 /* NB; not 1 */; i < VG_N_THREADS; i++) { 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Paranoia .. completely zero it out. */ 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)( & VG_(threads)[i], 0, sizeof( VG_(threads)[i] ) ); 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[i].sig_queue = NULL; 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown os_state_init(&VG_(threads)[i]); 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mostly_clear_thread_record(i); 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[i].status = VgTs_Empty; 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[i].client_stack_szB = 0; 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[i].client_stack_highest_word = (Addr)NULL; 558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(threads)[i].err_disablement_level = 0; 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid_main = VG_(alloc_ThreadState)(); 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Bleh. Unfortunately there are various places in the system that 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assume that the main thread has a ThreadId of 1. 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - Helgrind (possibly) 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - stack overflow message in default_action() in m_signals.c 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - definitely a lot more places 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tid_main == 1); 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return tid_main; 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Second phase of initialisation of the scheduler. Given the root 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId computed by first phase of initialisation, fill in stack 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown details and acquire bigLock. Initialise the scheduler. This is 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown called at startup. The caller subsequently initialises the guest 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown state components of this main thread. 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(scheduler_init_phase2) ( ThreadId tid_main, 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr clstack_end, 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT clstack_size ) 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1,"sched","sched_init_phase2: tid_main=%d, " 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "cls_end=0x%lx, cls_sz=%ld\n", 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid_main, clstack_end, clstack_size); 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1)); 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(clstack_size)); 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid_main].client_stack_highest_word 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = clstack_end + 1 - sizeof(UWord); 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid_main].client_stack_szB 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = clstack_size; 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(atfork)(NULL, NULL, sched_fork_cleanup); 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Helpers for running translations. 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Use gcc's built-in setjmp/longjmp. longjmp must not restore signal 606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mask state, but does need to pass "val" through. jumped must be a 607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov volatile UWord. */ 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SCHEDSETJMP(tid, jumped, stmt) \ 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { \ 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState * volatile _qq_tst = VG_(get_ThreadState)(tid); \ 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (jumped) = VG_MINIMAL_SETJMP(_qq_tst->sched_jmpbuf); \ 613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if ((jumped) == ((UWord)0)) { \ 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!_qq_tst->sched_jmpbuf_valid); \ 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _qq_tst->sched_jmpbuf_valid = True; \ 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stmt; \ 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (VG_(clo_trace_sched)) \ 618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)("SCHEDSETJMP(line %d) tid %d, jumped=%ld\n", \ 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __LINE__, tid, jumped); \ 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(_qq_tst->sched_jmpbuf_valid); \ 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _qq_tst->sched_jmpbuf_valid = False; \ 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while(0) 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do various guest state alignment checks prior to running a thread. 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Specifically, check that what we have matches Vex's guest state 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout requirements. See libvex.h for details, but in short the 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown requirements are: There must be no holes in between the primary 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guest state, its two copies, and the spill area. In short, all 4 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown areas must have a 16-aligned size and be 16-aligned, and placed 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown back-to-back. */ 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_pre_run_checks ( ThreadState* tst ) 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a_vex = (Addr) & tst->arch.vex; 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a_vexsh1 = (Addr) & tst->arch.vex_shadow1; 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a_vexsh2 = (Addr) & tst->arch.vex_shadow2; 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a_spill = (Addr) & tst->arch.vex_spill; 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt sz_vex = (UInt) sizeof tst->arch.vex; 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt sz_vexsh1 = (UInt) sizeof tst->arch.vex_shadow1; 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt sz_vexsh2 = (UInt) sizeof tst->arch.vex_shadow2; 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt sz_spill = (UInt) sizeof tst->arch.vex_spill; 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("gst %p %d, sh1 %p %d, " 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "sh2 %p %d, spill %p %d\n", 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)a_vex, sz_vex, 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)a_vexsh1, sz_vexsh1, 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)a_vexsh2, sz_vexsh2, 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)a_spill, sz_spill ); 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_16_ALIGNED(sz_vex)); 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_16_ALIGNED(sz_vexsh1)); 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_16_ALIGNED(sz_vexsh2)); 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_16_ALIGNED(sz_spill)); 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_16_ALIGNED(a_vex)); 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_16_ALIGNED(a_vexsh1)); 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_16_ALIGNED(a_vexsh2)); 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_16_ALIGNED(a_spill)); 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check that the guest state and its two shadows have the same 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown size, and that there are no holes in between. The latter is 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown important because Memcheck assumes that it can reliably access 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the shadows by indexing off a pointer to the start of the 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown primary guest state area. */ 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sz_vex == sz_vexsh1); 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sz_vex == sz_vexsh2); 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(a_vex + 1 * sz_vex == a_vexsh1); 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(a_vex + 2 * sz_vex == a_vexsh2); 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Also check there's no hole between the second shadow area and 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the spill area. */ 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sz_spill == LibVEX_N_SPILL_BYTES); 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(a_vex + 3 * sz_vex == a_spill); 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGA_amd64) 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* x86/amd64 XMM regs must form an array, ie, have no 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown holes in between. */ 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (offsetof(VexGuestAMD64State,guest_XMM16) 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - offsetof(VexGuestAMD64State,guest_XMM0)) 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown == (17/*#regs*/-1) * 16/*bytes per reg*/ 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGA_ppc32) || defined(VGA_ppc64) 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ppc guest_state vector regs must be 16 byte aligned for 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown loads/stores. This is important! */ 688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex.guest_VSR0)); 689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex_shadow1.guest_VSR0)); 690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex_shadow2.guest_VSR0)); 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* be extra paranoid .. */ 692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex.guest_VSR1)); 693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex_shadow1.guest_VSR1)); 694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex_shadow2.guest_VSR1)); 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGA_arm) 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* arm guest_state VFP regs must be 8 byte aligned for 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown loads/stores. */ 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex.guest_D0)); 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex_shadow1.guest_D0)); 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex_shadow2.guest_D0)); 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* be extra paranoid .. */ 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex.guest_D1)); 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex_shadow1.guest_D1)); 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex_shadow2.guest_D1)); 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 708b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 709b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGA_s390x) 710b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* no special requirements */ 711b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 714b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// NO_VGDB_POLL value ensures vgdb is not polled, while 715b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// VGDB_POLL_ASAP ensures that the next scheduler call 716b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// will cause a poll. 717b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define NO_VGDB_POLL 0xffffffffffffffffULL 718b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define VGDB_POLL_ASAP 0x0ULL 719b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 720b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid VG_(disable_vgdb_poll) (void ) 721b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 722b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vgdb_next_poll = NO_VGDB_POLL; 723b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 724b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid VG_(force_vgdb_poll) ( void ) 725b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 726b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vgdb_next_poll = VGDB_POLL_ASAP; 727b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Run the thread tid for a while, and return a VG_TRC_* value 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown indicating why VG_(run_innerloop) stopped. */ 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt run_thread_for_a_while ( ThreadId tid ) 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 733b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov volatile UWord jumped; 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown volatile ThreadState* tst = NULL; /* stop gcc complaining */ 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown volatile UInt trc; 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown volatile Int dispatch_ctr_SAVED; 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown volatile Int done_this_time; 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Paranoia */ 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!VG_(is_exiting)(tid)); 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(tid); 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_pre_run_checks( (ThreadState*)tst ); 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* end Paranoia */ 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown trc = 0; 749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dispatch_ctr_SAVED = VG_(dispatch_ctr); 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* there should be no undealt-with signals */ 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //vg_assert(VG_(threads)[tid].siginfo.si_signo == 0); 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) { 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t m; 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, err = VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &m); 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(err == 0); 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("tid %d: entering code with unblocked signals: ", tid); 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 1; i <= _VKI_NSIG; i++) 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_(sigismember)(&m, i)) 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("%d ", i); 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Tell the tool this thread is about to run client code 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( start_client_code, tid, bbs_done ); 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(in_generated_code) == False); 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(in_generated_code) = True; 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SCHEDSETJMP( 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jumped, 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown trc = (UInt)VG_(run_innerloop)( (void*)&tst->arch.vex, 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(clo_profile_flags) > 0 ? 1 : 0 ) 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(in_generated_code) == True); 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(in_generated_code) = False; 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 781b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (jumped != (UWord)0) { 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We get here if the client took a fault that caused our signal 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler to longjmp. */ 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(trc == 0); 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown trc = VG_TRC_FAULT_SIGNAL; 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_signals(); 787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown done_this_time = (Int)dispatch_ctr_SAVED - (Int)VG_(dispatch_ctr) - 0; 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(done_this_time >= 0); 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbs_done += (ULong)done_this_time; 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Tell the tool this thread has stopped running client code 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( stop_client_code, tid, bbs_done ); 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (bbs_done >= vgdb_next_poll) { 798b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(clo_vgdb_poll)) 799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vgdb_next_poll = bbs_done + (ULong)VG_(clo_vgdb_poll); 800b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 801b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* value was changed due to gdbserver invocation via ptrace */ 802b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vgdb_next_poll = NO_VGDB_POLL; 803b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(gdbserver_activity) (tid)) 804b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdbserver) (tid); 805b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 806b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return trc; 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Run a no-redir translation just once, and return the resulting 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRC_* value. */ 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt run_noredir_translation ( Addr hcode, ThreadId tid ) 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 815b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov volatile UWord jumped; 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown volatile ThreadState* tst; 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown volatile UWord argblock[4]; 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown volatile UInt retval; 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Paranoia */ 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!VG_(is_exiting)(tid)); 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(tid); 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_pre_run_checks( (ThreadState*)tst ); 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* end Paranoia */ 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGA_ppc32) || defined(VGA_ppc64) 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* I don't think we need to clear this thread's guest_RESVN here, 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown because we can only get here if run_thread_for_a_while() has 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown been used immediately before, on this same thread. */ 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There can be 3 outcomes from VG_(run_a_noredir_translation): 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - a signal occurred and the sighandler longjmp'd. Then both [2] 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and [3] are unchanged - hence zero. 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - translation ran normally, set [2] (next guest IP) and set [3] 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to whatever [1] was beforehand, indicating a normal (boring) 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jump to the next block. 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - translation ran normally, set [2] (next guest IP) and set [3] 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to something different from [1] beforehand, which indicates a 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown TRC_ value. 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argblock[0] = (UWord)hcode; 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argblock[1] = (UWord)&VG_(threads)[tid].arch.vex; 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argblock[2] = 0; /* next guest IP is written here */ 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown argblock[3] = 0; /* guest state ptr afterwards is written here */ 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Tell the tool this thread is about to run client code 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( start_client_code, tid, bbs_done ); 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(in_generated_code) == False); 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(in_generated_code) = True; 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SCHEDSETJMP( 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jumped, 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(run_a_noredir_translation)( &argblock[0] ) 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(in_generated_code) = False; 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 867b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (jumped != (UWord)0) { 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We get here if the client took a fault that caused our signal 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler to longjmp. */ 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(argblock[2] == 0); /* next guest IP was not written */ 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(argblock[3] == 0); /* trc was not written */ 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_signals(); 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown retval = VG_TRC_FAULT_SIGNAL; 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* store away the guest program counter */ 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(set_IP)( tid, argblock[2] ); 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (argblock[3] == argblock[1]) 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* the guest state pointer afterwards was unchanged */ 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown retval = VG_TRC_BORING; 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown retval = (UInt)argblock[3]; 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbs_done++; 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Tell the tool this thread has stopped running client code 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( stop_client_code, tid, bbs_done ); 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return retval; 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The scheduler proper. 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handle_tt_miss ( ThreadId tid ) 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool found; 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr ip = VG_(get_IP)(tid); 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Trivial event. Miss in the fast-cache. Do a full 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lookup for it. */ 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown found = VG_(search_transtab)( NULL, ip, True/*upd_fast_cache*/ ); 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (UNLIKELY(!found)) { 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not found; we need to request a translation. */ 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(translate)( tid, ip, /*debug*/False, 0/*not verbose*/, 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbs_done, True/*allow redirection*/ )) { 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown found = VG_(search_transtab)( NULL, ip, True ); 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(found, "VG_TRC_INNER_FASTMISS: missing tt_fast entry"); 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If VG_(translate)() fails, it's because it had to throw a 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // signal because the client jumped to a bad address. That 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // means that either a signal has been set up for delivery, 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // or the thread has been marked for termination. Either 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // way, we just need to go back into the scheduler loop. 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handle_syscall(ThreadId tid, UInt trc) 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState * volatile tst = VG_(get_ThreadState)(tid); 925b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov volatile UWord jumped; 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Syscall may or may not block; either way, it will be 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown complete by the time this call returns, and we'll be 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown runnable again. We could take a signal while the 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall runs. */ 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_sanity_level >= 3)) 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_do_sync_check)("(BEFORE SYSCALL)",__FILE__,__LINE__); 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SCHEDSETJMP(tid, jumped, VG_(client_syscall)(tid, trc)); 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_sanity_level >= 3)) 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_do_sync_check)("(AFTER SYSCALL)",__FILE__,__LINE__); 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_(is_running_thread)(tid)) 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("tid %d not running; VG_(running_tid)=%d, tid %d status %d\n", 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, VG_(running_tid), tid, tst->status); 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 945b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (jumped != (UWord)0) { 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_signals(); 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(poll_signals)(tid); 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* tid just requested a jump to the noredir version of its current 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown program counter. So make up that translation if needed, run it, 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and return the resulting thread return code. */ 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt/*trc*/ handle_noredir_jump ( ThreadId tid ) 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AddrH hcode = 0; 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr ip = VG_(get_IP)(tid); 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool found = VG_(search_unredir_transtab)( &hcode, ip ); 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!found) { 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not found; we need to request a translation. */ 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(translate)( tid, ip, /*debug*/False, 0/*not verbose*/, bbs_done, 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown False/*NO REDIRECTION*/ )) { 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown found = VG_(search_unredir_transtab)( &hcode, ip ); 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(found, "unredir translation missing after creation?!"); 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If VG_(translate)() fails, it's because it had to throw a 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // signal because the client jumped to a bad address. That 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // means that either a signal has been set up for delivery, 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // or the thread has been marked for termination. Either 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // way, we just need to go back into the scheduler loop. 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_TRC_BORING; 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(found); 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(hcode != 0); 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Otherwise run it and return the resulting VG_TRC_* value. */ 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return run_noredir_translation( hcode, tid ); 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Run a thread until it wants to exit. 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown We assume that the caller has already called VG_(acquire_BigLock) for 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown us, so we own the VCPU. Also, all signals are blocked. 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVgSchedReturnCode VG_(scheduler) ( ThreadId tid ) 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 995b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UInt trc = VG_TRC_BORING; 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 997b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov static Bool vgdb_startup_action_done = False; 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_sched)) 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown print_sched_event(tid, "entering VG_(scheduler)"); 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1002b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Do vgdb initialization (but once). Only the first (main) task 1003b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov starting up will do the below. 1004b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Initialize gdbserver earlier than at the first 1005b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov thread VG_(scheduler) is causing problems: 1006b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * at the end of VG_(scheduler_init_phase2) : 1007b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov The main thread is in VgTs_Init state, but in a not yet 1008b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov consistent state => the thread cannot be reported to gdb 1009b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (e.g. causes an assert in LibVEX_GuestX86_get_eflags when giving 1010b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov back the guest registers to gdb). 1011b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * at end of valgrind_main, just 1012b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov before VG_(main_thread_wrapper_NORETURN)(1) : 1013b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov The main thread is still in VgTs_Init state but in a 1014b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov more advanced state. However, the thread state is not yet 1015b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov completely initialized : a.o., the os_state is not yet fully 1016b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov set => the thread is then not properly reported to gdb, 1017b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov which is then confused (causing e.g. a duplicate thread be 1018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov shown, without thread id). 1019b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * it would be possible to initialize gdbserver "lower" in the 1020b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov call stack (e.g. in VG_(main_thread_wrapper_NORETURN)) but 1021b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov these are platform dependent and the place at which 1022b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov the thread state is completely initialized is not 1023b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov specific anymore to the main thread (so a similar "do it only 1024b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov once" would be needed). 1025b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1026b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov => a "once only" initialization here is the best compromise. */ 1027b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!vgdb_startup_action_done) { 1028b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(tid == 1); // it must be the main thread. 1029b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vgdb_startup_action_done = True; 1030b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(clo_vgdb) != Vg_VgdbNo) { 1031b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* If we have to poll, ensures we do an initial poll at first 1032b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov scheduler call. Otherwise, ensure no poll (unless interrupted 1033b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov by ptrace). */ 1034b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(clo_vgdb_poll)) 1035b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(force_vgdb_poll) (); 1036b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 1037b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(disable_vgdb_poll) (); 1038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1039b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert (VG_(dyn_vgdb_error) == VG_(clo_vgdb_error)); 1040b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* As we are initializing, VG_(dyn_vgdb_error) can't have been 1041b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov changed yet. */ 1042b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1043b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdbserver_prerun_action) (1); 1044b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 1045b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(disable_vgdb_poll) (); 1046b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1047b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1048b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* set the proper running signal mask */ 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_signals(); 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dispatch_ctr) = SCHEDULING_QUANTUM + 1; 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (!VG_(is_exiting)(tid)) { 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(dispatch_ctr) == 1) { 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Our slice is done, so yield the CPU to another thread. On 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Linux, this doesn't sleep between sleeping and running, 1062b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov since that would take too much time. */ 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 4 July 06: it seems that a zero-length nsleep is needed to 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cause async thread cancellation (canceller.c) to terminate 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in finite time; else it is in some kind of race/starvation 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown situation and completion is arbitrarily delayed (although 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this is not a deadlock). 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Unfortunately these sleeps cause MPI jobs not to terminate 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sometimes (some kind of livelock). So sleeping once 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown every N opportunities appears to work. */ 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 3 Aug 06: doing sys__nsleep works but crashes some apps. 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sys_yield also helps the problem, whilst not crashing apps. */ 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(release_BigLock)(tid, VgTs_Yielding, 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "VG_(scheduler):timeslice"); 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ------------ now we don't have The Lock ------------ */ 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1081f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov VG_(do_syscall0)(__NR_sched_yield); 1082f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(acquire_BigLock)(tid, "VG_(scheduler):timeslice"); 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ------------ now we do have The Lock ------------ */ 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* OK, do some relatively expensive housekeeping stuff */ 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scheduler_sanity(tid); 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sanity_check_general)(False); 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Look for any pending signals for this thread, and set them up 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for delivery */ 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(poll_signals)(tid); 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(is_exiting)(tid)) 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; /* poll_signals picked up a fatal signal */ 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For stats purposes only. */ 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_scheduling_events_MAJOR++; 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Figure out how many bbs to ask vg_run_innerloop to do. Note 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that it decrements the counter before testing it for zero, so 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that if tst->dispatch_ctr is set to N you get at most N-1 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iterations. Also this means that tst->dispatch_ctr must 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exceed zero before entering the innerloop. Also also, the 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown decrement is done before the bb is actually run, so you 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown always get at least one decrement even if nothing happens. */ 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dispatch_ctr) = SCHEDULING_QUANTUM + 1; 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* paranoia ... */ 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tst->tid == tid); 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tst->os_state.lwpid == VG_(gettid)()); 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For stats purposes only. */ 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_scheduling_events_MINOR++; 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "thread %d: running for %d bbs\n", 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, VG_(dispatch_ctr) - 1 ); 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1121f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov if (trc == VEX_TRC_JMP_YIELD_NOREDIR) { 1122f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov trc = handle_noredir_jump(tid); 1123f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov } else { 1124f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov trc = run_thread_for_a_while ( tid ); 1125f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov } 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_sched) && VG_(clo_verbosity) > 2) { 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char buf[50]; 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf, "TRC: %s", name_of_sched_event(trc)); 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown print_sched_event(tid, buf); 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (trc == VEX_TRC_JMP_NOREDIR) { 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we got a request to run a no-redir version of 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown something, do so now -- handle_noredir_jump just (creates 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and) runs that one translation. The flip side is that the 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown noredir translation can't itself return another noredir 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown request -- that would be nonsensical. It can, however, 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_TRC_BORING, which just means keep going as 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown normal. */ 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown trc = handle_noredir_jump(tid); 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(trc != VEX_TRC_JMP_NOREDIR); 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (trc) { 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_TRC_BORING: 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no special event, just keep going. */ 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_TRC_INNER_FASTMISS: 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(dispatch_ctr) > 1); 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handle_tt_miss(tid); 1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_CLIENTREQ: 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_client_request(tid); 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_INT128: /* x86-linux */ 1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_INT129: /* x86-darwin */ 1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_INT130: /* x86-darwin */ 1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_SYSCALL: /* amd64-linux, ppc32-linux, amd64-darwin */ 1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handle_syscall(tid, trc); 1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_sanity_level) > 2) 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sanity_check_general)(True); /* sanity-check every syscall */ 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_YIELD: 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Explicit yield, because this thread is in a spin-lock 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or something. Only let the thread run for a short while 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown longer. Because swapping to another thread is expensive, 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we're prepared to let this thread eat a little more CPU 1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown before swapping to another. That means that short term 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spins waiting for hardware to poke memory won't cause a 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread swap. */ 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(dispatch_ctr) > 2000) 1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(dispatch_ctr) = 2000; 1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1180f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov case VEX_TRC_JMP_YIELD_NOREDIR: 1181f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov VG_(dispatch_ctr) = 1; 1182f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov break; 1183f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_TRC_INNER_COUNTERZERO: 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Timeslice is out. Let a new thread be scheduled. */ 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(dispatch_ctr) == 1); 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_TRC_FAULT_SIGNAL: 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Everything should be set up (either we're exiting, or 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown about to start in a signal handler). */ 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_MAPFAIL: 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Failure of arch-specific address translation (x86/amd64 1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment override use) */ 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* jrs 2005 03 11: is this correct? */ 1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(synth_fault)(tid); 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_EMWARN: { 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Int counts[EmWarn_NUMBER]; 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Bool counts_initted = False; 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexEmWarn ew; 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* what; 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool show; 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int q; 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!counts_initted) { 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown counts_initted = True; 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (q = 0; q < EmWarn_NUMBER; q++) 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown counts[q] = 0; 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ew = (VexEmWarn)VG_(threads)[tid].arch.vex.guest_EMWARN; 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown what = (ew < 0 || ew >= EmWarn_NUMBER) 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? "unknown (?!)" 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : LibVEX_EmWarn_string(ew); 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show = (ew < 0 || ew >= EmWarn_NUMBER) 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? True 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : counts[ew]++ < 3; 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (show && VG_(clo_show_emwarns) && !VG_(clo_xml)) { 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_UserMsg, 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Emulation warning: unsupported action:\n"); 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_UserMsg, " %s\n", what); 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace)( tid, VG_(clo_backtrace_size) ); 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_EMFAIL: { 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexEmWarn ew; 1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar* what; 1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ew = (VexEmWarn)VG_(threads)[tid].arch.vex.guest_EMWARN; 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown what = (ew < 0 || ew >= EmWarn_NUMBER) 1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? "unknown (?!)" 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : LibVEX_EmWarn_string(ew); 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_UserMsg, 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Emulation fatal error -- Valgrind cannot continue:\n"); 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_UserMsg, " %s\n", what); 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace)( tid, VG_(clo_backtrace_size) ); 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "\n"); 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Valgrind has to exit now. Sorry.\n"); 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "\n"); 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(1); 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SIGTRAP: 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(synth_sigtrap)(tid); 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SIGSEGV: 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(synth_fault)(tid); 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SIGBUS: 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(synth_sigbus)(tid); 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_NODECODE: 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)( 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "valgrind: Unrecognised instruction at address %#lx.\n", 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_IP)(tid)); 1263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(get_and_pp_StackTrace)(tid, 50); 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define M(a) VG_(umsg)(a "\n"); 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown M("Your program just tried to execute an instruction that Valgrind" ); 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown M("did not recognise. There are two possible reasons for this." ); 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown M("1. Your program has a bug and erroneously jumped to a non-code" ); 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown M(" location. If you are running Memcheck and you just saw a" ); 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown M(" warning about a bad jump, it's probably your program's fault."); 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown M("2. The instruction is legitimate but Valgrind doesn't handle it,"); 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown M(" i.e. it's Valgrind's fault. If you think this is the case or"); 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown M(" you are not sure, please let us know and we'll try to fix it."); 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown M("Either way, Valgrind will now raise a SIGILL signal which will" ); 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown M("probably kill your program." ); 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef M 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(synth_sigill)(tid, VG_(get_IP)(tid)); 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_TINVAL: 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Addr64)VG_(threads)[tid].arch.vex.guest_TISTART, 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].arch.vex.guest_TILEN, 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "scheduler(VEX_TRC_JMP_TINVAL)" 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("dump translations done.\n"); 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_TRC_INVARIANT_FAILED: 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This typically happens if, after running generated code, 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it is detected that host CPU settings (eg, FPU/Vector 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown control words) are not as they should be. Vex's code 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generation specifies the state such control words should 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be in on entry to Vex-generated code, and they should be 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unchanged on exit from it. Failure of this assertion 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown usually means a bug in Vex's code generation. */ 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //{ UInt xx; 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // __asm__ __volatile__ ( 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // "\t.word 0xEEF12A10\n" // fmrx r2,fpscr 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // "\tmov %0, r2" : "=r"(xx) : : "r2" ); 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // VG_(printf)("QQQQ new fpscr = %08x\n", xx); 1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //} 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(0, "VG_(scheduler), phase 3: " 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "run_innerloop detected host " 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "state invariant failure", trc); 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_SYSENTER: 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Do whatever simulation is appropriate for an x86 sysenter 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instruction. Note that it is critical to set this thread's 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guest_EIP to point at the code to execute after the 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sysenter, since Vex-generated code will not have set it -- 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex does not know what it should be. Vex sets the next 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown address to zero, so if you don't set guest_EIP, the thread 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown will jump to zero afterwards and probably die as a result. */ 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) 1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(0, "VG_(scheduler), phase 3: " 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "sysenter_x86 on x86-linux is not supported"); 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_x86_darwin) 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* return address in client edx */ 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].arch.vex.guest_EIP 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = VG_(threads)[tid].arch.vex.guest_EDX; 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handle_syscall(tid, trc); 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(0, "VG_(scheduler), phase 3: " 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "sysenter_x86 on non-x86 platform?!?!"); 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(0, "VG_(scheduler), phase 3: " 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "unexpected thread return code (%u)", trc); 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* NOTREACHED */ 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* switch (trc) */ 1336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (0) 1338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov maybe_show_sb_counts(); 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_sched)) 1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown print_sched_event(tid, "exiting VG_(scheduler)"); 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_exiting)(tid)); 1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return tst->exitreason; 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This causes all threads to forceably exit. They aren't actually 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dead by the time this returns; you need to call 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(reap_threads)() to wait for them. 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(nuke_all_threads_except) ( ThreadId me, VgSchedReturnCode src ) 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid; 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(me)); 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (tid = 1; tid < VG_N_THREADS; tid++) { 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tid == me 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || VG_(threads)[tid].status == VgTs_Empty) 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "VG_(nuke_all_threads_except): nuking tid %d\n", tid); 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].exitreason = src; 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (src == VgSrc_FatalSig) 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].os_state.fatalsig = VKI_SIGKILL; 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_thread_out_of_syscall)(tid); 1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Specifying shadow register values 1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGA_x86) 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_CLREQ_ARGS guest_EAX 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_CLREQ_RET guest_EDX 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGA_amd64) 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_CLREQ_ARGS guest_RAX 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_CLREQ_RET guest_RDX 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGA_ppc32) || defined(VGA_ppc64) 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_CLREQ_ARGS guest_GPR4 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_CLREQ_RET guest_GPR3 1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGA_arm) 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_CLREQ_ARGS guest_R4 1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_CLREQ_RET guest_R3 1393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined (VGA_s390x) 1394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define VG_CLREQ_ARGS guest_r2 1395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define VG_CLREQ_RET guest_r3 1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown arch 1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CLREQ_ARGS(regs) ((regs).vex.VG_CLREQ_ARGS) 1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CLREQ_RET(regs) ((regs).vex.VG_CLREQ_RET) 1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define O_CLREQ_RET (offsetof(VexGuestArchState, VG_CLREQ_RET)) 1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// These macros write a value to a client's thread register, and tell the 1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// tool that it's happened (if necessary). 1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SET_CLREQ_RETVAL(zztid, zzval) \ 1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { CLREQ_RET(VG_(threads)[zztid].arch) = (zzval); \ 1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, \ 1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Vg_CoreClientReq, zztid, O_CLREQ_RET, sizeof(UWord)); \ 1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SET_CLCALL_RETVAL(zztid, zzval, f) \ 1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { CLREQ_RET(VG_(threads)[zztid].arch) = (zzval); \ 1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write_clientcall_return, \ 1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zztid, O_CLREQ_RET, sizeof(UWord), f); \ 1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Handle client requests. 1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// OS-specific(?) client requests 1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool os_client_request(ThreadId tid, UWord *args) 1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool handled = True; 1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(args[0]) { 1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__LIBC_FREERES_DONE: 1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is equivalent to an exit() syscall, but we don't set the 1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exitcode (since it might already be set) */ 1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 || VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) 1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "__libc_freeres() done; really quitting!\n"); 1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].exitreason = VgSrc_ExitThread; 1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handled = False; 1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return handled; 1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do a client request for the thread tid. After the request, tid may 1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or may not still be runnable; if not, the scheduler will have to 1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown choose a new thread to run. 1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_client_request ( ThreadId tid ) 1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord* arg = (UWord*)(CLREQ_ARGS(VG_(threads)[tid].arch)); 1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord req_no = arg[0]; 1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("req no = 0x%llx, arg = %p\n", (ULong)req_no, arg); 1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (req_no) { 1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__CLIENT_CALL0: { 1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord (*f)(ThreadId) = (void*)arg[1]; 1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (f == NULL) 1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "VG_USERREQ__CLIENT_CALL0: func=%p\n", f); 1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLCALL_RETVAL(tid, f ( tid ), (Addr)f); 1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__CLIENT_CALL1: { 1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord (*f)(ThreadId, UWord) = (void*)arg[1]; 1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (f == NULL) 1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "VG_USERREQ__CLIENT_CALL1: func=%p\n", f); 1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLCALL_RETVAL(tid, f ( tid, arg[2] ), (Addr)f ); 1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__CLIENT_CALL2: { 1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord (*f)(ThreadId, UWord, UWord) = (void*)arg[1]; 1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (f == NULL) 1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "VG_USERREQ__CLIENT_CALL2: func=%p\n", f); 1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLCALL_RETVAL(tid, f ( tid, arg[2], arg[3] ), (Addr)f ); 1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__CLIENT_CALL3: { 1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord (*f)(ThreadId, UWord, UWord, UWord) = (void*)arg[1]; 1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (f == NULL) 1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "VG_USERREQ__CLIENT_CALL3: func=%p\n", f); 1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLCALL_RETVAL(tid, f ( tid, arg[2], arg[3], arg[4] ), (Addr)f ); 1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Nb: this looks like a circular definition, because it kind of is. 1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // See comment in valgrind.h to understand what's going on. 1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__RUNNING_ON_VALGRIND: 1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL(tid, RUNNING_ON_VALGRIND+1); 1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__PRINTF: { 1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* JRS 2010-Jan-28: this is DEPRECATED; use the 1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _VALIST_BY_REF version instead */ 1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sizeof(va_list) != sizeof(UWord)) 1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto va_list_casting_error_NORETURN; 1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown union { 1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown va_list vargs; 1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long uw; 1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } u; 1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown u.uw = (unsigned long)arg[2]; 1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int count = 1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(vmessage)( Vg_ClientMsg, (char *)arg[1], u.vargs ); 1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message_flush)(); 1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, count ); 1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__PRINTF_BACKTRACE: { 1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* JRS 2010-Jan-28: this is DEPRECATED; use the 1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _VALIST_BY_REF version instead */ 1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sizeof(va_list) != sizeof(UWord)) 1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto va_list_casting_error_NORETURN; 1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown union { 1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown va_list vargs; 1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long uw; 1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } u; 1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown u.uw = (unsigned long)arg[2]; 1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int count = 1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(vmessage)( Vg_ClientMsg, (char *)arg[1], u.vargs ); 1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message_flush)(); 1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace)( tid, VG_(clo_backtrace_size) ); 1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, count ); 1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__PRINTF_VALIST_BY_REF: { 1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown va_list* vargsp = (va_list*)arg[2]; 1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int count = 1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(vmessage)( Vg_ClientMsg, (char *)arg[1], *vargsp ); 1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message_flush)(); 1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, count ); 1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF: { 1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown va_list* vargsp = (va_list*)arg[2]; 1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int count = 1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(vmessage)( Vg_ClientMsg, (char *)arg[1], *vargsp ); 1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message_flush)(); 1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace)( tid, VG_(clo_backtrace_size) ); 1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, count ); 1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__INTERNAL_PRINTF_VALIST_BY_REF: { 1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown va_list* vargsp = (va_list*)arg[2]; 1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int count = 1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(vmessage)( Vg_DebugMsg, (char *)arg[1], *vargsp ); 1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message_flush)(); 1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, count ); 1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__ADD_IFUNC_TARGET: { 1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(redir_add_ifunc_target)( arg[1], arg[2] ); 1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, 0); 1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; } 1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__STACK_REGISTER: { 1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord sid = VG_(register_stack)((Addr)arg[1], (Addr)arg[2]); 1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, sid ); 1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; } 1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__STACK_DEREGISTER: { 1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(deregister_stack)(arg[1]); 1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ 1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; } 1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__STACK_CHANGE: { 1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(change_stack)(arg[1], (Addr)arg[2], (Addr)arg[3]); 1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ 1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; } 1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__GET_MALLOCFUNCS: { 1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vg_mallocfunc_info *info = (struct vg_mallocfunc_info *)arg[1]; 1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl_malloc = VG_(tdict).tool_malloc; 1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl_calloc = VG_(tdict).tool_calloc; 1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl_realloc = VG_(tdict).tool_realloc; 1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl_memalign = VG_(tdict).tool_memalign; 1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl___builtin_new = VG_(tdict).tool___builtin_new; 1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl___builtin_vec_new = VG_(tdict).tool___builtin_vec_new; 1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl_free = VG_(tdict).tool_free; 1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl___builtin_delete = VG_(tdict).tool___builtin_delete; 1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl___builtin_vec_delete = VG_(tdict).tool___builtin_vec_delete; 1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl_malloc_usable_size = VG_(tdict).tool_malloc_usable_size; 1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->mallinfo = VG_(mallinfo); 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->clo_trace_malloc = VG_(clo_trace_malloc); 1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ 1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Requests from the client program */ 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__DISCARD_TRANSLATIONS: 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 2) 1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( "client request: DISCARD_TRANSLATIONS," 1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " addr %p, len %lu\n", 1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)arg[1], arg[2] ); 1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( 1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg[1], arg[2], "scheduler(VG_USERREQ__DISCARD_TRANSLATIONS)" 1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ 1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__COUNT_ERRORS: 1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, VG_(get_n_errs_found)() ); 1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__LOAD_PDB_DEBUGINFO: 1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(di_notify_pdb_debuginfo)( arg[1], arg[2], arg[3], arg[4] ); 1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ 1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__MAP_IP_TO_SRCLOC: { 1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr ip = arg[1]; 1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UChar* buf64 = (UChar*)arg[2]; 1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(buf64, 0, 64); 1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt linenum = 0; 1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok = VG_(get_filename_linenum)( 1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ip, &buf64[0], 50, NULL, 0, NULL, &linenum 1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok) { 1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Find the terminating zero in the first 50 bytes. */ 1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt i; 1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < 50; i++) { 1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (buf64[i] == 0) 1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We must find a zero somewhere in 0 .. 49. Else 1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_filename_linenum) is not properly zero 1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown terminating. */ 1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(i < 50); 1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(&buf64[i], ":%u", linenum); 1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf64[0] = 0; 1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ 1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case VG_USERREQ__CHANGE_ERR_DISABLEMENT: { 1662b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Word delta = arg[1]; 1663b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(delta == 1 || delta == -1); 1664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ThreadState* tst = VG_(get_ThreadState)(tid); 1665b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(tst); 1666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (delta == 1 && tst->err_disablement_level < 0xFFFFFFFF) { 1667b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tst->err_disablement_level++; 1668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1669b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 1670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (delta == -1 && tst->err_disablement_level > 0) { 1671b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tst->err_disablement_level--; 1672b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1673b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ 1674b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; 1675b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1676b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__MALLOCLIKE_BLOCK: 1678b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case VG_USERREQ__RESIZEINPLACE_BLOCK: 1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__FREELIKE_BLOCK: 1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Ignore them if the addr is NULL; otherwise pass onto the tool. 1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!arg[1]) { 1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ 1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto my_default; 1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1688f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov case VG_USERREQ__NACL_MEM_START: { 1689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Addr mem_start = arg[1]; 1690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov nacl_head = mem_start; 1691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)("*********************** NaCl mem_start: %p\n", (void*)mem_start); 1692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // At this point all segments in the sandbox belong to nacl_file (the 1694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // first untrusted binary loaded by sel_ldr), and have correct 1695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // permissions. Read its debug info. 1696b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov NSegment* seg = VG_(am_find_nsegment)(mem_start); 1697b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int fnIdx = -1; 1698b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (seg) { 1699b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (seg->kind == SkFileC) { 1700b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (fnIdx == seg->fnIdx || fnIdx == -1) { 1701b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fnIdx = seg->fnIdx; 1702b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)("Segment at %p belongs to the loader\n", (void*)seg->start); 1703b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(di_notify_mmap)(seg->start, False, /*glider: don't use fd*/-1); 1704b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1705b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1706b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov seg = VG_(am_next_nsegment)((NSegment*)seg, True); 1707b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1708f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov goto my_default; 1709f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov } 1710f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 1711f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov case VG_USERREQ__NACL_FILE: { 1712f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov VG_(printf)("*********************** NaCl nacl_file: %s\n", (void*)arg[1]); 1713f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov nacl_file = (char*) arg[1]; 1714f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov goto my_default; 1715f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov } 1716f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 1717b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case VG_USERREQ__NACL_MMAP: { 1718b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // Simulate an mmap(). 1719b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord vma = arg[1]; // Base VMA of the mapping. 1720b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord size = arg[2]; // Size of the mapping. 1721b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord file_offset = arg[3]; // File offset. 1722b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord access = arg[4]; // Access. 1723b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord clone_vma = arg[5]; // Another mapping of the same; only used to find the file name. 1724b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!access) 1725b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov access = VKI_PROT_READ | VKI_PROT_EXEC; 1726b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)("*********************** NaCl nacl_mmap: %lx %lx %lx %lx\n", vma, size, file_offset, clone_vma); 1727b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1728b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov char* file_name = NULL; 1729b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (clone_vma) { 1730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov NSegment* seg = VG_(am_find_nsegment)(clone_vma); 1731b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov file_name = VG_(am_get_filename)(seg); 1732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)("*********************** NaCl DSO file_name: %s\n", file_name); 1733b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1734b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1735b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord vma_end = vma + size; 1736b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord vma_aligned = VG_PGROUNDDN(vma); 1737b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord vma_end_aligned = VG_PGROUNDUP(vma_end); 1738b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov size = vma_end_aligned - vma_aligned; 1739b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov file_offset -= vma - vma_aligned; 1740b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(am_notify_fake_client_mmap)(vma_aligned, size, access, 1741b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 0, file_name ? file_name : (VG_(clo_nacl_file) ? VG_(clo_nacl_file) : nacl_file), file_offset); 1742b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // If file_name == NULL, then this is the main (sel_ldr-mapped) nexe, 1743b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // and has incorrect permissions at this point. In that case, wait for 1744b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov // NACL_MEM_START to read the debug info. 1745b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (file_name) 1746b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(di_notify_mmap)(vma_aligned, False, /*glider: don't use fd*/-1); 1747b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov goto my_default; 1748b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1749b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1750f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown my_default: 1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (os_client_request(tid, arg)) { 1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // do nothing, os_client_request() handled it 1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (VG_(needs).client_requests) { 1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord ret; 1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 2) 1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("client request: code %lx, addr %p, len %lu\n", 1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg[0], (void*)arg[1], arg[2] ); 1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( VG_TDICT_CALL(tool_handle_client_request, tid, arg, &ret) ) 1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL(tid, ret); 1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Bool whined = False; 1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!whined && VG_(clo_verbosity) > 2) { 1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Allow for requests in core, but defined by tools, which 1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // have 0 and 0 in their two high bytes. 1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char c1 = (arg[0] >> 24) & 0xff; 1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char c2 = (arg[0] >> 16) & 0xff; 1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (c1 == 0) c1 = '_'; 1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (c2 == 0) c2 = '_'; 1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Warning:\n" 1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " unhandled client request: 0x%lx (%c%c+0x%lx). Perhaps\n" 1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " VG_(needs).client_requests should be set?\n", 1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg[0], c1, c2, arg[0] & 0xffff); 1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown whined = True; 1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown va_list_casting_error_NORETURN: 1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)( 1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Valgrind: fatal error - cannot continue: use of the deprecated\n" 1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "client requests VG_USERREQ__PRINTF or VG_USERREQ__PRINTF_BACKTRACE\n" 1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "on a platform where they cannot be supported. Please use the\n" 1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "equivalent _VALIST_BY_REF versions instead.\n" 1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\n" 1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "This is a binary-incompatible change in Valgrind's client request\n" 1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "mechanism. It is unfortunate, but difficult to avoid. End-users\n" 1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "are expected to almost never see this message. The only case in\n" 1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "which you might see this message is if your code uses the macros\n" 1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "VALGRIND_PRINTF or VALGRIND_PRINTF_BACKTRACE. If so, you will need\n" 1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "to recompile such code, using the header files from this version of\n" 1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Valgrind, and not any previous version.\n" 1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\n" 1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "If you see this mesage in any other circumstances, it is probably\n" 1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "a bug in Valgrind. In this case, please file a bug report at\n" 1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\n" 1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " http://www.valgrind.org/support/bug_reports.html\n" 1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\n" 1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Will now abort.\n" 1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Sanity checking (permanently engaged) 1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Internal consistency checks on the sched structures. */ 1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid scheduler_sanity ( ThreadId tid ) 1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool bad = False; 1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UInt lasttime = 0; 1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt now; 1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int lwpid = VG_(gettid)(); 1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_(is_running_thread)(tid)) { 1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Thread %d is supposed to be running, " 1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "but doesn't own the_BigLock (owned by %d)\n", 1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, VG_(running_tid)); 1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad = True; 1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (lwpid != VG_(threads)[tid].os_state.lwpid) { 1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Thread %d supposed to be in LWP %d, but we're actually %d\n", 1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, VG_(threads)[tid].os_state.lwpid, VG_(gettid)()); 1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad = True; 1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if !defined(VGO_darwin) 1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme 1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (lwpid != the_BigLock.owner_lwpid) { 1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Thread (LWPID) %d doesn't own the_BigLock\n", 1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid); 1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad = True; 1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Periodically show the state of all threads, for debugging 1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown purposes. */ 1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown now = VG_(read_millisecond_timer)(); 1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 && (!bad) && (lasttime + 4000/*ms*/ <= now)) { 1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lasttime = now; 1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n------------ Sched State at %d ms ------------\n", 1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (Int)now); 1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(show_sched_status)(); 1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* core_panic also shows the sched status, which is why we don't 1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show it above if bad==True. */ 1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bad) 1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("scheduler_sanity: failed"); 1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(sanity_check_general) ( Bool force_expensive ) 1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid; 1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UInt next_slow_check_at = 1; 1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UInt slow_check_interval = 25; 1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_sanity_level) < 1) return; 1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- First do all the tests that we can do quickly. ---*/ 1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sanity_fast_count++; 1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check stuff pertaining to the memory check system. */ 1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check that nobody has spuriously claimed that the first or 1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown last 16 pages of memory have become accessible [...] */ 1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(needs).sanity_checks) { 1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_TDICT_CALL(tool_cheap_sanity_check)); 1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- Now some more expensive checks. ---*/ 1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Once every now and again, check some more expensive stuff. 1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Gradually increase the interval between such checks so as not to 1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown burden long-running programs too much. */ 1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( force_expensive 1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || VG_(clo_sanity_level) > 1 1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (VG_(clo_sanity_level) == 1 1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && sanity_fast_count == next_slow_check_at)) { 1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("SLOW at %d\n", sanity_fast_count-1); 1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown next_slow_check_at = sanity_fast_count - 1 + slow_check_interval; 1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown slow_check_interval++; 1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sanity_slow_count++; 1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(needs).sanity_checks) { 1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_TDICT_CALL(tool_expensive_sanity_check)); 1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Look for stack overruns. Visit all threads. */ 1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (tid = 1; tid < VG_N_THREADS; tid++) { 1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT remains; 1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VgStack* stack; 1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(threads)[tid].status == VgTs_Empty || 1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].status == VgTs_Zombie) 1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack 1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = (VgStack*) 1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_ThreadState)(tid)->os_state.valgrind_stack_base; 1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT limit 1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = 4096; // Let's say. Checking more causes lots of L2 misses. 1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown remains 1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = VG_(am_get_VgStack_unused_szB)(stack, limit); 1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (remains < limit) 1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "WARNING: Thread %d is within %ld bytes " 1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "of running out of stack!\n", 1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, remains); 1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_sanity_level) > 1) { 1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check sanity of the low-level memory manager. Note that bugs 1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in the client's code can cause this to fail, so we don't do 1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this check unless specially asked for. And because it's 1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown potentially very expensive. */ 1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sanity_check_malloc_all)(); 1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1943