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 10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Copyright (C) 2000-2013 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...] 58663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/ 59663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h" 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuglog.h" 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h" 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vkiscnums.h" // __NR_sched_yield 65b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_threadstate.h" 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h" 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_clreq.h" // for VG_USERREQ__* 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_dispatch.h" 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_errormgr.h" // For VG_(get_n_errs_found)() 71b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_gdbserver.h" // for VG_(gdbserver) and VG_(gdbserver_activity) 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h" 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h" 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h" 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcproc.h" 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcsignal.h" 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_darwin) 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mach.h" 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_machine.h" 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mallocfree.h" 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h" 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_replacemalloc.h" 84436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_core_sbprofile.h" 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_signals.h" 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_stacks.h" 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_stacktrace.h" // For VG_(get_and_pp_StackTrace)() 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syscall.h" 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syswrap.h" 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h" 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_translate.h" // For VG_(translate)() 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_transtab.h" 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuginfo.h" // VG_(di_notify_pdb_debuginfo) 94663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "priv_sched-lock.h" 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_scheduler.h" // self 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_redir.h" 97436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "libvex_emnote.h" // VexEmNote 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Types and globals for the scheduler. 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ThreadId and ThreadState are defined elsewhere*/ 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Defines the thread-scheduling timeslice, in terms of the number of 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown basic blocks we attempt to run each thread for. Smaller values 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown give finer interleaving but much increased scheduling overheads. */ 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SCHEDULING_QUANTUM 100000 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* If False, a fault is Valgrind-internal (ie, a bug) */ 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool VG_(in_generated_code) = False; 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 133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Stats: number of XIndirs, and number that missed in the fast 134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng cache. */ 135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic ULong stats__n_xindirs = 0; 136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic ULong stats__n_xindir_misses = 0; 137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* And 32-bit temp bins for the above, so that 32-bit platforms don't 139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng have to do 64 bit incs on the hot path through 140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(cp_disp_xindir). */ 141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*global*/ UInt VG_(stats__n_xindirs_32) = 0; 142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/*global*/ UInt VG_(stats__n_xindir_misses_32) = 0; 143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Sanity checking counts. */ 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt sanity_fast_count = 0; 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt sanity_slow_count = 0; 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(print_scheduler_stats)(void) 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "scheduler: %'llu event checks.\n", bbs_done ); 152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(message)(Vg_DebugMsg, 153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "scheduler: %'llu indir transfers, %'llu misses (1 in %llu)\n", 154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng stats__n_xindirs, stats__n_xindir_misses, 155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng stats__n_xindirs / (stats__n_xindir_misses 156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ? stats__n_xindir_misses : 1)); 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "scheduler: %'llu/%'llu major/minor sched events.\n", 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_scheduling_events_MAJOR, n_scheduling_events_MINOR); 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " sanity: %d cheap, %d expensive checks.\n", 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sanity_fast_count, sanity_slow_count ); 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng * Mutual exclusion object used to serialize threads. 167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng */ 168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic struct sched_lock *the_BigLock; 169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Helper functions for the scheduler. 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 176436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid print_sched_event ( ThreadId tid, const HChar* what ) 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, " SCHED[%d]: %s\n", tid, what ); 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 181436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* For showing SB profiles, if the user asks to see them. */ 182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic 183436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid maybe_show_sb_profile ( void ) 184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 185436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* DO NOT MAKE NON-STATIC */ 186436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov static ULong bbs_done_lastcheck = 0; 187436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* */ 188436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(VG_(clo_profyle_interval) > 0); 189436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Long delta = (Long)(bbs_done - bbs_done_lastcheck); 190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(delta >= 0); 191436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if ((ULong)delta >= VG_(clo_profyle_interval)) { 192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov bbs_done_lastcheck = bbs_done; 193436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(get_and_show_SB_profile)(bbs_done); 194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovconst HChar* name_of_sched_event ( UInt event ) 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (event) { 201eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov case VEX_TRC_JMP_INVALICACHE: return "INVALICACHE"; 202eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov case VEX_TRC_JMP_FLUSHDCACHE: return "FLUSHDCACHE"; 203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_NOREDIR: return "NOREDIR"; 204436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case VEX_TRC_JMP_SIGILL: return "SIGILL"; 205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_SIGTRAP: return "SIGTRAP"; 206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_SIGSEGV: return "SIGSEGV"; 207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_SIGBUS: return "SIGBUS"; 208436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case VEX_TRC_JMP_SIGFPE_INTOVF: 209436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case VEX_TRC_JMP_SIGFPE_INTDIV: return "SIGFPE"; 210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_EMWARN: return "EMWARN"; 211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_EMFAIL: return "EMFAIL"; 212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_CLIENTREQ: return "CLIENTREQ"; 213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_YIELD: return "YIELD"; 214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_NODECODE: return "NODECODE"; 215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_MAPFAIL: return "MAPFAIL"; 216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_SYS_SYSCALL: return "SYSCALL"; 217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_SYS_INT32: return "INT32"; 218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_SYS_INT128: return "INT128"; 219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_SYS_INT129: return "INT129"; 220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_SYS_INT130: return "INT130"; 221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_SYS_SYSENTER: return "SYSENTER"; 222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_BORING: return "VEX_BORING"; 223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VG_TRC_BORING: return "VG_BORING"; 225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VG_TRC_INNER_FASTMISS: return "FASTMISS"; 226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VG_TRC_INNER_COUNTERZERO: return "COUNTERZERO"; 227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VG_TRC_FAULT_SIGNAL: return "FAULTSIGNAL"; 228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VG_TRC_INVARIANT_FAILED: return "INVFAILED"; 229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VG_TRC_CHAIN_ME_TO_SLOW_EP: return "CHAIN_ME_SLOW"; 230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VG_TRC_CHAIN_ME_TO_FAST_EP: return "CHAIN_ME_FAST"; 231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng default: return "??UNKNOWN??"; 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Allocate a completely empty ThreadState record. */ 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownThreadId VG_(alloc_ThreadState) ( void ) 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 1; i < VG_N_THREADS; i++) { 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(threads)[i].status == VgTs_Empty) { 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[i].status = VgTs_Init; 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[i].exitreason = VgSrc_None; 243436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (VG_(threads)[i].thread_name) 244436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(arena_free)(VG_AR_CORE, VG_(threads)[i].thread_name); 245436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(threads)[i].thread_name = NULL; 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return i; 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("vg_alloc_ThreadState: no free slots available\n"); 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("Increase VG_N_THREADS, rebuild and try again.\n"); 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("VG_N_THREADS is too low"); 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Mark a thread as Runnable. This will block until the_BigLock is 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown available, so that we get exclusive access to all the shared 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown structures and the CPU. Up until we get the_BigLock, we must not 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown touch any shared state. 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown When this returns, we'll actually be running. 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 263436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid VG_(acquire_BigLock)(ThreadId tid, const HChar* who) 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst; 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_sched)) { 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar buf[100]; 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(strlen)(who) <= 100-50); 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf, "waiting for lock (%s)", who); 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown print_sched_event(tid, buf); 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First, acquire the_BigLock. We can't do anything else safely 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown prior to this point. Even doing debug printing prior to this 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown point is, technically, wrong. */ 279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(acquire_BigLock_LL)(NULL); 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(tid); 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tst->status != VgTs_Runnable); 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->status = VgTs_Runnable; 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(running_tid) != VG_INVALID_THREADID) 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("tid %d found %d running\n", tid, VG_(running_tid)); 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(running_tid) == VG_INVALID_THREADID); 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(running_tid) = tid; 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { Addr gsp = VG_(get_SP)(tid); 293436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (NULL != VG_(tdict).track_new_mem_stack_w_ECU) 294436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(unknown_SP_update_w_ECU)(gsp, gsp, 0/*unknown origin*/); 295436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov else 296436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(unknown_SP_update)(gsp, gsp); 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_sched)) { 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown HChar buf[150]; 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(strlen)(who) <= 150-50); 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf, " acquired lock (%s)", who); 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown print_sched_event(tid, buf); 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Set a thread into a sleeping state, and give up exclusive access to 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the CPU. On return, the thread must be prepared to block until it 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is ready to run again (generally this means blocking in a syscall, 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but it may mean that we remain in a Runnable state and we're just 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown yielding the CPU to another thread). 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 314436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid VG_(release_BigLock)(ThreadId tid, ThreadStatus sleepstate, 315436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* who) 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tst->status == VgTs_Runnable); 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sleepstate == VgTs_WaitSys || 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sleepstate == VgTs_Yielding); 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->status = sleepstate; 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(running_tid) == tid); 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(running_tid) = VG_INVALID_THREADID; 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_sched)) { 330436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar buf[200]; 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(strlen)(who) <= 200-100); 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf, "releasing lock (%s) -> %s", 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown who, VG_(name_of_ThreadStatus)(sleepstate)); 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown print_sched_event(tid, buf); 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Release the_BigLock; this will reschedule any runnable 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread. */ 339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(release_BigLock_LL)(NULL); 340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void init_BigLock(void) 343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{ 344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(!the_BigLock); 345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng the_BigLock = ML_(create_sched_lock)(); 346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic void deinit_BigLock(void) 349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{ 350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ML_(destroy_sched_lock)(the_BigLock); 351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng the_BigLock = NULL; 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* See pub_core_scheduler.h for description */ 355436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid VG_(acquire_BigLock_LL) ( const HChar* who ) 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ML_(acquire_sched_lock)(the_BigLock); 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* See pub_core_scheduler.h for description */ 361436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid VG_(release_BigLock_LL) ( const HChar* who ) 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ML_(release_sched_lock)(the_BigLock); 364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 366663860b1408516d02ebfcb3a9999a134e6cfb223Ben ChengBool VG_(owns_BigLock_LL) ( ThreadId tid ) 367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{ 368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return (ML_(get_sched_lock_owner)(the_BigLock) 369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng == VG_(threads)[tid].os_state.lwpid); 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Clear out the ThreadState and release the semaphore. Leaves the 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState in VgTs_Zombie state, so that it doesn't get 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reallocated until the caller is really ready. */ 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(exit_thread)(ThreadId tid) 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_exiting)(tid)); 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mostly_clear_thread_record(tid); 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(running_tid) = VG_INVALID_THREADID; 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There should still be a valid exitreason for this thread */ 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[tid].exitreason != VgSrc_None); 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_sched)) 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown print_sched_event(tid, "release lock in VG_(exit_thread)"); 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(release_BigLock_LL)(NULL); 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* If 'tid' is blocked in a syscall, send it SIGVGKILL so as to get it 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown out of the syscall and onto doing the next thing, whatever that is. 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If it isn't blocked in a syscall, has no effect on the thread. */ 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(get_thread_out_of_syscall)(ThreadId tid) 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!VG_(is_running_thread)(tid)); 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(threads)[tid].status == VgTs_WaitSys) { 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_signals)) { 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "get_thread_out_of_syscall zaps tid %d lwp %d\n", 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, VG_(threads)[tid].os_state.lwpid); 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_darwin) 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme use mach primitives on darwin? 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme thread_abort_safely? 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme race for thread with WaitSys set but not in syscall yet? 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown extern kern_return_t thread_abort(mach_port_t); 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread_abort(VG_(threads)[tid].os_state.lwpid); 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __attribute__((unused)) 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int r = VG_(tkill)(VG_(threads)[tid].os_state.lwpid, VG_SIGVGKILL); 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* JRS 2009-Mar-20: should we assert for r==0 (tkill succeeded)? 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown I'm really not sure. Here's a race scenario which argues 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that we shoudn't; but equally I'm not sure the scenario is 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown even possible, because of constraints caused by the question 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of who holds the BigLock when. 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Target thread tid does sys_read on a socket and blocks. This 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown function gets called, and we observe correctly that tid's 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown status is WaitSys but then for whatever reason this function 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goes very slowly for a while. Then data arrives from 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wherever, tid's sys_read returns, tid exits. Then we do 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tkill on tid, but tid no longer exists; tkill returns an 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown error code and the assert fails. */ 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* vg_assert(r == 0); */ 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Yield the CPU for a short time to let some other thread run. 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(vg_yield)(void) 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid = VG_(running_tid); 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tid != VG_INVALID_THREADID); 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(threads)[tid].os_state.lwpid == VG_(gettid)()); 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(release_BigLock)(tid, VgTs_Yielding, "VG_(vg_yield)"); 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Tell the kernel we're yielding. 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(do_syscall0)(__NR_sched_yield); 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(acquire_BigLock)(tid, "VG_(vg_yield)"); 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set the standard set of blocked signals, used whenever we're not 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown running a client syscall. */ 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void block_signals(void) 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t mask; 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigfillset)(&mask); 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Don't block these because they're synchronous */ 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&mask, VKI_SIGSEGV); 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&mask, VKI_SIGBUS); 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&mask, VKI_SIGFPE); 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&mask, VKI_SIGILL); 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&mask, VKI_SIGTRAP); 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Can't block these anyway */ 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&mask, VKI_SIGSTOP); 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigdelset)(&mask, VKI_SIGKILL); 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, NULL); 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void os_state_clear(ThreadState *tst) 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.lwpid = 0; 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.threadgroup = 0; 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no other fields to clear */ 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.post_mach_trap_fn = NULL; 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.pthread = 0; 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.func_arg = 0; 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&tst->os_state.child_go, 0, sizeof(tst->os_state.child_go)); 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&tst->os_state.child_done, 0, sizeof(tst->os_state.child_done)); 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.wq_jmpbuf_valid = False; 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.remote_port = 0; 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.msgh_id = 0; 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(&tst->os_state.mach_args, 0, sizeof(tst->os_state.mach_args)); 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void os_state_init(ThreadState *tst) 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.valgrind_stack_base = 0; 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.valgrind_stack_init_SP = 0; 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown os_state_clear(tst); 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid mostly_clear_thread_record ( ThreadId tid ) 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t savedmask; 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tid >= 0 && tid < VG_N_THREADS); 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(cleanup_thread)(&VG_(threads)[tid].arch); 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].tid = tid; 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Leave the thread in Zombie, so that it doesn't get reallocated 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown until the caller is finally done with the thread stack. */ 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].status = VgTs_Zombie; 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigemptyset)(&VG_(threads)[tid].sig_mask); 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigemptyset)(&VG_(threads)[tid].tmp_sig_mask); 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown os_state_clear(&VG_(threads)[tid]); 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* start with no altstack */ 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].altstack.ss_sp = (void *)0xdeadbeef; 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].altstack.ss_size = 0; 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].altstack.ss_flags = VKI_SS_DISABLE; 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(clear_out_queued_signals)(tid, &savedmask); 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].sched_jmpbuf_valid = False; 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Called in the child after fork. If the parent has multiple 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown threads, then we've inherited a VG_(threads) array describing them, 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but only the thread which called fork() is actually alive in the 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown child. This functions needs to clean up all those other thread 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown structures. 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Whichever tid in the parent which called fork() becomes the 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown master_tid in the child. That's because the only living slot in 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads) in the child after fork is VG_(threads)[tid], and it 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown would be too hard to try to re-number the thread and relocate the 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread state down to VG_(threads)[1]. 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This function also needs to reinitialize the_BigLock, since 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown otherwise we may end up sharing its state with the parent, which 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown would be deeply confusing. 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void sched_fork_cleanup(ThreadId me) 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid; 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(running_tid) == me); 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_darwin) 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme hack reset Mach ports 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(mach_init)(); 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[me].os_state.lwpid = VG_(gettid)(); 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[me].os_state.threadgroup = VG_(getpid)(); 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* clear out all the unused thread slots */ 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (tid = 1; tid < VG_N_THREADS; tid++) { 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tid != me) { 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mostly_clear_thread_record(tid); 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].status = VgTs_Empty; 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(clear_syscallInfo)(tid); 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* re-init and take the sema */ 578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng deinit_BigLock(); 579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng init_BigLock(); 580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(acquire_BigLock_LL)(NULL); 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* First phase of initialisation of the scheduler. Initialise the 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bigLock, zeroise the VG_(threads) structure and decide on the 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId of the root thread. 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownThreadId VG_(scheduler_init_phase1) ( void ) 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid_main; 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1,"sched","sched_init_phase1\n"); 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (VG_(clo_fair_sched) != disable_fair_sched 596663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng && !ML_(set_sched_lock_impl)(sched_lock_ticket) 597663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng && VG_(clo_fair_sched) == enable_fair_sched) 598663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng { 599663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(printf)("Error: fair scheduling is not supported on this system.\n"); 600663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(exit)(1); 601663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 602663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 603663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (VG_(clo_verbosity) > 1) { 604663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(message)(Vg_DebugMsg, 605663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "Scheduler: using %s scheduler lock implementation.\n", 606663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ML_(get_sched_lock_name)()); 607663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 608663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 609663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng init_BigLock(); 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0 /* NB; not 1 */; i < VG_N_THREADS; i++) { 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Paranoia .. completely zero it out. */ 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)( & VG_(threads)[i], 0, sizeof( VG_(threads)[i] ) ); 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[i].sig_queue = NULL; 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown os_state_init(&VG_(threads)[i]); 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mostly_clear_thread_record(i); 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[i].status = VgTs_Empty; 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[i].client_stack_szB = 0; 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[i].client_stack_highest_word = (Addr)NULL; 623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(threads)[i].err_disablement_level = 0; 624436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(threads)[i].thread_name = NULL; 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid_main = VG_(alloc_ThreadState)(); 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Bleh. Unfortunately there are various places in the system that 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assume that the main thread has a ThreadId of 1. 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - Helgrind (possibly) 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - stack overflow message in default_action() in m_signals.c 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown - definitely a lot more places 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tid_main == 1); 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return tid_main; 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Second phase of initialisation of the scheduler. Given the root 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId computed by first phase of initialisation, fill in stack 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown details and acquire bigLock. Initialise the scheduler. This is 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown called at startup. The caller subsequently initialises the guest 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown state components of this main thread. 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(scheduler_init_phase2) ( ThreadId tid_main, 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr clstack_end, 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT clstack_size ) 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(debugLog)(1,"sched","sched_init_phase2: tid_main=%d, " 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "cls_end=0x%lx, cls_sz=%ld\n", 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid_main, clstack_end, clstack_size); 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1)); 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_PAGE_ALIGNED(clstack_size)); 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid_main].client_stack_highest_word 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = clstack_end + 1 - sizeof(UWord); 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid_main].client_stack_szB 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = clstack_size; 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(atfork)(NULL, NULL, sched_fork_cleanup); 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Helpers for running translations. 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Use gcc's built-in setjmp/longjmp. longjmp must not restore signal 672b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mask state, but does need to pass "val" through. jumped must be a 673b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov volatile UWord. */ 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SCHEDSETJMP(tid, jumped, stmt) \ 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { \ 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState * volatile _qq_tst = VG_(get_ThreadState)(tid); \ 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown \ 678b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (jumped) = VG_MINIMAL_SETJMP(_qq_tst->sched_jmpbuf); \ 679b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if ((jumped) == ((UWord)0)) { \ 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!_qq_tst->sched_jmpbuf_valid); \ 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _qq_tst->sched_jmpbuf_valid = True; \ 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stmt; \ 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (VG_(clo_trace_sched)) \ 684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)("SCHEDSETJMP(line %d) tid %d, jumped=%ld\n", \ 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __LINE__, tid, jumped); \ 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(_qq_tst->sched_jmpbuf_valid); \ 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _qq_tst->sched_jmpbuf_valid = False; \ 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while(0) 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do various guest state alignment checks prior to running a thread. 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Specifically, check that what we have matches Vex's guest state 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown layout requirements. See libvex.h for details, but in short the 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown requirements are: There must be no holes in between the primary 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guest state, its two copies, and the spill area. In short, all 4 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown areas must have a 16-aligned size and be 16-aligned, and placed 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown back-to-back. */ 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void do_pre_run_checks ( ThreadState* tst ) 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a_vex = (Addr) & tst->arch.vex; 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a_vexsh1 = (Addr) & tst->arch.vex_shadow1; 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a_vexsh2 = (Addr) & tst->arch.vex_shadow2; 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a_spill = (Addr) & tst->arch.vex_spill; 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt sz_vex = (UInt) sizeof tst->arch.vex; 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt sz_vexsh1 = (UInt) sizeof tst->arch.vex_shadow1; 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt sz_vexsh2 = (UInt) sizeof tst->arch.vex_shadow2; 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt sz_spill = (UInt) sizeof tst->arch.vex_spill; 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("gst %p %d, sh1 %p %d, " 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "sh2 %p %d, spill %p %d\n", 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)a_vex, sz_vex, 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)a_vexsh1, sz_vexsh1, 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)a_vexsh2, sz_vexsh2, 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)a_spill, sz_spill ); 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_16_ALIGNED(sz_vex)); 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_16_ALIGNED(sz_vexsh1)); 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_16_ALIGNED(sz_vexsh2)); 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_16_ALIGNED(sz_spill)); 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_16_ALIGNED(a_vex)); 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_16_ALIGNED(a_vexsh1)); 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_16_ALIGNED(a_vexsh2)); 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_16_ALIGNED(a_spill)); 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check that the guest state and its two shadows have the same 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown size, and that there are no holes in between. The latter is 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown important because Memcheck assumes that it can reliably access 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the shadows by indexing off a pointer to the start of the 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown primary guest state area. */ 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sz_vex == sz_vexsh1); 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sz_vex == sz_vexsh2); 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(a_vex + 1 * sz_vex == a_vexsh1); 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(a_vex + 2 * sz_vex == a_vexsh2); 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Also check there's no hole between the second shadow area and 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the spill area. */ 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(sz_spill == LibVEX_N_SPILL_BYTES); 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(a_vex + 3 * sz_vex == a_spill); 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# if defined(VGA_x86) 742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* x86 XMM regs must form an array, ie, have no holes in 743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng between. */ 744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert( 745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (offsetof(VexGuestX86State,guest_XMM7) 746663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng - offsetof(VexGuestX86State,guest_XMM0)) 747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng == (8/*#regs*/-1) * 16/*bytes per reg*/ 748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ); 749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(VG_IS_16_ALIGNED(offsetof(VexGuestX86State,guest_XMM0))); 750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(VG_IS_8_ALIGNED(offsetof(VexGuestX86State,guest_FPREG))); 751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(8 == offsetof(VexGuestX86State,guest_EAX)); 752663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(VG_IS_4_ALIGNED(offsetof(VexGuestX86State,guest_EAX))); 753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(VG_IS_4_ALIGNED(offsetof(VexGuestX86State,guest_EIP))); 754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# endif 755663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGA_amd64) 757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* amd64 YMM regs must form an array, ie, have no holes in 758663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng between. */ 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( 760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (offsetof(VexGuestAMD64State,guest_YMM16) 761663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng - offsetof(VexGuestAMD64State,guest_YMM0)) 762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng == (17/*#regs*/-1) * 32/*bytes per reg*/ 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(VG_IS_16_ALIGNED(offsetof(VexGuestAMD64State,guest_YMM0))); 765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(VG_IS_8_ALIGNED(offsetof(VexGuestAMD64State,guest_FPREG))); 766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(16 == offsetof(VexGuestAMD64State,guest_RAX)); 767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(VG_IS_8_ALIGNED(offsetof(VexGuestAMD64State,guest_RAX))); 768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(VG_IS_8_ALIGNED(offsetof(VexGuestAMD64State,guest_RIP))); 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGA_ppc32) || defined(VGA_ppc64) 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ppc guest_state vector regs must be 16 byte aligned for 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown loads/stores. This is important! */ 774b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex.guest_VSR0)); 775b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex_shadow1.guest_VSR0)); 776b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex_shadow2.guest_VSR0)); 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* be extra paranoid .. */ 778b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex.guest_VSR1)); 779b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex_shadow1.guest_VSR1)); 780b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex_shadow2.guest_VSR1)); 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGA_arm) 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* arm guest_state VFP regs must be 8 byte aligned for 785663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng loads/stores. Let's use 16 just to be on the safe side. */ 786663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex.guest_D0)); 787663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex_shadow1.guest_D0)); 788663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex_shadow2.guest_D0)); 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* be extra paranoid .. */ 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex.guest_D1)); 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex_shadow1.guest_D1)); 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex_shadow2.guest_D1)); 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 794b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 795436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# if defined(VGA_arm64) 796436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex.guest_X0)); 797436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex_shadow1.guest_X0)); 798436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex_shadow2.guest_X0)); 799436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex.guest_Q0)); 800436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex_shadow1.guest_Q0)); 801436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov vg_assert(VG_IS_16_ALIGNED(& tst->arch.vex_shadow2.guest_Q0)); 802436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# endif 803436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 804b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGA_s390x) 805b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* no special requirements */ 806b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 807663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 808436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# if defined(VGA_mips32) || defined(VGA_mips64) 809436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* no special requirements */ 810663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# endif 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 813b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// NO_VGDB_POLL value ensures vgdb is not polled, while 814b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// VGDB_POLL_ASAP ensures that the next scheduler call 815b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// will cause a poll. 816b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define NO_VGDB_POLL 0xffffffffffffffffULL 817b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define VGDB_POLL_ASAP 0x0ULL 818b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 819b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid VG_(disable_vgdb_poll) (void ) 820b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 821b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vgdb_next_poll = NO_VGDB_POLL; 822b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 823b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid VG_(force_vgdb_poll) ( void ) 824b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 825b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vgdb_next_poll = VGDB_POLL_ASAP; 826b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Run the thread tid for a while, and return a VG_TRC_* value 829663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng indicating why VG_(disp_run_translations) stopped, and possibly an 830663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng auxiliary word. Also, only allow the thread to run for at most 831663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *dispatchCtrP events. If (as is the normal case) use_alt_host_addr 832663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng is False, we are running ordinary redir'd translations, and we 833663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng should therefore start by looking up the guest next IP in TT. If 834663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng it is True then we ignore the guest next IP and just run from 835663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng alt_host_addr, which presumably points at host code for a no-redir 836663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng translation. 837663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 838663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Return results are placed in two_words. two_words[0] is set to the 839663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng TRC. In the case where that is VG_TRC_CHAIN_ME_TO_{SLOW,FAST}_EP, 840663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng the address to patch is placed in two_words[1]. 841663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng*/ 842663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic 843663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid run_thread_for_a_while ( /*OUT*/HWord* two_words, 844663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /*MOD*/Int* dispatchCtrP, 845663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ThreadId tid, 846663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HWord alt_host_addr, 847663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool use_alt_host_addr ) 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 849663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng volatile HWord jumped = 0; 850663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng volatile ThreadState* tst = NULL; /* stop gcc complaining */ 851663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng volatile Int done_this_time = 0; 852663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng volatile HWord host_code_addr = 0; 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Paranoia */ 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(!VG_(is_exiting)(tid)); 858663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(*dispatchCtrP > 0); 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(tid); 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_pre_run_checks( (ThreadState*)tst ); 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* end Paranoia */ 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 864663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Futz with the XIndir stats counters. */ 865663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(VG_(stats__n_xindirs_32) == 0); 866663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(VG_(stats__n_xindir_misses_32) == 0); 867663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 868663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Clear return area. */ 869663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng two_words[0] = two_words[1] = 0; 870663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 871663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Figure out where we're starting from. */ 872663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (use_alt_host_addr) { 873663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* unusual case -- no-redir translation */ 874663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng host_code_addr = alt_host_addr; 875663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 876663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* normal case -- redir translation */ 877663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng UInt cno = (UInt)VG_TT_FAST_HASH((Addr)tst->arch.vex.VG_INSTR_PTR); 878663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (LIKELY(VG_(tt_fast)[cno].guest == (Addr)tst->arch.vex.VG_INSTR_PTR)) 879663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng host_code_addr = VG_(tt_fast)[cno].host; 880663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng else { 881663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng AddrH res = 0; 882663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* not found in VG_(tt_fast). Searching here the transtab 883663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng improves the performance compared to returning directly 884663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng to the scheduler. */ 885663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool found = VG_(search_transtab)(&res, NULL, NULL, 886663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (Addr)tst->arch.vex.VG_INSTR_PTR, 887663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng True/*upd cache*/ 888663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ); 889663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (LIKELY(found)) { 890663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng host_code_addr = res; 891663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 892663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* At this point, we know that we intended to start at a 893663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng normal redir translation, but it was not found. In 894663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng which case we can return now claiming it's not 895663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng findable. */ 896663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng two_words[0] = VG_TRC_INNER_FASTMISS; /* hmm, is that right? */ 897663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 898663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 899663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 900663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 901663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* We have either a no-redir or a redir translation. */ 902663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(host_code_addr != 0); /* implausible */ 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* there should be no undealt-with signals */ 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //vg_assert(VG_(threads)[tid].siginfo.si_signo == 0); 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 907663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Set up event counter stuff for the run. */ 908663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng tst->arch.vex.host_EvC_COUNTER = *dispatchCtrP; 909663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng tst->arch.vex.host_EvC_FAILADDR 910663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng = (HWord)VG_(fnptr_to_fnentry)( &VG_(disp_cp_evcheck_fail) ); 911663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) { 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t m; 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, err = VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &m); 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(err == 0); 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("tid %d: entering code with unblocked signals: ", tid); 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 1; i <= _VKI_NSIG; i++) 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_(sigismember)(&m, i)) 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("%d ", i); 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("\n"); 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 923663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Set up return-value area. */ 924663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Tell the tool this thread is about to run client code 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( start_client_code, tid, bbs_done ); 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(in_generated_code) == False); 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(in_generated_code) = True; 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SCHEDSETJMP( 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jumped, 934663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(disp_run_translations)( 935663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng two_words, 936663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (void*)&tst->arch.vex, 937663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng host_code_addr 938663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ) 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(in_generated_code) == True); 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(in_generated_code) = False; 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 944663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (jumped != (HWord)0) { 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We get here if the client took a fault that caused our signal 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handler to longjmp. */ 947663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(two_words[0] == 0 && two_words[1] == 0); // correct? 948663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng two_words[0] = VG_TRC_FAULT_SIGNAL; 949663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng two_words[1] = 0; 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_signals(); 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 953663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Merge the 32-bit XIndir/miss counters into the 64 bit versions, 954663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng and zero out the 32-bit ones in preparation for the next run of 955663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng generated code. */ 956663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng stats__n_xindirs += (ULong)VG_(stats__n_xindirs_32); 957663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(stats__n_xindirs_32) = 0; 958663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng stats__n_xindir_misses += (ULong)VG_(stats__n_xindir_misses_32); 959663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(stats__n_xindir_misses_32) = 0; 960663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 961663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Inspect the event counter. */ 962663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert((Int)tst->arch.vex.host_EvC_COUNTER >= -1); 963663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(tst->arch.vex.host_EvC_FAILADDR 964663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng == (HWord)VG_(fnptr_to_fnentry)( &VG_(disp_cp_evcheck_fail)) ); 965663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 966663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng done_this_time = *dispatchCtrP - ((Int)tst->arch.vex.host_EvC_COUNTER + 1); 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(done_this_time >= 0); 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbs_done += (ULong)done_this_time; 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 971663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng *dispatchCtrP -= done_this_time; 972663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(*dispatchCtrP >= 0); 973663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Tell the tool this thread has stopped running client code 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( stop_client_code, tid, bbs_done ); 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 977b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (bbs_done >= vgdb_next_poll) { 978b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(clo_vgdb_poll)) 979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vgdb_next_poll = bbs_done + (ULong)VG_(clo_vgdb_poll); 980b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 981b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* value was changed due to gdbserver invocation via ptrace */ 982b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vgdb_next_poll = NO_VGDB_POLL; 983b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(gdbserver_activity) (tid)) 984b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdbserver) (tid); 985b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 987663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* TRC value and possible auxiliary patch-address word are already 988663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng in two_words[0] and [1] respectively, as a result of the call to 989663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(run_innerloop). */ 990663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Stay sane .. */ 991663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (two_words[0] == VG_TRC_CHAIN_ME_TO_SLOW_EP 992663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || two_words[0] == VG_TRC_CHAIN_ME_TO_FAST_EP) { 993663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(two_words[1] != 0); /* we have a legit patch addr */ 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 995663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(two_words[1] == 0); /* nobody messed with it */ 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The scheduler proper. 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handle_tt_miss ( ThreadId tid ) 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool found; 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr ip = VG_(get_IP)(tid); 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Trivial event. Miss in the fast-cache. Do a full 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lookup for it. */ 1011663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng found = VG_(search_transtab)( NULL, NULL, NULL, 1012663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ip, True/*upd_fast_cache*/ ); 1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (UNLIKELY(!found)) { 1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not found; we need to request a translation. */ 1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(translate)( tid, ip, /*debug*/False, 0/*not verbose*/, 1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bbs_done, True/*allow redirection*/ )) { 1017663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng found = VG_(search_transtab)( NULL, NULL, NULL, 1018663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ip, True ); 1019663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert2(found, "handle_tt_miss: missing tt_fast entry"); 1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If VG_(translate)() fails, it's because it had to throw a 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // signal because the client jumped to a bad address. That 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // means that either a signal has been set up for delivery, 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // or the thread has been marked for termination. Either 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // way, we just need to go back into the scheduler loop. 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1031663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic 1032663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid handle_chain_me ( ThreadId tid, void* place_to_chain, Bool toFastEP ) 1033663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{ 1034663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Bool found = False; 1035663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr ip = VG_(get_IP)(tid); 1036663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng UInt to_sNo = (UInt)-1; 1037663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng UInt to_tteNo = (UInt)-1; 1038663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1039663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng found = VG_(search_transtab)( NULL, &to_sNo, &to_tteNo, 1040663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ip, False/*dont_upd_fast_cache*/ ); 1041663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (!found) { 1042663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Not found; we need to request a translation. */ 1043663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (VG_(translate)( tid, ip, /*debug*/False, 0/*not verbose*/, 1044663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng bbs_done, True/*allow redirection*/ )) { 1045663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng found = VG_(search_transtab)( NULL, &to_sNo, &to_tteNo, 1046663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ip, False ); 1047663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert2(found, "handle_chain_me: missing tt_fast entry"); 1048663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } else { 1049663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // If VG_(translate)() fails, it's because it had to throw a 1050663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // signal because the client jumped to a bad address. That 1051663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // means that either a signal has been set up for delivery, 1052663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // or the thread has been marked for termination. Either 1053663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // way, we just need to go back into the scheduler loop. 1054663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 1055663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 1056663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 1057663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(found); 1058663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(to_sNo != -1); 1059663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(to_tteNo != -1); 1060663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1061663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* So, finally we know where to patch through to. Do the patching 1062663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng and update the various admin tables that allow it to be undone 1063663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng in the case that the destination block gets deleted. */ 1064663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(tt_tc_do_chaining)( place_to_chain, 1065663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng to_sNo, to_tteNo, toFastEP ); 1066663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 1067663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handle_syscall(ThreadId tid, UInt trc) 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState * volatile tst = VG_(get_ThreadState)(tid); 1071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov volatile UWord jumped; 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Syscall may or may not block; either way, it will be 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown complete by the time this call returns, and we'll be 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown runnable again. We could take a signal while the 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown syscall runs. */ 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_sanity_level >= 3)) 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_do_sync_check)("(BEFORE SYSCALL)",__FILE__,__LINE__); 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SCHEDSETJMP(tid, jumped, VG_(client_syscall)(tid, trc)); 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_sanity_level >= 3)) 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(am_do_sync_check)("(AFTER SYSCALL)",__FILE__,__LINE__); 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_(is_running_thread)(tid)) 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("tid %d not running; VG_(running_tid)=%d, tid %d status %d\n", 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, VG_(running_tid), tid, tst->status); 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1091b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (jumped != (UWord)0) { 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_signals(); 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(poll_signals)(tid); 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* tid just requested a jump to the noredir version of its current 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown program counter. So make up that translation if needed, run it, 1099663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng and return the resulting thread return code in two_words[]. */ 1100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic 1101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid handle_noredir_jump ( /*OUT*/HWord* two_words, 1102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /*MOD*/Int* dispatchCtrP, 1103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ThreadId tid ) 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Clear return area. */ 1106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng two_words[0] = two_words[1] = 0; 1107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown AddrH hcode = 0; 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr ip = VG_(get_IP)(tid); 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool found = VG_(search_unredir_transtab)( &hcode, ip ); 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!found) { 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Not found; we need to request a translation. */ 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(translate)( tid, ip, /*debug*/False, 0/*not verbose*/, bbs_done, 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown False/*NO REDIRECTION*/ )) { 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown found = VG_(search_unredir_transtab)( &hcode, ip ); 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(found, "unredir translation missing after creation?!"); 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // If VG_(translate)() fails, it's because it had to throw a 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // signal because the client jumped to a bad address. That 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // means that either a signal has been set up for delivery, 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // or the thread has been marked for termination. Either 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // way, we just need to go back into the scheduler loop. 1125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng two_words[0] = VG_TRC_BORING; 1126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return; 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(found); 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(hcode != 0); 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Otherwise run it and return the resulting VG_TRC_* value. */ 1135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(*dispatchCtrP > 0); /* so as to guarantee progress */ 1136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_thread_for_a_while( two_words, dispatchCtrP, tid, 1137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng hcode, True/*use hcode*/ ); 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Run a thread until it wants to exit. 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown We assume that the caller has already called VG_(acquire_BigLock) for 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown us, so we own the VCPU. Also, all signals are blocked. 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVgSchedReturnCode VG_(scheduler) ( ThreadId tid ) 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Holds the remaining size of this thread's "timeslice". */ 1150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int dispatch_ctr = 0; 1151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 1153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov static Bool vgdb_startup_action_done = False; 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_sched)) 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown print_sched_event(tid, "entering VG_(scheduler)"); 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Do vgdb initialization (but once). Only the first (main) task 1159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov starting up will do the below. 1160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Initialize gdbserver earlier than at the first 1161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov thread VG_(scheduler) is causing problems: 1162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * at the end of VG_(scheduler_init_phase2) : 1163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov The main thread is in VgTs_Init state, but in a not yet 1164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov consistent state => the thread cannot be reported to gdb 1165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (e.g. causes an assert in LibVEX_GuestX86_get_eflags when giving 1166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov back the guest registers to gdb). 1167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * at end of valgrind_main, just 1168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov before VG_(main_thread_wrapper_NORETURN)(1) : 1169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov The main thread is still in VgTs_Init state but in a 1170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov more advanced state. However, the thread state is not yet 1171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov completely initialized : a.o., the os_state is not yet fully 1172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov set => the thread is then not properly reported to gdb, 1173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov which is then confused (causing e.g. a duplicate thread be 1174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov shown, without thread id). 1175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * it would be possible to initialize gdbserver "lower" in the 1176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov call stack (e.g. in VG_(main_thread_wrapper_NORETURN)) but 1177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov these are platform dependent and the place at which 1178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov the thread state is completely initialized is not 1179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov specific anymore to the main thread (so a similar "do it only 1180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov once" would be needed). 1181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov => a "once only" initialization here is the best compromise. */ 1183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!vgdb_startup_action_done) { 1184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(tid == 1); // it must be the main thread. 1185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vgdb_startup_action_done = True; 1186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(clo_vgdb) != Vg_VgdbNo) { 1187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* If we have to poll, ensures we do an initial poll at first 1188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov scheduler call. Otherwise, ensure no poll (unless interrupted 1189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov by ptrace). */ 1190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(clo_vgdb_poll)) 1191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(force_vgdb_poll) (); 1192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 1193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(disable_vgdb_poll) (); 1194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert (VG_(dyn_vgdb_error) == VG_(clo_vgdb_error)); 1196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* As we are initializing, VG_(dyn_vgdb_error) can't have been 1197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov changed yet. */ 1198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(gdbserver_prerun_action) (1); 1200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 1201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(disable_vgdb_poll) (); 1202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* set the proper running signal mask */ 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown block_signals(); 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng dispatch_ctr = SCHEDULING_QUANTUM; 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (!VG_(is_exiting)(tid)) { 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(dispatch_ctr >= 0); 1215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (dispatch_ctr == 0) { 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Our slice is done, so yield the CPU to another thread. On 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Linux, this doesn't sleep between sleeping and running, 1219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov since that would take too much time. */ 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 4 July 06: it seems that a zero-length nsleep is needed to 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cause async thread cancellation (canceller.c) to terminate 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in finite time; else it is in some kind of race/starvation 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown situation and completion is arbitrarily delayed (although 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this is not a deadlock). 1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Unfortunately these sleeps cause MPI jobs not to terminate 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sometimes (some kind of livelock). So sleeping once 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown every N opportunities appears to work. */ 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 3 Aug 06: doing sys__nsleep works but crashes some apps. 1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sys_yield also helps the problem, whilst not crashing apps. */ 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(release_BigLock)(tid, VgTs_Yielding, 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "VG_(scheduler):timeslice"); 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ------------ now we don't have The Lock ------------ */ 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(acquire_BigLock)(tid, "VG_(scheduler):timeslice"); 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ------------ now we do have The Lock ------------ */ 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* OK, do some relatively expensive housekeeping stuff */ 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown scheduler_sanity(tid); 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sanity_check_general)(False); 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Look for any pending signals for this thread, and set them up 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for delivery */ 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(poll_signals)(tid); 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(is_exiting)(tid)) 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; /* poll_signals picked up a fatal signal */ 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For stats purposes only. */ 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_scheduling_events_MAJOR++; 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Figure out how many bbs to ask vg_run_innerloop to do. Note 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that it decrements the counter before testing it for zero, so 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that if tst->dispatch_ctr is set to N you get at most N-1 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown iterations. Also this means that tst->dispatch_ctr must 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exceed zero before entering the innerloop. Also also, the 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown decrement is done before the bb is actually run, so you 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown always get at least one decrement even if nothing happens. */ 1262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // FIXME is this right? 1263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng dispatch_ctr = SCHEDULING_QUANTUM; 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* paranoia ... */ 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tst->tid == tid); 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(tst->os_state.lwpid == VG_(gettid)()); 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* For stats purposes only. */ 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_scheduling_events_MINOR++; 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "thread %d: running for %d bbs\n", 1275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng tid, dispatch_ctr - 1 ); 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HWord trc[2]; /* "two_words" */ 1278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng run_thread_for_a_while( &trc[0], 1279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng &dispatch_ctr, 1280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng tid, 0/*ignored*/, False ); 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_sched) && VG_(clo_verbosity) > 2) { 1283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng HChar buf[50]; 1284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(sprintf)(buf, "TRC: %s", name_of_sched_event(trc[0])); 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown print_sched_event(tid, buf); 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (trc[0] == VEX_TRC_JMP_NOREDIR) { 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we got a request to run a no-redir version of 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown something, do so now -- handle_noredir_jump just (creates 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and) runs that one translation. The flip side is that the 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown noredir translation can't itself return another noredir 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown request -- that would be nonsensical. It can, however, 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return VG_TRC_BORING, which just means keep going as 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown normal. */ 1296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Note that the fact that we need to continue with a 1297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng no-redir jump is not recorded anywhere else in this 1298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng thread's state. So we *must* execute the block right now 1299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng -- we can't fail to execute it and later resume with it, 1300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng because by then we'll have forgotten the fact that it 1301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng should be run as no-redir, but will get run as a normal 1302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng potentially-redir'd, hence screwing up. This really ought 1303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng to be cleaned up, by noting in the guest state that the 1304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng next block to be executed should be no-redir. Then we can 1305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng suspend and resume at any point, which isn't the case at 1306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng the moment. */ 1307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng handle_noredir_jump( &trc[0], 1308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng &dispatch_ctr, 1309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng tid ); 1310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(trc[0] != VEX_TRC_JMP_NOREDIR); 1311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* This can't be allowed to happen, since it means the block 1313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng didn't execute, and we have no way to resume-as-noredir 1314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng after we get more timeslice. But I don't think it ever 1315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng can, since handle_noredir_jump will assert if the counter 1316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng is zero on entry. */ 1317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(trc[0] != VG_TRC_INNER_COUNTERZERO); 1318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* A no-redir translation can't return with a chain-me 1320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng request, since chaining in the no-redir cache is too 1321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng complex. */ 1322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(trc[0] != VG_TRC_CHAIN_ME_TO_SLOW_EP 1323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng && trc[0] != VG_TRC_CHAIN_ME_TO_FAST_EP); 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng switch (trc[0]) { 1327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_BORING: 1328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* assisted dispatch, no event. Used by no-redir 1329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng translations to force return to the scheduler. */ 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_TRC_BORING: 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* no special event, just keep going. */ 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_TRC_INNER_FASTMISS: 1335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(dispatch_ctr > 0); 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handle_tt_miss(tid); 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VG_TRC_CHAIN_ME_TO_SLOW_EP: { 1340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (0) VG_(printf)("sched: CHAIN_TO_SLOW_EP: %p\n", (void*)trc[1] ); 1341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng handle_chain_me(tid, (void*)trc[1], False); 1342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 1343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 1344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VG_TRC_CHAIN_ME_TO_FAST_EP: { 1346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (0) VG_(printf)("sched: CHAIN_TO_FAST_EP: %p\n", (void*)trc[1] ); 1347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng handle_chain_me(tid, (void*)trc[1], True); 1348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 1349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 1350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_CLIENTREQ: 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do_client_request(tid); 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_INT128: /* x86-linux */ 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_INT129: /* x86-darwin */ 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_INT130: /* x86-darwin */ 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_SYSCALL: /* amd64-linux, ppc32-linux, amd64-darwin */ 1359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng handle_syscall(tid, trc[0]); 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_sanity_level) > 2) 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sanity_check_general)(True); /* sanity-check every syscall */ 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_YIELD: 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Explicit yield, because this thread is in a spin-lock 1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or something. Only let the thread run for a short while 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown longer. Because swapping to another thread is expensive, 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we're prepared to let this thread eat a little more CPU 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown before swapping to another. That means that short term 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spins waiting for hardware to poke memory won't cause a 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread swap. */ 1372436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (dispatch_ctr > 1000) 1373436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov dispatch_ctr = 1000; 1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_TRC_INNER_COUNTERZERO: 1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Timeslice is out. Let a new thread be scheduled. */ 1378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(dispatch_ctr == 0); 1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_TRC_FAULT_SIGNAL: 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Everything should be set up (either we're exiting, or 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown about to start in a signal handler). */ 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_MAPFAIL: 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Failure of arch-specific address translation (x86/amd64 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown segment override use) */ 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* jrs 2005 03 11: is this correct? */ 1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(synth_fault)(tid); 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_EMWARN: { 1394436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov static Int counts[EmNote_NUMBER]; 1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Bool counts_initted = False; 1396436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VexEmNote ew; 1397436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* what; 1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool show; 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int q; 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!counts_initted) { 1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown counts_initted = True; 1402436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (q = 0; q < EmNote_NUMBER; q++) 1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown counts[q] = 0; 1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1405436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ew = (VexEmNote)VG_(threads)[tid].arch.vex.guest_EMNOTE; 1406436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov what = (ew < 0 || ew >= EmNote_NUMBER) 1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? "unknown (?!)" 1408436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov : LibVEX_EmNote_string(ew); 1409436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov show = (ew < 0 || ew >= EmNote_NUMBER) 1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? True 1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown : counts[ew]++ < 3; 1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (show && VG_(clo_show_emwarns) && !VG_(clo_xml)) { 1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_UserMsg, 1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Emulation warning: unsupported action:\n"); 1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_UserMsg, " %s\n", what); 1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace)( tid, VG_(clo_backtrace_size) ); 1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_EMFAIL: { 1422436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VexEmNote ew; 1423436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* what; 1424436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ew = (VexEmNote)VG_(threads)[tid].arch.vex.guest_EMNOTE; 1425436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov what = (ew < 0 || ew >= EmNote_NUMBER) 1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ? "unknown (?!)" 1427436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov : LibVEX_EmNote_string(ew); 1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_UserMsg, 1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Emulation fatal error -- Valgrind cannot continue:\n"); 1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)( Vg_UserMsg, " %s\n", what); 1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace)( tid, VG_(clo_backtrace_size) ); 1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "\n"); 1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Valgrind has to exit now. Sorry.\n"); 1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "\n"); 1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(1); 1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1439436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case VEX_TRC_JMP_SIGILL: 1440436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(synth_sigill)(tid, VG_(get_IP)(tid)); 1441436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 1442436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SIGTRAP: 1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(synth_sigtrap)(tid); 1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SIGSEGV: 1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(synth_fault)(tid); 1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SIGBUS: 1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(synth_sigbus)(tid); 1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1455436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case VEX_TRC_JMP_SIGFPE_INTDIV: 1456436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(synth_sigfpe)(tid, VKI_FPE_INTDIV); 1457436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 1458436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1459436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case VEX_TRC_JMP_SIGFPE_INTOVF: 1460436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(synth_sigfpe)(tid, VKI_FPE_INTOVF); 1461436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 1462436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng case VEX_TRC_JMP_NODECODE: { 1464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr addr = VG_(get_IP)(tid); 1465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 1466436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (VG_(clo_sigill_diag)) { 1467436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(umsg)( 1468436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "valgrind: Unrecognised instruction at address %#lx.\n", addr); 1469436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size)); 1470eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov# define M(a) VG_(umsg)(a "\n"); 1471eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov M("Your program just tried to execute an instruction that Valgrind" ); 1472eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov M("did not recognise. There are two possible reasons for this." ); 1473eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov M("1. Your program has a bug and erroneously jumped to a non-code" ); 1474eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov M(" location. If you are running Memcheck and you just saw a" ); 1475eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov M(" warning about a bad jump, it's probably your program's fault."); 1476eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov M("2. The instruction is legitimate but Valgrind doesn't handle it,"); 1477eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov M(" i.e. it's Valgrind's fault. If you think this is the case or"); 1478eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov M(" you are not sure, please let us know and we'll try to fix it."); 1479eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov M("Either way, Valgrind will now raise a SIGILL signal which will" ); 1480eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov M("probably kill your program." ); 1481eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov# undef M 1482436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1483eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov# if defined(VGA_s390x) 1484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Now that the complaint is out we need to adjust the guest_IA. The 1485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng reason is that -- after raising the exception -- execution will 1486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng continue with the insn that follows the invalid insn. As the first 1487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 2 bits of the invalid insn determine its length in the usual way, 1488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng we can compute the address of the next insn here and adjust the 1489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng guest_IA accordingly. This adjustment is essential and tested by 1490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng none/tests/s390x/op_exception.c (which would loop forever 1491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng otherwise) */ 1492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng UChar byte = ((UChar *)addr)[0]; 1493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng UInt insn_length = ((((byte >> 6) + 1) >> 1) + 1) << 1; 1494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr next_insn_addr = addr + insn_length; 1495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(set_IP)(tid, next_insn_addr); 1496eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov# endif 1497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(synth_sigill)(tid, addr); 1498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng break; 1499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 1500eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 1501eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov case VEX_TRC_JMP_INVALICACHE: 1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( 1503eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov (Addr64)VG_(threads)[tid].arch.vex.guest_CMSTART, 1504eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov VG_(threads)[tid].arch.vex.guest_CMLEN, 1505eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "scheduler(VEX_TRC_JMP_INVALICACHE)" 1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("dump translations done.\n"); 1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1511eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov case VEX_TRC_JMP_FLUSHDCACHE: { 1512eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov void* start = (void*)VG_(threads)[tid].arch.vex.guest_CMSTART; 1513eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov SizeT len = VG_(threads)[tid].arch.vex.guest_CMLEN; 1514eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov VG_(debugLog)(2, "sched", "flush_dcache(%p, %lu)\n", start, len); 1515eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov VG_(flush_dcache)(start, len); 1516eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov break; 1517eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 1518eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_TRC_INVARIANT_FAILED: 1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This typically happens if, after running generated code, 1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it is detected that host CPU settings (eg, FPU/Vector 1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown control words) are not as they should be. Vex's code 1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown generation specifies the state such control words should 1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown be in on entry to Vex-generated code, and they should be 1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unchanged on exit from it. Failure of this assertion 1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown usually means a bug in Vex's code generation. */ 1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //{ UInt xx; 1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // __asm__ __volatile__ ( 1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // "\t.word 0xEEF12A10\n" // fmrx r2,fpscr 1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // "\tmov %0, r2" : "=r"(xx) : : "r2" ); 1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // VG_(printf)("QQQQ new fpscr = %08x\n", xx); 1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //} 1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(0, "VG_(scheduler), phase 3: " 1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "run_innerloop detected host " 1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "state invariant failure", trc); 1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VEX_TRC_JMP_SYS_SYSENTER: 1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Do whatever simulation is appropriate for an x86 sysenter 1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instruction. Note that it is critical to set this thread's 1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown guest_EIP to point at the code to execute after the 1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sysenter, since Vex-generated code will not have set it -- 1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex does not know what it should be. Vex sets the next 1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown address to zero, so if you don't set guest_EIP, the thread 1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown will jump to zero afterwards and probably die as a result. */ 1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) 1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(0, "VG_(scheduler), phase 3: " 1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "sysenter_x86 on x86-linux is not supported"); 1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_x86_darwin) 1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* return address in client edx */ 1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].arch.vex.guest_EIP 1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = VG_(threads)[tid].arch.vex.guest_EDX; 1552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng handle_syscall(tid, trc[0]); 1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(0, "VG_(scheduler), phase 3: " 1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "sysenter_x86 on non-x86 platform?!?!"); 1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert2(0, "VG_(scheduler), phase 3: " 1561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng "unexpected thread return code (%u)", trc[0]); 1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* NOTREACHED */ 1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } /* switch (trc) */ 1566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1567436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (UNLIKELY(VG_(clo_profyle_sbs)) && VG_(clo_profyle_interval) > 0) 1568436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov maybe_show_sb_profile(); 1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_trace_sched)) 1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown print_sched_event(tid, "exiting VG_(scheduler)"); 1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_exiting)(tid)); 1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return tst->exitreason; 1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This causes all threads to forceably exit. They aren't actually 1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown dead by the time this returns; you need to call 1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(reap_threads)() to wait for them. 1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(nuke_all_threads_except) ( ThreadId me, VgSchedReturnCode src ) 1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid; 1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(me)); 1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (tid = 1; tid < VG_N_THREADS; tid++) { 1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tid == me 1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || VG_(threads)[tid].status == VgTs_Empty) 1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( 1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "VG_(nuke_all_threads_except): nuking tid %d\n", tid); 1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].exitreason = src; 1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (src == VgSrc_FatalSig) 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].os_state.fatalsig = VKI_SIGKILL; 1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_thread_out_of_syscall)(tid); 1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Specifying shadow register values 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGA_x86) 1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_CLREQ_ARGS guest_EAX 1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_CLREQ_RET guest_EDX 1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGA_amd64) 1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_CLREQ_ARGS guest_RAX 1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_CLREQ_RET guest_RDX 1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGA_ppc32) || defined(VGA_ppc64) 1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_CLREQ_ARGS guest_GPR4 1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_CLREQ_RET guest_GPR3 1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGA_arm) 1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_CLREQ_ARGS guest_R4 1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define VG_CLREQ_RET guest_R3 1623436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGA_arm64) 1624436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# define VG_CLREQ_ARGS guest_X4 1625436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# define VG_CLREQ_RET guest_X3 1626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined (VGA_s390x) 1627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define VG_CLREQ_ARGS guest_r2 1628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# define VG_CLREQ_RET guest_r3 1629436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGA_mips32) || defined(VGA_mips64) 1630663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# define VG_CLREQ_ARGS guest_r12 1631663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# define VG_CLREQ_RET guest_r11 1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown arch 1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CLREQ_ARGS(regs) ((regs).vex.VG_CLREQ_ARGS) 1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CLREQ_RET(regs) ((regs).vex.VG_CLREQ_RET) 1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define O_CLREQ_RET (offsetof(VexGuestArchState, VG_CLREQ_RET)) 1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// These macros write a value to a client's thread register, and tell the 1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// tool that it's happened (if necessary). 1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SET_CLREQ_RETVAL(zztid, zzval) \ 1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { CLREQ_RET(VG_(threads)[zztid].arch) = (zzval); \ 1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write, \ 1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Vg_CoreClientReq, zztid, O_CLREQ_RET, sizeof(UWord)); \ 1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SET_CLCALL_RETVAL(zztid, zzval, f) \ 1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { CLREQ_RET(VG_(threads)[zztid].arch) = (zzval); \ 1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_TRACK( post_reg_write_clientcall_return, \ 1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zztid, O_CLREQ_RET, sizeof(UWord), f); \ 1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Handle client requests. 1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// OS-specific(?) client requests 1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool os_client_request(ThreadId tid, UWord *args) 1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool handled = True; 1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_running_thread)(tid)); 1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(args[0]) { 1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__LIBC_FREERES_DONE: 1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is equivalent to an exit() syscall, but we don't set the 1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exitcode (since it might already be set) */ 1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0 || VG_(clo_trace_syscalls) || VG_(clo_trace_sched)) 1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "__libc_freeres() done; really quitting!\n"); 1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].exitreason = VgSrc_ExitThread; 1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handled = False; 1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return handled; 1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1686436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Write out a client message, possibly including a back trace. Return 1687436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov the number of characters written. In case of XML output, the format 1688436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov string as well as any arguments it requires will be XML'ified. 1689436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov I.e. special characters such as the angle brackets will be translated 1690436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov into proper escape sequences. */ 1691436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic 1692436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovInt print_client_message( ThreadId tid, const HChar *format, 1693436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov va_list *vargsp, Bool include_backtrace) 1694436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 1695436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int count; 1696436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1697436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (VG_(clo_xml)) { 1698436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Translate the format string as follows: 1699436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov < --> < 1700436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov > --> > 1701436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov & --> & 1702436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov %s --> %pS 1703436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Yes, yes, it's simplified but in synch with 1704436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov myvprintf_str_XML_simplistic and VG_(debugLog_vprintf). 1705436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 1706436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1707436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Allocate a buffer that is for sure large enough. */ 1708436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar xml_format[VG_(strlen)(format) * 5 + 1]; 1709436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1710436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar *p; 1711436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar *q = xml_format; 1712436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1713436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (p = format; *p; ++p) { 1714436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (*p) { 1715436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case '<': VG_(strcpy)(q, "<"); q += 4; break; 1716436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case '>': VG_(strcpy)(q, ">"); q += 4; break; 1717436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case '&': VG_(strcpy)(q, "&"); q += 5; break; 1718436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case '%': 1719436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Careful: make sure %%s stays %%s */ 1720436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *q++ = *p++; 1721436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (*p == 's') { 1722436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *q++ = 'p'; 1723436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *q++ = 'S'; 1724436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 1725436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *q++ = *p; 1726436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1727436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 1728436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1729436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov default: 1730436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *q++ = *p; 1731436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 1732436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1733436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1734436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *q = '\0'; 1735436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1736436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(printf_xml)( "<clientmsg>\n" ); 1737436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(printf_xml)( " <tid>%d</tid>\n", tid ); 1738436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(printf_xml)( " <text>" ); 1739436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov count = VG_(vprintf_xml)( xml_format, *vargsp ); 1740436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(printf_xml)( " </text>\n" ); 1741436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 1742436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov count = VG_(vmessage)( Vg_ClientMsg, format, *vargsp ); 1743436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(message_flush)(); 1744436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1745436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1746436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (include_backtrace) 1747436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(get_and_pp_StackTrace)( tid, VG_(clo_backtrace_size) ); 1748436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1749436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (VG_(clo_xml)) 1750436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(printf_xml)( "</clientmsg>\n" ); 1751436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1752436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return count; 1753436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 1754436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1755436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do a client request for the thread tid. After the request, tid may 1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown or may not still be runnable; if not, the scheduler will have to 1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown choose a new thread to run. 1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid do_client_request ( ThreadId tid ) 1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord* arg = (UWord*)(CLREQ_ARGS(VG_(threads)[tid].arch)); 1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord req_no = arg[0]; 1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) 1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("req no = 0x%llx, arg = %p\n", (ULong)req_no, arg); 1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (req_no) { 1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__CLIENT_CALL0: { 1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord (*f)(ThreadId) = (void*)arg[1]; 1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (f == NULL) 1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "VG_USERREQ__CLIENT_CALL0: func=%p\n", f); 1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLCALL_RETVAL(tid, f ( tid ), (Addr)f); 1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__CLIENT_CALL1: { 1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord (*f)(ThreadId, UWord) = (void*)arg[1]; 1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (f == NULL) 1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "VG_USERREQ__CLIENT_CALL1: func=%p\n", f); 1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLCALL_RETVAL(tid, f ( tid, arg[2] ), (Addr)f ); 1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__CLIENT_CALL2: { 1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord (*f)(ThreadId, UWord, UWord) = (void*)arg[1]; 1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (f == NULL) 1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "VG_USERREQ__CLIENT_CALL2: func=%p\n", f); 1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLCALL_RETVAL(tid, f ( tid, arg[2], arg[3] ), (Addr)f ); 1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__CLIENT_CALL3: { 1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord (*f)(ThreadId, UWord, UWord, UWord) = (void*)arg[1]; 1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (f == NULL) 1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, "VG_USERREQ__CLIENT_CALL3: func=%p\n", f); 1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLCALL_RETVAL(tid, f ( tid, arg[2], arg[3], arg[4] ), (Addr)f ); 1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Nb: this looks like a circular definition, because it kind of is. 1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // See comment in valgrind.h to understand what's going on. 1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__RUNNING_ON_VALGRIND: 1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL(tid, RUNNING_ON_VALGRIND+1); 1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__PRINTF: { 1810436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* format = (HChar *)arg[1]; 1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* JRS 2010-Jan-28: this is DEPRECATED; use the 1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _VALIST_BY_REF version instead */ 1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sizeof(va_list) != sizeof(UWord)) 1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto va_list_casting_error_NORETURN; 1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown union { 1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown va_list vargs; 1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long uw; 1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } u; 1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown u.uw = (unsigned long)arg[2]; 1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int count = 1821436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov print_client_message( tid, format, &u.vargs, 1822436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* include_backtrace */ False ); 1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, count ); 1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__PRINTF_BACKTRACE: { 1828436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* format = (HChar *)arg[1]; 1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* JRS 2010-Jan-28: this is DEPRECATED; use the 1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _VALIST_BY_REF version instead */ 1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sizeof(va_list) != sizeof(UWord)) 1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto va_list_casting_error_NORETURN; 1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown union { 1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown va_list vargs; 1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long uw; 1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } u; 1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown u.uw = (unsigned long)arg[2]; 1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int count = 1839436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov print_client_message( tid, format, &u.vargs, 1840436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* include_backtrace */ True ); 1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, count ); 1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__PRINTF_VALIST_BY_REF: { 1846436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* format = (HChar *)arg[1]; 1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown va_list* vargsp = (va_list*)arg[2]; 1848436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Int count = 1849436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov print_client_message( tid, format, vargsp, 1850436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* include_backtrace */ False ); 1851436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, count ); 1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF: { 1857436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const HChar* format = (HChar *)arg[1]; 1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown va_list* vargsp = (va_list*)arg[2]; 1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int count = 1860436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov print_client_message( tid, format, vargsp, 1861436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* include_backtrace */ True ); 1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, count ); 1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__INTERNAL_PRINTF_VALIST_BY_REF: { 1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown va_list* vargsp = (va_list*)arg[2]; 1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int count = 1869436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(vmessage)( Vg_DebugMsg, (HChar *)arg[1], *vargsp ); 1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message_flush)(); 1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, count ); 1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__ADD_IFUNC_TARGET: { 1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(redir_add_ifunc_target)( arg[1], arg[2] ); 1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, 0); 1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; } 1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__STACK_REGISTER: { 1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord sid = VG_(register_stack)((Addr)arg[1], (Addr)arg[2]); 1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, sid ); 1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; } 1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__STACK_DEREGISTER: { 1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(deregister_stack)(arg[1]); 1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ 1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; } 1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__STACK_CHANGE: { 1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(change_stack)(arg[1], (Addr)arg[2], (Addr)arg[3]); 1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ 1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; } 1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__GET_MALLOCFUNCS: { 1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vg_mallocfunc_info *info = (struct vg_mallocfunc_info *)arg[1]; 1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl_malloc = VG_(tdict).tool_malloc; 1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl_calloc = VG_(tdict).tool_calloc; 1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl_realloc = VG_(tdict).tool_realloc; 1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl_memalign = VG_(tdict).tool_memalign; 1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl___builtin_new = VG_(tdict).tool___builtin_new; 1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl___builtin_vec_new = VG_(tdict).tool___builtin_vec_new; 1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl_free = VG_(tdict).tool_free; 1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl___builtin_delete = VG_(tdict).tool___builtin_delete; 1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl___builtin_vec_delete = VG_(tdict).tool___builtin_vec_delete; 1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->tl_malloc_usable_size = VG_(tdict).tool_malloc_usable_size; 1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->mallinfo = VG_(mallinfo); 1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info->clo_trace_malloc = VG_(clo_trace_malloc); 1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ 1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Requests from the client program */ 1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__DISCARD_TRANSLATIONS: 1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 2) 1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)( "client request: DISCARD_TRANSLATIONS," 1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " addr %p, len %lu\n", 1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (void*)arg[1], arg[2] ); 1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(discard_translations)( 1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg[1], arg[2], "scheduler(VG_USERREQ__DISCARD_TRANSLATIONS)" 1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ 1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__COUNT_ERRORS: 1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, VG_(get_n_errs_found)() ); 1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__LOAD_PDB_DEBUGINFO: 1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(di_notify_pdb_debuginfo)( arg[1], arg[2], arg[3], arg[4] ); 1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ 1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__MAP_IP_TO_SRCLOC: { 1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr ip = arg[1]; 1943436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar* buf64 = (HChar*)arg[2]; 1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)(buf64, 0, 64); 1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt linenum = 0; 1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool ok = VG_(get_filename_linenum)( 1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ip, &buf64[0], 50, NULL, 0, NULL, &linenum 1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ok) { 1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Find the terminating zero in the first 50 bytes. */ 1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt i; 1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < 50; i++) { 1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (buf64[i] == 0) 1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We must find a zero somewhere in 0 .. 49. Else 1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_filename_linenum) is not properly zero 1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown terminating. */ 1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(i < 50); 1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(&buf64[i], ":%u", linenum); 1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown buf64[0] = 0; 1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ 1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case VG_USERREQ__CHANGE_ERR_DISABLEMENT: { 1971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Word delta = arg[1]; 1972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(delta == 1 || delta == -1); 1973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ThreadState* tst = VG_(get_ThreadState)(tid); 1974b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(tst); 1975b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (delta == 1 && tst->err_disablement_level < 0xFFFFFFFF) { 1976b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tst->err_disablement_level++; 1977b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1978b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov else 1979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (delta == -1 && tst->err_disablement_level > 0) { 1980b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tst->err_disablement_level--; 1981b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1982b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ 1983b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov break; 1984b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 1985b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1986436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case VG_USERREQ__GDB_MONITOR_COMMAND: { 1987436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UWord ret; 1988436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ret = (UWord) VG_(client_monitor_command) ((HChar*)arg[1]); 1989436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SET_CLREQ_RETVAL(tid, ret); 1990436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 1991436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1992436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__MALLOCLIKE_BLOCK: 1994b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov case VG_USERREQ__RESIZEINPLACE_BLOCK: 1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case VG_USERREQ__FREELIKE_BLOCK: 1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Ignore them if the addr is NULL; otherwise pass onto the tool. 1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!arg[1]) { 1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ 1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto my_default; 2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2004436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov case VG_USERREQ__VEX_INIT_FOR_IRI: 2005436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov LibVEX_InitIRI ( (IRICB *)arg[1] ); 2006436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; 2007436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown my_default: 2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (os_client_request(tid, arg)) { 2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // do nothing, os_client_request() handled it 2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if (VG_(needs).client_requests) { 2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UWord ret; 2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 2) 2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("client request: code %lx, addr %p, len %lu\n", 2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg[0], (void*)arg[1], arg[2] ); 2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( VG_TDICT_CALL(tool_handle_client_request, tid, arg, &ret) ) 2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SET_CLREQ_RETVAL(tid, ret); 2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static Bool whined = False; 2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!whined && VG_(clo_verbosity) > 2) { 2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Allow for requests in core, but defined by tools, which 2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // have 0 and 0 in their two high bytes. 2027436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar c1 = (arg[0] >> 24) & 0xff; 2028436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HChar c2 = (arg[0] >> 16) & 0xff; 2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (c1 == 0) c1 = '_'; 2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (c2 == 0) c2 = '_'; 2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Warning:\n" 2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " unhandled client request: 0x%lx (%c%c+0x%lx). Perhaps\n" 2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " VG_(needs).client_requests should be set?\n", 2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown arg[0], c1, c2, arg[0] & 0xffff); 2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown whined = True; 2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown va_list_casting_error_NORETURN: 2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)( 2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Valgrind: fatal error - cannot continue: use of the deprecated\n" 2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "client requests VG_USERREQ__PRINTF or VG_USERREQ__PRINTF_BACKTRACE\n" 2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "on a platform where they cannot be supported. Please use the\n" 2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "equivalent _VALIST_BY_REF versions instead.\n" 2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\n" 2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "This is a binary-incompatible change in Valgrind's client request\n" 2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "mechanism. It is unfortunate, but difficult to avoid. End-users\n" 2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "are expected to almost never see this message. The only case in\n" 2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "which you might see this message is if your code uses the macros\n" 2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "VALGRIND_PRINTF or VALGRIND_PRINTF_BACKTRACE. If so, you will need\n" 2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "to recompile such code, using the header files from this version of\n" 2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Valgrind, and not any previous version.\n" 2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\n" 2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "If you see this mesage in any other circumstances, it is probably\n" 2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "a bug in Valgrind. In this case, please file a bug report at\n" 2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\n" 2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " http://www.valgrind.org/support/bug_reports.html\n" 2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\n" 2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Will now abort.\n" 2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Sanity checking (permanently engaged) 2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Internal consistency checks on the sched structures. */ 2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid scheduler_sanity ( ThreadId tid ) 2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool bad = False; 2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int lwpid = VG_(gettid)(); 2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_(is_running_thread)(tid)) { 2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Thread %d is supposed to be running, " 2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "but doesn't own the_BigLock (owned by %d)\n", 2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, VG_(running_tid)); 2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad = True; 2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (lwpid != VG_(threads)[tid].os_state.lwpid) { 2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Thread %d supposed to be in LWP %d, but we're actually %d\n", 2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, VG_(threads)[tid].os_state.lwpid, VG_(gettid)()); 2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad = True; 2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2095663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (lwpid != ML_(get_sched_lock_owner)(the_BigLock)) { 2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Thread (LWPID) %d doesn't own the_BigLock\n", 2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid); 2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad = True; 2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2102436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (0) { 2103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* Periodically show the state of all threads, for debugging 2104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov purposes. */ 2105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov static UInt lasttime = 0; 2106436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov UInt now; 2107436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov now = VG_(read_millisecond_timer)(); 2108436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if ((!bad) && (lasttime + 4000/*ms*/ <= now)) { 2109436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov lasttime = now; 2110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VG_(printf)("\n------------ Sched State at %d ms ------------\n", 2111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (Int)now); 2112eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov VG_(show_sched_status)(True, // host_stacktrace 2113eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov True, // valgrind_stack_usage 2114eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov True); // exited_threads); 2115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* core_panic also shows the sched status, which is why we don't 2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown show it above if bad==True. */ 2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bad) 2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)("scheduler_sanity: failed"); 2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(sanity_check_general) ( Bool force_expensive ) 2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid; 2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UInt next_slow_check_at = 1; 2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UInt slow_check_interval = 25; 2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_sanity_level) < 1) return; 2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- First do all the tests that we can do quickly. ---*/ 2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sanity_fast_count++; 2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check stuff pertaining to the memory check system. */ 2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check that nobody has spuriously claimed that the first or 2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown last 16 pages of memory have become accessible [...] */ 2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(needs).sanity_checks) { 2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_TDICT_CALL(tool_cheap_sanity_check)); 2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* --- Now some more expensive checks. ---*/ 2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Once every now and again, check some more expensive stuff. 2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Gradually increase the interval between such checks so as not to 2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown burden long-running programs too much. */ 2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ( force_expensive 2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || VG_(clo_sanity_level) > 1 2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || (VG_(clo_sanity_level) == 1 2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && sanity_fast_count == next_slow_check_at)) { 2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (0) VG_(printf)("SLOW at %d\n", sanity_fast_count-1); 2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown next_slow_check_at = sanity_fast_count - 1 + slow_check_interval; 2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown slow_check_interval++; 2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sanity_slow_count++; 2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(needs).sanity_checks) { 2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_TDICT_CALL(tool_expensive_sanity_check)); 2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Look for stack overruns. Visit all threads. */ 2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (tid = 1; tid < VG_N_THREADS; tid++) { 2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT remains; 2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VgStack* stack; 2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(threads)[tid].status == VgTs_Empty || 2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(threads)[tid].status == VgTs_Zombie) 2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack 2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = (VgStack*) 2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_ThreadState)(tid)->os_state.valgrind_stack_base; 2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT limit 2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = 4096; // Let's say. Checking more causes lots of L2 misses. 2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown remains 2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown = VG_(am_get_VgStack_unused_szB)(stack, limit); 2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (remains < limit) 2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "WARNING: Thread %d is within %ld bytes " 2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "of running out of stack!\n", 2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, remains); 2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_sanity_level) > 1) { 2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Check sanity of the low-level memory manager. Note that bugs 2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in the client's code can cause this to fail, so we don't do 2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this check unless specially asked for. And because it's 2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown potentially very expensive. */ 2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sanity_check_malloc_all)(); 2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 2201