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         <  -->  &lt;
1700436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         >  -->  &gt;
1701436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         &  -->  &amp;
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, "&lt;");  q += 4; break;
1716436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case '>': VG_(strcpy)(q, "&gt;");  q += 4; break;
1717436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         case '&': VG_(strcpy)(q, "&amp;"); 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