blob: cef0f0290b6aa2731efebe78378843877c02f202 [file] [log] [blame]
sewardje663cb92002-04-12 10:26:32 +00001
2/*--------------------------------------------------------------------*/
njn278b3d62005-05-30 23:20:51 +00003/*--- Thread scheduling. scheduler.c ---*/
sewardje663cb92002-04-12 10:26:32 +00004/*--------------------------------------------------------------------*/
5
6/*
sewardjb5f6f512005-03-10 23:59:00 +00007 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
sewardje663cb92002-04-12 10:26:32 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Julian Seward
sewardje663cb92002-04-12 10:26:32 +000011 jseward@acm.org
sewardje663cb92002-04-12 10:26:32 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardje663cb92002-04-12 10:26:32 +000029*/
30
sewardjb5f6f512005-03-10 23:59:00 +000031/*
32 Overview
33
34 Valgrind tries to emulate the kernel's threading as closely as
35 possible. The client does all threading via the normal syscalls
36 (on Linux: clone, etc). Valgrind emulates this by creating exactly
37 the same process structure as would be created without Valgrind.
38 There are no extra threads.
39
40 The main difference is that Valgrind only allows one client thread
41 to run at once. This is controlled with the VCPU semaphore,
42 "run_sema". Any time a thread wants to run client code or
43 manipulate any shared state (which is anything other than its own
44 ThreadState entry), it must hold the run_sema.
45
46 When a thread is about to block in a blocking syscall, it releases
47 run_sema, and re-takes it when it becomes runnable again (either
48 because the syscall finished, or we took a signal).
49
50 VG_(scheduler) therefore runs in each thread. It returns only when
51 the thread is exiting, either because it exited itself, or it was
52 told to exit by another thread.
53
54 This file is almost entirely OS-independent. The details of how
55 the OS handles threading and signalling are abstracted away and
njn12771092005-06-18 02:18:04 +000056 implemented elsewhere. [Some of the functions have worked their
57 way back for the moment, until we do an OS port in earnest...]
sewardjb5f6f512005-03-10 23:59:00 +000058 */
59
njn12771092005-06-18 02:18:04 +000060#include "valgrind.h" // for VG_USERREQ__*
61#include "coregrind.h" // for VG_USERREQ__*
sewardje663cb92002-04-12 10:26:32 +000062
njnc7561b92005-06-19 01:24:32 +000063#include "pub_core_basics.h"
64#include "pub_core_threadstate.h"
njn899ce732005-06-21 00:28:11 +000065#include "pub_core_debuginfo.h" // Needed for pub_core_aspacemgr :(
njn04e16982005-05-31 00:23:43 +000066#include "pub_core_aspacemgr.h"
njn36b66df2005-05-12 05:13:04 +000067#include "pub_core_dispatch.h"
njnf4c50162005-06-20 14:18:12 +000068#include "pub_core_errormgr.h" // For VG_(get_n_errs_found)()
njn97405b22005-06-02 03:39:33 +000069#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000070#include "pub_core_libcassert.h"
njn36a20fa2005-06-03 03:08:39 +000071#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000072#include "pub_core_libcproc.h"
njnde62cbf2005-06-10 22:08:14 +000073#include "pub_core_libcsignal.h"
njnf536bbb2005-06-13 04:21:38 +000074#include "pub_core_machine.h"
njnaf1d7df2005-06-11 01:31:52 +000075#include "pub_core_mallocfree.h"
njn20242342005-05-16 23:31:24 +000076#include "pub_core_options.h"
njn31513b42005-06-01 03:09:59 +000077#include "pub_core_profile.h"
njn717cde52005-05-10 02:47:21 +000078#include "pub_core_replacemalloc.h"
njn278b3d62005-05-30 23:20:51 +000079#include "pub_core_scheduler.h"
njn0c246472005-05-31 01:00:08 +000080#include "pub_core_signals.h"
njn945ed2e2005-06-24 03:28:30 +000081#include "pub_core_stacks.h"
njnf4c50162005-06-20 14:18:12 +000082#include "pub_core_stacktrace.h" // For VG_(get_and_pp_StackTrace)()
njn9abd6082005-06-17 21:31:45 +000083#include "pub_core_syscall.h"
njnc1b01812005-06-17 22:19:06 +000084#include "pub_core_syswrap.h"
njn43b9a8a2005-05-10 04:37:01 +000085#include "pub_core_tooliface.h"
njnf4c50162005-06-20 14:18:12 +000086#include "pub_core_translate.h" // For VG_(translate)()
njn8bddf582005-05-13 23:40:55 +000087#include "pub_core_transtab.h"
njn3c660b62005-05-13 22:18:47 +000088#include "vki_unistd.h"
njn278b3d62005-05-30 23:20:51 +000089#include "priv_sema.h"
sewardje663cb92002-04-12 10:26:32 +000090
91/* ---------------------------------------------------------------------
92 Types and globals for the scheduler.
93 ------------------------------------------------------------------ */
94
njnc7561b92005-06-19 01:24:32 +000095/* ThreadId and ThreadState are defined elsewhere*/
sewardje663cb92002-04-12 10:26:32 +000096
njn14319cc2005-03-13 06:26:22 +000097/* Defines the thread-scheduling timeslice, in terms of the number of
98 basic blocks we attempt to run each thread for. Smaller values
99 give finer interleaving but much increased scheduling overheads. */
100#define SCHEDULING_QUANTUM 50000
101
sewardjb5f6f512005-03-10 23:59:00 +0000102/* If true, a fault is Valgrind-internal (ie, a bug) */
103Bool VG_(my_fault) = True;
njn25e49d8e72002-09-23 09:36:25 +0000104
njnde583aa2005-05-11 18:57:02 +0000105/* Counts downwards in VG_(run_innerloop). */
106UInt VG_(dispatch_ctr);
107
njn394213a2005-06-19 18:38:24 +0000108/* 64-bit counter for the number of basic blocks done. */
109static ULong bbs_done = 0;
110
sewardje663cb92002-04-12 10:26:32 +0000111/* Forwards */
sewardjb5f6f512005-03-10 23:59:00 +0000112static void do_client_request ( ThreadId tid );
113static void scheduler_sanity ( ThreadId tid );
114static void mostly_clear_thread_record ( ThreadId tid );
sewardjd140e442002-05-29 01:21:19 +0000115
nethercote844e7122004-08-02 15:27:22 +0000116/* Stats. */
117static UInt n_scheduling_events_MINOR = 0;
118static UInt n_scheduling_events_MAJOR = 0;
119
njn6676d5b2005-06-19 18:49:19 +0000120/* Sanity checking counts. */
121static UInt sanity_fast_count = 0;
122static UInt sanity_slow_count = 0;
sewardjb5f6f512005-03-10 23:59:00 +0000123
nethercote844e7122004-08-02 15:27:22 +0000124void VG_(print_scheduler_stats)(void)
125{
126 VG_(message)(Vg_DebugMsg,
njn394213a2005-06-19 18:38:24 +0000127 "scheduler: %llu jumps (bb entries).", bbs_done );
128 VG_(message)(Vg_DebugMsg,
129 "scheduler: %d/%d major/minor sched events.",
nethercote844e7122004-08-02 15:27:22 +0000130 n_scheduling_events_MAJOR, n_scheduling_events_MINOR);
njn6676d5b2005-06-19 18:49:19 +0000131 VG_(message)(Vg_DebugMsg,
132 " sanity: %d cheap, %d expensive checks.",
133 sanity_fast_count, sanity_slow_count );
nethercote844e7122004-08-02 15:27:22 +0000134}
135
sewardjb5f6f512005-03-10 23:59:00 +0000136/* CPU semaphore, so that threads can run exclusively */
137static vg_sema_t run_sema;
sewardjb5f6f512005-03-10 23:59:00 +0000138
139
sewardje663cb92002-04-12 10:26:32 +0000140/* ---------------------------------------------------------------------
141 Helper functions for the scheduler.
142 ------------------------------------------------------------------ */
143
sewardje663cb92002-04-12 10:26:32 +0000144static
145void print_sched_event ( ThreadId tid, Char* what )
146{
sewardj45b4b372002-04-16 22:50:32 +0000147 VG_(message)(Vg_DebugMsg, " SCHED[%d]: %s", tid, what );
sewardj8937c812002-04-12 20:12:20 +0000148}
149
sewardj8937c812002-04-12 20:12:20 +0000150static
sewardjb5f6f512005-03-10 23:59:00 +0000151HChar* name_of_sched_event ( UInt event )
sewardje663cb92002-04-12 10:26:32 +0000152{
153 switch (event) {
sewardjd79ef682004-11-26 13:25:17 +0000154 case VEX_TRC_JMP_SYSCALL: return "SYSCALL";
155 case VEX_TRC_JMP_CLIENTREQ: return "CLIENTREQ";
156 case VEX_TRC_JMP_YIELD: return "YIELD";
sewardj45f02c42005-02-05 18:27:14 +0000157 case VEX_TRC_JMP_NODECODE: return "NODECODE";
sewardje663cb92002-04-12 10:26:32 +0000158 case VG_TRC_INNER_COUNTERZERO: return "COUNTERZERO";
159 case VG_TRC_INNER_FASTMISS: return "FASTMISS";
sewardjb5f6f512005-03-10 23:59:00 +0000160 case VG_TRC_FAULT_SIGNAL: return "FAULTSIGNAL";
sewardje663cb92002-04-12 10:26:32 +0000161 default: return "??UNKNOWN??";
162 }
163}
164
sewardje663cb92002-04-12 10:26:32 +0000165/* Allocate a completely empty ThreadState record. */
sewardjb5f6f512005-03-10 23:59:00 +0000166ThreadId VG_(alloc_ThreadState) ( void )
sewardje663cb92002-04-12 10:26:32 +0000167{
168 Int i;
sewardj6072c362002-04-19 14:40:57 +0000169 for (i = 1; i < VG_N_THREADS; i++) {
sewardjb5f6f512005-03-10 23:59:00 +0000170 if (VG_(threads)[i].status == VgTs_Empty) {
171 VG_(threads)[i].status = VgTs_Init;
172 VG_(threads)[i].exitreason = VgSrc_None;
sewardje663cb92002-04-12 10:26:32 +0000173 return i;
sewardjb5f6f512005-03-10 23:59:00 +0000174 }
sewardje663cb92002-04-12 10:26:32 +0000175 }
176 VG_(printf)("vg_alloc_ThreadState: no free slots available\n");
177 VG_(printf)("Increase VG_N_THREADS, rebuild and try again.\n");
njne427a662002-10-02 11:08:25 +0000178 VG_(core_panic)("VG_N_THREADS is too low");
sewardje663cb92002-04-12 10:26:32 +0000179 /*NOTREACHED*/
180}
181
sewardjb5f6f512005-03-10 23:59:00 +0000182/*
183 Mark a thread as Runnable. This will block until the run_sema is
184 available, so that we get exclusive access to all the shared
185 structures and the CPU. Up until we get the sema, we must not
186 touch any shared state.
187
188 When this returns, we'll actually be running.
189 */
190void VG_(set_running)(ThreadId tid)
191{
192 ThreadState *tst = VG_(get_ThreadState)(tid);
193
194 vg_assert(tst->status != VgTs_Runnable);
195
196 tst->status = VgTs_Runnable;
197
sewardj7eb7c582005-06-23 01:02:53 +0000198 ML_(sema_down)(&run_sema);
njnc7561b92005-06-19 01:24:32 +0000199 if (VG_(running_tid) != VG_INVALID_THREADID)
200 VG_(printf)("tid %d found %d running\n", tid, VG_(running_tid));
201 vg_assert(VG_(running_tid) == VG_INVALID_THREADID);
202 VG_(running_tid) = tid;
sewardjb5f6f512005-03-10 23:59:00 +0000203
204 if (VG_(clo_trace_sched))
205 print_sched_event(tid, "now running");
tomdeca43f2005-07-27 23:04:28 +0000206
207 // While thre modeling is disable, issue thread_run events here
208 // VG_(tm_thread_switchto)(tid);
209 VG_TRACK( thread_run, tid );
sewardjb5f6f512005-03-10 23:59:00 +0000210}
211
sewardjb5f6f512005-03-10 23:59:00 +0000212/*
213 Set a thread into a sleeping state, and give up exclusive access to
214 the CPU. On return, the thread must be prepared to block until it
215 is ready to run again (generally this means blocking in a syscall,
216 but it may mean that we remain in a Runnable state and we're just
217 yielding the CPU to another thread).
218 */
219void VG_(set_sleeping)(ThreadId tid, ThreadStatus sleepstate)
220{
221 ThreadState *tst = VG_(get_ThreadState)(tid);
222
223 vg_assert(tst->status == VgTs_Runnable);
224
225 vg_assert(sleepstate == VgTs_WaitSys ||
226 sleepstate == VgTs_Yielding);
227
228 tst->status = sleepstate;
229
njnc7561b92005-06-19 01:24:32 +0000230 vg_assert(VG_(running_tid) == tid);
231 VG_(running_tid) = VG_INVALID_THREADID;
sewardjb5f6f512005-03-10 23:59:00 +0000232
233 /* Release the run_sema; this will reschedule any runnable
234 thread. */
sewardj7eb7c582005-06-23 01:02:53 +0000235 ML_(sema_up)(&run_sema);
sewardjb5f6f512005-03-10 23:59:00 +0000236
237 if (VG_(clo_trace_sched)) {
238 Char buf[50];
sewardja8d8e232005-06-07 20:04:56 +0000239 VG_(sprintf)(buf, "now sleeping in state %s",
njnc7561b92005-06-19 01:24:32 +0000240 VG_(name_of_ThreadStatus)(sleepstate));
sewardjb5f6f512005-03-10 23:59:00 +0000241 print_sched_event(tid, buf);
nethercote75d26242004-08-01 22:59:18 +0000242 }
243}
244
sewardjb5f6f512005-03-10 23:59:00 +0000245/* Clear out the ThreadState and release the semaphore. Leaves the
246 ThreadState in VgTs_Zombie state, so that it doesn't get
247 reallocated until the caller is really ready. */
248void VG_(exit_thread)(ThreadId tid)
249{
250 vg_assert(VG_(is_valid_tid)(tid));
251 vg_assert(VG_(is_running_thread)(tid));
252 vg_assert(VG_(is_exiting)(tid));
253
sewardjb5f6f512005-03-10 23:59:00 +0000254 mostly_clear_thread_record(tid);
njnc7561b92005-06-19 01:24:32 +0000255 VG_(running_tid) = VG_INVALID_THREADID;
sewardjb5f6f512005-03-10 23:59:00 +0000256
257 /* There should still be a valid exitreason for this thread */
258 vg_assert(VG_(threads)[tid].exitreason != VgSrc_None);
259
sewardj7eb7c582005-06-23 01:02:53 +0000260 ML_(sema_up)(&run_sema);
sewardjb5f6f512005-03-10 23:59:00 +0000261}
262
263/* Kill a thread. This interrupts whatever a thread is doing, and
264 makes it exit ASAP. This does not set the exitreason or
265 exitcode. */
266void VG_(kill_thread)(ThreadId tid)
267{
268 vg_assert(VG_(is_valid_tid)(tid));
269 vg_assert(!VG_(is_running_thread)(tid));
270 vg_assert(VG_(is_exiting)(tid));
271
272 if (VG_(threads)[tid].status == VgTs_WaitSys) {
273 if (VG_(clo_trace_signals))
274 VG_(message)(Vg_DebugMsg, "kill_thread zaps tid %d lwp %d",
275 tid, VG_(threads)[tid].os_state.lwpid);
njn351d0062005-06-21 22:23:59 +0000276 VG_(tkill)(VG_(threads)[tid].os_state.lwpid, VG_SIGVGKILL);
sewardjb5f6f512005-03-10 23:59:00 +0000277 }
278}
279
280/*
281 Yield the CPU for a short time to let some other thread run.
282 */
283void VG_(vg_yield)(void)
284{
285 struct vki_timespec ts = { 0, 1 };
njnc7561b92005-06-19 01:24:32 +0000286 ThreadId tid = VG_(running_tid);
sewardjb5f6f512005-03-10 23:59:00 +0000287
288 vg_assert(tid != VG_INVALID_THREADID);
289 vg_assert(VG_(threads)[tid].os_state.lwpid == VG_(gettid)());
290
291 VG_(set_sleeping)(tid, VgTs_Yielding);
292
293 //VG_(printf)("tid %d yielding EIP=%p\n", tid, VG_(threads)[tid].arch.m_eip);
294
295 /*
296 Tell the kernel we're yielding.
297 */
298 if (1)
299 VG_(do_syscall0)(__NR_sched_yield);
300 else
301 VG_(nanosleep)(&ts);
302
303 VG_(set_running)(tid);
sewardjb5f6f512005-03-10 23:59:00 +0000304}
305
306
njn9fc31122005-05-11 18:48:33 +0000307/* Set the standard set of blocked signals, used wheneever we're not
308 running a client syscall. */
309static void block_signals(ThreadId tid)
310{
311 vki_sigset_t mask;
312
313 VG_(sigfillset)(&mask);
314
315 /* Don't block these because they're synchronous */
316 VG_(sigdelset)(&mask, VKI_SIGSEGV);
317 VG_(sigdelset)(&mask, VKI_SIGBUS);
318 VG_(sigdelset)(&mask, VKI_SIGFPE);
319 VG_(sigdelset)(&mask, VKI_SIGILL);
320 VG_(sigdelset)(&mask, VKI_SIGTRAP);
321
322 /* Can't block these anyway */
323 VG_(sigdelset)(&mask, VKI_SIGSTOP);
324 VG_(sigdelset)(&mask, VKI_SIGKILL);
325
njn9fc31122005-05-11 18:48:33 +0000326 VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, NULL);
327}
328
njn4f6e3702005-05-16 20:50:52 +0000329/* Use libc setjmp/longjmp. longjmp must not restore signal mask
330 state, but does need to pass "val" through. */
sewardjb5f6f512005-03-10 23:59:00 +0000331#define SCHEDSETJMP(tid, jumped, stmt) \
332 do { \
333 ThreadState * volatile _qq_tst = VG_(get_ThreadState)(tid); \
334 \
njn4f6e3702005-05-16 20:50:52 +0000335 (jumped) = setjmp(_qq_tst->sched_jmpbuf); \
sewardjb5f6f512005-03-10 23:59:00 +0000336 if ((jumped) == 0) { \
337 vg_assert(!_qq_tst->sched_jmpbuf_valid); \
338 _qq_tst->sched_jmpbuf_valid = True; \
339 stmt; \
340 } else if (VG_(clo_trace_sched)) \
341 VG_(printf)("SCHEDSETJMP(line %d) tid %d, jumped=%d\n", __LINE__, tid, jumped); \
342 vg_assert(_qq_tst->sched_jmpbuf_valid); \
343 _qq_tst->sched_jmpbuf_valid = False; \
344 } while(0)
345
346/* Run the thread tid for a while, and return a VG_TRC_* value to the
347 scheduler indicating what happened. */
sewardj6072c362002-04-19 14:40:57 +0000348static
sewardje663cb92002-04-12 10:26:32 +0000349UInt run_thread_for_a_while ( ThreadId tid )
350{
sewardjb5f6f512005-03-10 23:59:00 +0000351 volatile Bool jumped;
352 volatile ThreadState *tst = VG_(get_ThreadState)(tid);
sewardjb5f6f512005-03-10 23:59:00 +0000353
sewardj7ccc5c22002-04-24 21:39:11 +0000354 volatile UInt trc = 0;
sewardjb5f6f512005-03-10 23:59:00 +0000355 volatile Int dispatch_ctr_SAVED = VG_(dispatch_ctr);
356 volatile Int done_this_time;
sewardj8b635a42004-11-22 19:01:47 +0000357
sewardj873b3132004-11-25 22:50:17 +0000358 /* For paranoia purposes only */
359 volatile Addr a_vex = (Addr) & VG_(threads)[tid].arch.vex;
360 volatile Addr a_vexsh = (Addr) & VG_(threads)[tid].arch.vex_shadow;
361 volatile Addr a_spill = (Addr) & VG_(threads)[tid].arch.vex_spill;
362 volatile UInt sz_vex = (UInt) sizeof VG_(threads)[tid].arch.vex;
363 volatile UInt sz_vexsh = (UInt) sizeof VG_(threads)[tid].arch.vex_shadow;
364 volatile UInt sz_spill = (UInt) sizeof VG_(threads)[tid].arch.vex_spill;
365
366 /* Paranoia */
sewardjb48e5002002-05-13 00:16:03 +0000367 vg_assert(VG_(is_valid_tid)(tid));
sewardjb5f6f512005-03-10 23:59:00 +0000368 vg_assert(VG_(is_valid_tid)(tid));
369 vg_assert(VG_(is_running_thread)(tid));
370 vg_assert(!VG_(is_exiting)(tid));
sewardje663cb92002-04-12 10:26:32 +0000371
sewardj873b3132004-11-25 22:50:17 +0000372 /* Even more paranoia. Check that what we have matches
373 Vex's guest state layout requirements. */
sewardj12a74b52004-11-26 11:57:41 +0000374 if (0)
375 VG_(printf)("%p %d %p %d %p %d\n",
sewardjb5f6f512005-03-10 23:59:00 +0000376 (void*)a_vex, sz_vex, (void*)a_vexsh, sz_vexsh,
377 (void*)a_spill, sz_spill );
sewardj873b3132004-11-25 22:50:17 +0000378
njnbe91aae2005-03-27 01:42:41 +0000379 vg_assert(VG_IS_8_ALIGNED(sz_vex));
380 vg_assert(VG_IS_8_ALIGNED(sz_vexsh));
381 vg_assert(VG_IS_16_ALIGNED(sz_spill));
sewardj12a74b52004-11-26 11:57:41 +0000382
njnbe91aae2005-03-27 01:42:41 +0000383 vg_assert(VG_IS_4_ALIGNED(a_vex));
384 vg_assert(VG_IS_4_ALIGNED(a_vexsh));
385 vg_assert(VG_IS_4_ALIGNED(a_spill));
sewardj873b3132004-11-25 22:50:17 +0000386
387 vg_assert(sz_vex == sz_vexsh);
388 vg_assert(a_vex + sz_vex == a_vexsh);
389
390 vg_assert(sz_spill == LibVEX_N_SPILL_BYTES);
391 vg_assert(a_vex + 2 * sz_vex == a_spill);
392
sewardj671ff542002-05-07 09:25:30 +0000393 VGP_PUSHCC(VgpRun);
jsgf855d93d2003-10-13 22:26:55 +0000394
sewardj10537332005-08-05 00:25:11 +0000395# if defined(VGA_ppc32)
396 /* This is necessary due to the hacky way vex models reservations
397 on ppc. It's really quite incorrect for each thread to have its
398 own reservation flag/address, since it's really something that
399 all threads share (that's the whole point). But having shared
400 guest state is something we can't model with Vex. However, as
401 per PaulM's 2.4.0ppc, the reservation is modelled using a
402 reservation flag which is cleared at each context switch. So it
403 is indeed possible to get away with a per thread-reservation if
404 the thread's reservation is cleared before running it.
405
406 This should be abstractified and lifted out.
407 */
408 { Int i;
409 /* Clear any existing reservation. Be paranoid and clear them all. */
410 for (i = 0; i < VG_N_THREADS; i++)
411 VG_(threads)[i].arch.vex.guest_RESVN = 0;
412 }
413# endif
414
jsgf855d93d2003-10-13 22:26:55 +0000415 /* there should be no undealt-with signals */
sewardjb5f6f512005-03-10 23:59:00 +0000416 //vg_assert(VG_(threads)[tid].siginfo.si_signo == 0);
jsgf855d93d2003-10-13 22:26:55 +0000417
sewardjb5f6f512005-03-10 23:59:00 +0000418 //VG_(printf)("running EIP = %p ESP=%p\n", VG_(threads)[tid].arch.m_eip, VG_(threads)[tid].arch.m_esp);
419
420 vg_assert(VG_(my_fault));
421 VG_(my_fault) = False;
422
sewardj0312f512005-03-30 19:04:29 +0000423 SCHEDSETJMP(tid, jumped,
424 trc = (UInt)VG_(run_innerloop)( (void*)&tst->arch.vex ));
sewardjb5f6f512005-03-10 23:59:00 +0000425
426 //nextEIP = tst->arch.m_eip;
427 //if (nextEIP >= VG_(client_end))
428 // VG_(printf)("trc=%d jump to %p from %p\n",
429 // trc, nextEIP, EIP);
430
431 VG_(my_fault) = True;
432
433 if (jumped) {
sewardje663cb92002-04-12 10:26:32 +0000434 /* We get here if the client took a fault, which caused our
435 signal handler to longjmp. */
436 vg_assert(trc == 0);
sewardjb5f6f512005-03-10 23:59:00 +0000437 trc = VG_TRC_FAULT_SIGNAL;
njn9fc31122005-05-11 18:48:33 +0000438 block_signals(tid);
sewardjb5f6f512005-03-10 23:59:00 +0000439 }
sewardj5390e662005-01-10 16:51:14 +0000440
sewardj8b635a42004-11-22 19:01:47 +0000441 done_this_time = (Int)dispatch_ctr_SAVED - (Int)VG_(dispatch_ctr) - 0;
442
443 vg_assert(done_this_time >= 0);
njn394213a2005-06-19 18:38:24 +0000444 bbs_done += (ULong)done_this_time;
sewardj8b635a42004-11-22 19:01:47 +0000445
njn25e49d8e72002-09-23 09:36:25 +0000446 VGP_POPCC(VgpRun);
sewardje663cb92002-04-12 10:26:32 +0000447 return trc;
448}
449
450
njn8aa35852005-06-10 22:59:56 +0000451static void os_state_clear(ThreadState *tst)
452{
453 tst->os_state.lwpid = 0;
454 tst->os_state.threadgroup = 0;
455}
456
457static void os_state_init(ThreadState *tst)
458{
459 tst->os_state.valgrind_stack_base = 0;
460 tst->os_state.valgrind_stack_szB = 0;
461
462 os_state_clear(tst);
463}
464
sewardj20917d82002-05-28 01:36:45 +0000465static
466void mostly_clear_thread_record ( ThreadId tid )
467{
sewardjb5f6f512005-03-10 23:59:00 +0000468 vki_sigset_t savedmask;
469
sewardj20917d82002-05-28 01:36:45 +0000470 vg_assert(tid >= 0 && tid < VG_N_THREADS);
njnaf839f52005-06-23 03:27:57 +0000471 VG_(cleanup_thread)(&VG_(threads)[tid].arch);
sewardjb5f6f512005-03-10 23:59:00 +0000472 VG_(threads)[tid].tid = tid;
473
474 /* Leave the thread in Zombie, so that it doesn't get reallocated
475 until the caller is finally done with the thread stack. */
476 VG_(threads)[tid].status = VgTs_Zombie;
477
nethercote73b526f2004-10-31 18:48:21 +0000478 VG_(sigemptyset)(&VG_(threads)[tid].sig_mask);
sewardjb5f6f512005-03-10 23:59:00 +0000479 VG_(sigemptyset)(&VG_(threads)[tid].tmp_sig_mask);
jsgf855d93d2003-10-13 22:26:55 +0000480
njn8aa35852005-06-10 22:59:56 +0000481 os_state_clear(&VG_(threads)[tid]);
fitzhardinge28428592004-03-16 22:07:12 +0000482
483 /* start with no altstack */
484 VG_(threads)[tid].altstack.ss_sp = (void *)0xdeadbeef;
485 VG_(threads)[tid].altstack.ss_size = 0;
486 VG_(threads)[tid].altstack.ss_flags = VKI_SS_DISABLE;
sewardjb5f6f512005-03-10 23:59:00 +0000487
njn444eba12005-05-12 03:47:31 +0000488 VG_(clear_out_queued_signals)(tid, &savedmask);
sewardjb5f6f512005-03-10 23:59:00 +0000489
490 VG_(threads)[tid].sched_jmpbuf_valid = False;
sewardj20917d82002-05-28 01:36:45 +0000491}
492
njn3f8c4372005-03-13 04:43:10 +0000493/*
494 Called in the child after fork. If the parent has multiple
495 threads, then we've inhereted a VG_(threads) array describing them,
496 but only the thread which called fork() is actually alive in the
497 child. This functions needs to clean up all those other thread
498 structures.
499
500 Whichever tid in the parent which called fork() becomes the
501 master_tid in the child. That's because the only living slot in
502 VG_(threads) in the child after fork is VG_(threads)[tid], and it
503 would be too hard to try to re-number the thread and relocate the
504 thread state down to VG_(threads)[1].
505
506 This function also needs to reinitialize the run_sema, since
507 otherwise we may end up sharing its state with the parent, which
508 would be deeply confusing.
509*/
sewardjb5f6f512005-03-10 23:59:00 +0000510static void sched_fork_cleanup(ThreadId me)
511{
512 ThreadId tid;
njnc7561b92005-06-19 01:24:32 +0000513 vg_assert(VG_(running_tid) == me);
sewardjb5f6f512005-03-10 23:59:00 +0000514
sewardjb5f6f512005-03-10 23:59:00 +0000515 VG_(threads)[me].os_state.lwpid = VG_(gettid)();
516 VG_(threads)[me].os_state.threadgroup = VG_(getpid)();
517
518 /* clear out all the unused thread slots */
519 for (tid = 1; tid < VG_N_THREADS; tid++) {
njn3f8c4372005-03-13 04:43:10 +0000520 if (tid != me) {
521 mostly_clear_thread_record(tid);
sewardjb5f6f512005-03-10 23:59:00 +0000522 VG_(threads)[tid].status = VgTs_Empty;
sewardja8d8e232005-06-07 20:04:56 +0000523 VG_(clear_syscallInfo)(tid);
njn3f8c4372005-03-13 04:43:10 +0000524 }
sewardjb5f6f512005-03-10 23:59:00 +0000525 }
526
527 /* re-init and take the sema */
sewardj7eb7c582005-06-23 01:02:53 +0000528 ML_(sema_deinit)(&run_sema);
529 ML_(sema_init)(&run_sema);
530 ML_(sema_down)(&run_sema);
sewardjb5f6f512005-03-10 23:59:00 +0000531}
sewardj20917d82002-05-28 01:36:45 +0000532
jsgf855d93d2003-10-13 22:26:55 +0000533
sewardje663cb92002-04-12 10:26:32 +0000534/* Initialise the scheduler. Create a single "main" thread ready to
sewardj2a99cf62004-11-24 10:44:19 +0000535 run, with special ThreadId of one. This is called at startup. The
sewardjb5f6f512005-03-10 23:59:00 +0000536 caller subsequently initialises the guest state components of this
537 main thread, thread 1.
sewardje663cb92002-04-12 10:26:32 +0000538*/
539void VG_(scheduler_init) ( void )
540{
thughesc37184f2004-09-11 14:16:57 +0000541 Int i;
sewardje663cb92002-04-12 10:26:32 +0000542 ThreadId tid_main;
543
sewardj7eb7c582005-06-23 01:02:53 +0000544 ML_(sema_init)(&run_sema);
sewardjb5f6f512005-03-10 23:59:00 +0000545
sewardj6072c362002-04-19 14:40:57 +0000546 for (i = 0 /* NB; not 1 */; i < VG_N_THREADS; i++) {
sewardjc793fd32005-05-31 17:24:49 +0000547
548 /* Paranoia .. completely zero it out. */
549 VG_(memset)( & VG_(threads)[i], 0, sizeof( VG_(threads)[i] ) );
550
551 VG_(threads)[i].sig_queue = NULL;
sewardjb5f6f512005-03-10 23:59:00 +0000552
njn8aa35852005-06-10 22:59:56 +0000553 os_state_init(&VG_(threads)[i]);
sewardj20917d82002-05-28 01:36:45 +0000554 mostly_clear_thread_record(i);
sewardjb5f6f512005-03-10 23:59:00 +0000555
njn50ba34e2005-04-04 02:41:42 +0000556 VG_(threads)[i].status = VgTs_Empty;
557 VG_(threads)[i].client_stack_szB = 0;
558 VG_(threads)[i].client_stack_highest_word = (Addr)NULL;
sewardje663cb92002-04-12 10:26:32 +0000559 }
560
sewardjb5f6f512005-03-10 23:59:00 +0000561 tid_main = VG_(alloc_ThreadState)();
sewardj5f07b662002-04-23 16:52:51 +0000562
sewardjb5f6f512005-03-10 23:59:00 +0000563 /* Initial thread's stack is the original process stack */
njn50ba34e2005-04-04 02:41:42 +0000564 VG_(threads)[tid_main].client_stack_highest_word
njn90eecea2005-04-04 02:48:32 +0000565 = VG_(clstk_end) - sizeof(UWord);
njn50ba34e2005-04-04 02:41:42 +0000566 VG_(threads)[tid_main].client_stack_szB = VG_(client_rlimit_stack).rlim_cur;
sewardjbf290b92002-05-01 02:28:01 +0000567
njn310ed282005-06-26 15:11:37 +0000568 VG_(atfork_child)(sched_fork_cleanup);
sewardje663cb92002-04-12 10:26:32 +0000569}
570
571
sewardje663cb92002-04-12 10:26:32 +0000572/* ---------------------------------------------------------------------
573 The scheduler proper.
574 ------------------------------------------------------------------ */
575
sewardjb5f6f512005-03-10 23:59:00 +0000576static void handle_tt_miss ( ThreadId tid )
sewardje663cb92002-04-12 10:26:32 +0000577{
sewardjb5f6f512005-03-10 23:59:00 +0000578 Bool found;
njnf536bbb2005-06-13 04:21:38 +0000579 Addr ip = VG_(get_IP)(tid);
sewardjb5f6f512005-03-10 23:59:00 +0000580
581 /* Trivial event. Miss in the fast-cache. Do a full
582 lookup for it. */
njnf536bbb2005-06-13 04:21:38 +0000583 found = VG_(search_transtab)( NULL, ip, True/*upd_fast_cache*/ );
sewardjb5f6f512005-03-10 23:59:00 +0000584 if (!found) {
585 /* Not found; we need to request a translation. */
njn394213a2005-06-19 18:38:24 +0000586 if (VG_(translate)( tid, ip, /*debug*/False, 0/*not verbose*/, bbs_done )) {
sewardjb5f6f512005-03-10 23:59:00 +0000587 found = VG_(search_transtab)( NULL, ip, True );
njn50ae1a72005-04-08 23:28:23 +0000588 vg_assert2(found, "VG_TRC_INNER_FASTMISS: missing tt_fast entry");
589
sewardjb5f6f512005-03-10 23:59:00 +0000590 } else {
591 // If VG_(translate)() fails, it's because it had to throw a
592 // signal because the client jumped to a bad address. That
593 // means that either a signal has been set up for delivery,
594 // or the thread has been marked for termination. Either
595 // way, we just need to go back into the scheduler loop.
596 }
597 }
598}
599
600static void handle_syscall(ThreadId tid)
601{
602 ThreadState *tst = VG_(get_ThreadState)(tid);
603 Bool jumped;
604
605 /* Syscall may or may not block; either way, it will be
606 complete by the time this call returns, and we'll be
607 runnable again. We could take a signal while the
608 syscall runs. */
609 SCHEDSETJMP(tid, jumped, VG_(client_syscall)(tid));
610
611 if (!VG_(is_running_thread)(tid))
njnc7561b92005-06-19 01:24:32 +0000612 VG_(printf)("tid %d not running; VG_(running_tid)=%d, tid %d status %d\n",
613 tid, VG_(running_tid), tid, tst->status);
sewardjb5f6f512005-03-10 23:59:00 +0000614 vg_assert(VG_(is_running_thread)(tid));
615
616 if (jumped) {
njn9fc31122005-05-11 18:48:33 +0000617 block_signals(tid);
sewardjb5f6f512005-03-10 23:59:00 +0000618 VG_(poll_signals)(tid);
619 }
620}
621
622/*
623 Run a thread until it wants to exit.
624
625 We assume that the caller has already called VG_(set_running) for
626 us, so we own the VCPU. Also, all signals are blocked.
627 */
628VgSchedReturnCode VG_(scheduler) ( ThreadId tid )
629{
sewardje663cb92002-04-12 10:26:32 +0000630 UInt trc;
sewardjb5f6f512005-03-10 23:59:00 +0000631 ThreadState *tst = VG_(get_ThreadState)(tid);
sewardje663cb92002-04-12 10:26:32 +0000632
sewardjc24be7a2005-03-15 01:40:12 +0000633 if (VG_(clo_trace_sched))
634 print_sched_event(tid, "entering VG_(scheduler)");
635
sewardjb5f6f512005-03-10 23:59:00 +0000636 VGP_PUSHCC(VgpSched);
sewardje663cb92002-04-12 10:26:32 +0000637
sewardjb5f6f512005-03-10 23:59:00 +0000638 /* set the proper running signal mask */
njn9fc31122005-05-11 18:48:33 +0000639 block_signals(tid);
sewardjb5f6f512005-03-10 23:59:00 +0000640
641 vg_assert(VG_(is_running_thread)(tid));
sewardje663cb92002-04-12 10:26:32 +0000642
njn14319cc2005-03-13 06:26:22 +0000643 VG_(dispatch_ctr) = SCHEDULING_QUANTUM + 1;
sewardj6072c362002-04-19 14:40:57 +0000644
sewardjb5f6f512005-03-10 23:59:00 +0000645 while(!VG_(is_exiting)(tid)) {
sewardjb5f6f512005-03-10 23:59:00 +0000646 if (VG_(dispatch_ctr) == 1) {
647 /* Our slice is done, so yield the CPU to another thread. This
648 doesn't sleep between sleeping and running, since that would
649 take too much time. */
650 VG_(set_sleeping)(tid, VgTs_Yielding);
651 /* nothing */
652 VG_(set_running)(tid);
sewardje663cb92002-04-12 10:26:32 +0000653
sewardjb5f6f512005-03-10 23:59:00 +0000654 /* OK, do some relatively expensive housekeeping stuff */
655 scheduler_sanity(tid);
656 VG_(sanity_check_general)(False);
sewardje663cb92002-04-12 10:26:32 +0000657
sewardjb5f6f512005-03-10 23:59:00 +0000658 /* Look for any pending signals for this thread, and set them up
659 for delivery */
660 VG_(poll_signals)(tid);
sewardje663cb92002-04-12 10:26:32 +0000661
sewardjb5f6f512005-03-10 23:59:00 +0000662 if (VG_(is_exiting)(tid))
663 break; /* poll_signals picked up a fatal signal */
sewardje663cb92002-04-12 10:26:32 +0000664
sewardjb5f6f512005-03-10 23:59:00 +0000665 /* For stats purposes only. */
666 n_scheduling_events_MAJOR++;
sewardje663cb92002-04-12 10:26:32 +0000667
sewardjb5f6f512005-03-10 23:59:00 +0000668 /* Figure out how many bbs to ask vg_run_innerloop to do. Note
669 that it decrements the counter before testing it for zero, so
670 that if tst->dispatch_ctr is set to N you get at most N-1
671 iterations. Also this means that tst->dispatch_ctr must
672 exceed zero before entering the innerloop. Also also, the
673 decrement is done before the bb is actually run, so you
674 always get at least one decrement even if nothing happens. */
njn14319cc2005-03-13 06:26:22 +0000675 VG_(dispatch_ctr) = SCHEDULING_QUANTUM + 1;
jsgf855d93d2003-10-13 22:26:55 +0000676
sewardjb5f6f512005-03-10 23:59:00 +0000677 /* paranoia ... */
678 vg_assert(tst->tid == tid);
679 vg_assert(tst->os_state.lwpid == VG_(gettid)());
sewardje663cb92002-04-12 10:26:32 +0000680 }
681
sewardjb5f6f512005-03-10 23:59:00 +0000682 /* For stats purposes only. */
683 n_scheduling_events_MINOR++;
sewardje663cb92002-04-12 10:26:32 +0000684
685 if (0)
sewardjb5f6f512005-03-10 23:59:00 +0000686 VG_(message)(Vg_DebugMsg, "thread %d: running for %d bbs",
687 tid, VG_(dispatch_ctr) - 1 );
sewardje663cb92002-04-12 10:26:32 +0000688
sewardjb5f6f512005-03-10 23:59:00 +0000689 trc = run_thread_for_a_while ( tid );
sewardje663cb92002-04-12 10:26:32 +0000690
sewardjb5f6f512005-03-10 23:59:00 +0000691 if (VG_(clo_trace_sched) && VG_(clo_verbosity) > 2) {
692 Char buf[50];
693 VG_(sprintf)(buf, "TRC: %s", name_of_sched_event(trc));
694 print_sched_event(tid, buf);
sewardje663cb92002-04-12 10:26:32 +0000695 }
696
sewardjb5f6f512005-03-10 23:59:00 +0000697 switch(trc) {
698 case VG_TRC_INNER_FASTMISS:
699 vg_assert(VG_(dispatch_ctr) > 1);
700 handle_tt_miss(tid);
701 break;
702
703 case VEX_TRC_JMP_CLIENTREQ:
704 do_client_request(tid);
705 break;
706
707 case VEX_TRC_JMP_SYSCALL:
708 handle_syscall(tid);
709 if (VG_(clo_sanity_level) > 2)
710 VG_(sanity_check_general)(True); /* sanity-check every syscall */
711 break;
sewardje663cb92002-04-12 10:26:32 +0000712
sewardjb5f6f512005-03-10 23:59:00 +0000713 case VEX_TRC_JMP_YIELD:
714 /* Explicit yield, because this thread is in a spin-lock
sewardj3fc75752005-03-12 15:16:31 +0000715 or something. Only let the thread run for a short while
716 longer. Because swapping to another thread is expensive,
717 we're prepared to let this thread eat a little more CPU
718 before swapping to another. That means that short term
719 spins waiting for hardware to poke memory won't cause a
720 thread swap. */
721 if (VG_(dispatch_ctr) > 100)
722 VG_(dispatch_ctr) = 100;
sewardjb5f6f512005-03-10 23:59:00 +0000723 break;
sewardje663cb92002-04-12 10:26:32 +0000724
sewardjb5f6f512005-03-10 23:59:00 +0000725 case VG_TRC_INNER_COUNTERZERO:
726 /* Timeslice is out. Let a new thread be scheduled. */
727 vg_assert(VG_(dispatch_ctr) == 1);
728 break;
sewardje663cb92002-04-12 10:26:32 +0000729
sewardjb5f6f512005-03-10 23:59:00 +0000730 case VG_TRC_FAULT_SIGNAL:
731 /* Everything should be set up (either we're exiting, or
732 about to start in a signal handler). */
733 break;
sewardj9d1b5d32002-04-17 19:40:49 +0000734
sewardj07bdc5e2005-03-11 13:19:47 +0000735 case VEX_TRC_JMP_MAPFAIL:
736 /* Failure of arch-specific address translation (x86/amd64
737 segment override use) */
738 /* jrs 2005 03 11: is this correct? */
739 VG_(synth_fault)(tid);
740 break;
741
sewardjb5f6f512005-03-10 23:59:00 +0000742 case VEX_TRC_JMP_EMWARN: {
743 static Int counts[EmWarn_NUMBER];
744 static Bool counts_initted = False;
745 VexEmWarn ew;
746 HChar* what;
747 Bool show;
748 Int q;
749 if (!counts_initted) {
750 counts_initted = True;
751 for (q = 0; q < EmWarn_NUMBER; q++)
752 counts[q] = 0;
753 }
754 ew = (VexEmWarn)VG_(threads)[tid].arch.vex.guest_EMWARN;
755 what = (ew < 0 || ew >= EmWarn_NUMBER)
756 ? "unknown (?!)"
757 : LibVEX_EmWarn_string(ew);
758 show = (ew < 0 || ew >= EmWarn_NUMBER)
759 ? True
760 : counts[ew]++ < 3;
sewardjb1131a82005-03-19 15:12:21 +0000761 if (show && VG_(clo_show_emwarns)) {
sewardjb5f6f512005-03-10 23:59:00 +0000762 VG_(message)( Vg_UserMsg,
763 "Emulation warning: unsupported action:");
764 VG_(message)( Vg_UserMsg, " %s", what);
njnd01fef72005-03-25 23:35:48 +0000765 VG_(get_and_pp_StackTrace)( tid, VG_(clo_backtrace_size) );
sewardjb5f6f512005-03-10 23:59:00 +0000766 }
767 break;
768 }
sewardje663cb92002-04-12 10:26:32 +0000769
sewardjb5f6f512005-03-10 23:59:00 +0000770 case VEX_TRC_JMP_NODECODE:
njnf536bbb2005-06-13 04:21:38 +0000771 VG_(synth_sigill)(tid, VG_(get_IP)(tid));
sewardjb5f6f512005-03-10 23:59:00 +0000772 break;
sewardje663cb92002-04-12 10:26:32 +0000773
cerion85665ca2005-06-20 15:51:07 +0000774 case VEX_TRC_JMP_TINVAL:
cerion85665ca2005-06-20 15:51:07 +0000775 VG_(discard_translations)(
776 (Addr64)VG_(threads)[tid].arch.vex.guest_TISTART,
sewardj487ac702005-06-21 12:52:38 +0000777 VG_(threads)[tid].arch.vex.guest_TILEN
778 );
cerion85665ca2005-06-20 15:51:07 +0000779 if (0)
780 VG_(printf)("dump translations done.\n");
cerion85665ca2005-06-20 15:51:07 +0000781 break;
782
sewardje3a384b2005-07-29 08:51:34 +0000783 case VG_TRC_INVARIANT_FAILED:
784 /* This typically happens if, after running generated code,
785 it is detected that host CPU settings (eg, FPU/Vector
786 control words) are not as they should be. Vex's code
787 generation specifies the state such control words should
788 be in on entry to Vex-generated code, and they should be
789 unchanged on exit from it. Failure of this assertion
790 usually means a bug in Vex's code generation. */
791 vg_assert2(0, "VG_(scheduler), phase 3: "
792 "run_innerloop detected host "
793 "state invariant failure", trc);
794
sewardj5438a012005-08-07 14:49:27 +0000795 case VEX_TRC_JMP_SYSENTER_X86:
796 /* Do whatever simulation is appropriate for an x86 sysenter
797 instruction. Note that it is critical to set this thread's
798 guest_EIP to point at the code to execute after the
799 sysenter, since Vex-generated code will not have set it --
800 vex does not know what it should be. Vex sets the next
801 address to zero, so if you don't guest_EIP, the thread will
802 jump to zero afterwards and probably die as a result. */
803# if defined(VGA_x86)
804 //FIXME: VG_(threads)[tid].arch.vex.guest_EIP = ....
805 //handle_sysenter_x86(tid);
806 vg_assert2(0, "VG_(scheduler), phase 3: "
807 "sysenter_x86 on not yet implemented");
808# else
809 vg_assert2(0, "VG_(scheduler), phase 3: "
810 "sysenter_x86 on non-x86 platform?!?!");
811# endif
812
sewardjb5f6f512005-03-10 23:59:00 +0000813 default:
njn50ae1a72005-04-08 23:28:23 +0000814 vg_assert2(0, "VG_(scheduler), phase 3: "
815 "unexpected thread return code (%u)", trc);
sewardjb5f6f512005-03-10 23:59:00 +0000816 /* NOTREACHED */
817 break;
sewardje663cb92002-04-12 10:26:32 +0000818
819 } /* switch (trc) */
nethercote238a3c32004-08-09 13:13:31 +0000820 }
sewardjc24be7a2005-03-15 01:40:12 +0000821
822 if (VG_(clo_trace_sched))
823 print_sched_event(tid, "exiting VG_(scheduler)");
824
sewardjb5f6f512005-03-10 23:59:00 +0000825 vg_assert(VG_(is_exiting)(tid));
thughes513197c2004-06-13 12:07:53 +0000826
sewardjb5f6f512005-03-10 23:59:00 +0000827 VGP_POPCC(VgpSched);
thughes513197c2004-06-13 12:07:53 +0000828
sewardjb5f6f512005-03-10 23:59:00 +0000829 //if (VG_(clo_model_pthreads))
830 // VG_(tm_thread_exit)(tid);
831
832 return tst->exitreason;
sewardj20917d82002-05-28 01:36:45 +0000833}
834
835
sewardjb5f6f512005-03-10 23:59:00 +0000836/*
837 This causes all threads to forceably exit. They aren't actually
838 dead by the time this returns; you need to call
njnaf839f52005-06-23 03:27:57 +0000839 VG_(reap_threads)() to wait for them.
sewardjb5f6f512005-03-10 23:59:00 +0000840 */
841void VG_(nuke_all_threads_except) ( ThreadId me, VgSchedReturnCode src )
sewardjccef2e62002-05-29 19:26:32 +0000842{
843 ThreadId tid;
sewardjb5f6f512005-03-10 23:59:00 +0000844
845 vg_assert(VG_(is_running_thread)(me));
sewardj45f02c42005-02-05 18:27:14 +0000846
sewardjccef2e62002-05-29 19:26:32 +0000847 for (tid = 1; tid < VG_N_THREADS; tid++) {
848 if (tid == me
jsgf855d93d2003-10-13 22:26:55 +0000849 || VG_(threads)[tid].status == VgTs_Empty)
sewardjccef2e62002-05-29 19:26:32 +0000850 continue;
sewardjb5f6f512005-03-10 23:59:00 +0000851 if (0)
sewardjef037c72002-05-30 00:40:03 +0000852 VG_(printf)(
853 "VG_(nuke_all_threads_except): nuking tid %d\n", tid);
sewardjb5f6f512005-03-10 23:59:00 +0000854
855 VG_(threads)[tid].exitreason = src;
sewardja8d8e232005-06-07 20:04:56 +0000856 if (src == VgSrc_FatalSig)
857 VG_(threads)[tid].os_state.fatalsig = VKI_SIGKILL;
sewardjb5f6f512005-03-10 23:59:00 +0000858 VG_(kill_thread)(tid);
sewardjccef2e62002-05-29 19:26:32 +0000859 }
860}
861
862
njnd3040452003-05-19 15:04:06 +0000863/* ---------------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +0000864 Specifying shadow register values
njnd3040452003-05-19 15:04:06 +0000865 ------------------------------------------------------------------ */
866
njnf536bbb2005-06-13 04:21:38 +0000867#if defined(VGA_x86)
njnaf839f52005-06-23 03:27:57 +0000868# define VG_CLREQ_ARGS guest_EAX
869# define VG_CLREQ_RET guest_EDX
njnf536bbb2005-06-13 04:21:38 +0000870#elif defined(VGA_amd64)
njnaf839f52005-06-23 03:27:57 +0000871# define VG_CLREQ_ARGS guest_RAX
872# define VG_CLREQ_RET guest_RDX
cerion85665ca2005-06-20 15:51:07 +0000873#elif defined(VGA_ppc32)
njnaf839f52005-06-23 03:27:57 +0000874# define VG_CLREQ_ARGS guest_GPR4
875# define VG_CLREQ_RET guest_GPR3
njnf536bbb2005-06-13 04:21:38 +0000876#else
877# error Unknown arch
878#endif
879
njnaf839f52005-06-23 03:27:57 +0000880#define CLREQ_ARGS(regs) ((regs).vex.VG_CLREQ_ARGS)
881#define CLREQ_RET(regs) ((regs).vex.VG_CLREQ_RET)
882#define O_CLREQ_RET (offsetof(VexGuestArchState, VG_CLREQ_RET))
njnf536bbb2005-06-13 04:21:38 +0000883
njn502badb2005-05-08 02:04:49 +0000884// These macros write a value to a client's thread register, and tell the
885// tool that it's happened (if necessary).
886
887#define SET_CLREQ_RETVAL(zztid, zzval) \
888 do { CLREQ_RET(VG_(threads)[zztid].arch) = (zzval); \
889 VG_TRACK( post_reg_write, \
890 Vg_CoreClientReq, zztid, O_CLREQ_RET, sizeof(UWord)); \
891 } while (0)
892
893#define SET_CLCALL_RETVAL(zztid, zzval, f) \
894 do { CLREQ_RET(VG_(threads)[zztid].arch) = (zzval); \
895 VG_TRACK( post_reg_write_clientcall_return, \
896 zztid, O_CLREQ_RET, sizeof(UWord), f); \
897 } while (0)
898
sewardje663cb92002-04-12 10:26:32 +0000899/* ---------------------------------------------------------------------
sewardj124ca2a2002-06-20 10:19:38 +0000900 Handle client requests.
sewardje663cb92002-04-12 10:26:32 +0000901 ------------------------------------------------------------------ */
902
njn9cb54ac2005-06-12 04:19:17 +0000903// OS-specific(?) client requests
904static Bool os_client_request(ThreadId tid, UWord *args)
905{
906 Bool handled = True;
907
908 vg_assert(VG_(is_running_thread)(tid));
909
910 switch(args[0]) {
911 case VG_USERREQ__LIBC_FREERES_DONE:
912 /* This is equivalent to an exit() syscall, but we don't set the
913 exitcode (since it might already be set) */
914 if (0 || VG_(clo_trace_syscalls) || VG_(clo_trace_sched))
915 VG_(message)(Vg_DebugMsg,
916 "__libc_freeres() done; really quitting!");
917 VG_(threads)[tid].exitreason = VgSrc_ExitSyscall;
918 break;
919
920 default:
921 handled = False;
922 break;
923 }
924
925 return handled;
926}
927
928
sewardj124ca2a2002-06-20 10:19:38 +0000929/* Do a client request for the thread tid. After the request, tid may
930 or may not still be runnable; if not, the scheduler will have to
931 choose a new thread to run.
932*/
sewardje663cb92002-04-12 10:26:32 +0000933static
sewardjb5f6f512005-03-10 23:59:00 +0000934void do_client_request ( ThreadId tid )
sewardje663cb92002-04-12 10:26:32 +0000935{
sewardjb5f6f512005-03-10 23:59:00 +0000936 UWord* arg = (UWord*)(CLREQ_ARGS(VG_(threads)[tid].arch));
nethercoted1b64b22004-11-04 18:22:28 +0000937 UWord req_no = arg[0];
sewardj124ca2a2002-06-20 10:19:38 +0000938
fitzhardinge98abfc72003-12-16 02:05:15 +0000939 if (0)
nethercoted1b64b22004-11-04 18:22:28 +0000940 VG_(printf)("req no = 0x%llx, arg = %p\n", (ULong)req_no, arg);
sewardje663cb92002-04-12 10:26:32 +0000941 switch (req_no) {
942
njn3e884182003-04-15 13:03:23 +0000943 case VG_USERREQ__CLIENT_CALL0: {
njn2ac95242005-03-13 23:07:30 +0000944 UWord (*f)(ThreadId) = (void*)arg[1];
fitzhardinge98abfc72003-12-16 02:05:15 +0000945 if (f == NULL)
njn3d9edb22005-08-25 01:52:52 +0000946 VG_(message)(Vg_DebugMsg, "VG_USERREQ__CLIENT_CALL0: func=%p", f);
fitzhardinge98abfc72003-12-16 02:05:15 +0000947 else
njn2ac95242005-03-13 23:07:30 +0000948 SET_CLCALL_RETVAL(tid, f ( tid ), (Addr)f);
njn3e884182003-04-15 13:03:23 +0000949 break;
950 }
951 case VG_USERREQ__CLIENT_CALL1: {
njn2ac95242005-03-13 23:07:30 +0000952 UWord (*f)(ThreadId, UWord) = (void*)arg[1];
fitzhardinge98abfc72003-12-16 02:05:15 +0000953 if (f == NULL)
njn3d9edb22005-08-25 01:52:52 +0000954 VG_(message)(Vg_DebugMsg, "VG_USERREQ__CLIENT_CALL1: func=%p", f);
fitzhardinge98abfc72003-12-16 02:05:15 +0000955 else
njn2ac95242005-03-13 23:07:30 +0000956 SET_CLCALL_RETVAL(tid, f ( tid, arg[2] ), (Addr)f );
njn3e884182003-04-15 13:03:23 +0000957 break;
958 }
959 case VG_USERREQ__CLIENT_CALL2: {
njn2ac95242005-03-13 23:07:30 +0000960 UWord (*f)(ThreadId, UWord, UWord) = (void*)arg[1];
fitzhardinge98abfc72003-12-16 02:05:15 +0000961 if (f == NULL)
njn3d9edb22005-08-25 01:52:52 +0000962 VG_(message)(Vg_DebugMsg, "VG_USERREQ__CLIENT_CALL2: func=%p", f);
fitzhardinge98abfc72003-12-16 02:05:15 +0000963 else
njn2ac95242005-03-13 23:07:30 +0000964 SET_CLCALL_RETVAL(tid, f ( tid, arg[2], arg[3] ), (Addr)f );
njn3e884182003-04-15 13:03:23 +0000965 break;
966 }
967 case VG_USERREQ__CLIENT_CALL3: {
njn2ac95242005-03-13 23:07:30 +0000968 UWord (*f)(ThreadId, UWord, UWord, UWord) = (void*)arg[1];
fitzhardinge98abfc72003-12-16 02:05:15 +0000969 if (f == NULL)
njn3d9edb22005-08-25 01:52:52 +0000970 VG_(message)(Vg_DebugMsg, "VG_USERREQ__CLIENT_CALL3: func=%p", f);
fitzhardinge98abfc72003-12-16 02:05:15 +0000971 else
njn2ac95242005-03-13 23:07:30 +0000972 SET_CLCALL_RETVAL(tid, f ( tid, arg[2], arg[3], arg[4] ), (Addr)f );
njn3e884182003-04-15 13:03:23 +0000973 break;
974 }
975
njnf09745a2005-05-10 03:01:23 +0000976 // Nb: this looks like a circular definition, because it kind of is.
977 // See comment in valgrind.h to understand what's going on.
sewardj124ca2a2002-06-20 10:19:38 +0000978 case VG_USERREQ__RUNNING_ON_VALGRIND:
sewardjb5f6f512005-03-10 23:59:00 +0000979 SET_CLREQ_RETVAL(tid, RUNNING_ON_VALGRIND+1);
sewardj124ca2a2002-06-20 10:19:38 +0000980 break;
981
fitzhardinge39de4b42003-10-31 07:12:21 +0000982 case VG_USERREQ__PRINTF: {
983 int count =
nethercote3e901a22004-09-11 13:17:02 +0000984 VG_(vmessage)( Vg_ClientMsg, (char *)arg[1], (void*)arg[2] );
fitzhardinge39de4b42003-10-31 07:12:21 +0000985 SET_CLREQ_RETVAL( tid, count );
986 break; }
987
988 case VG_USERREQ__INTERNAL_PRINTF: {
989 int count =
njnaa3c26b2005-03-12 05:32:28 +0000990 VG_(vmessage)( Vg_DebugMsg, (char *)arg[1], (void*)arg[2] );
fitzhardinge39de4b42003-10-31 07:12:21 +0000991 SET_CLREQ_RETVAL( tid, count );
992 break; }
993
994 case VG_USERREQ__PRINTF_BACKTRACE: {
fitzhardinge39de4b42003-10-31 07:12:21 +0000995 int count =
nethercote3e901a22004-09-11 13:17:02 +0000996 VG_(vmessage)( Vg_ClientMsg, (char *)arg[1], (void*)arg[2] );
njnd01fef72005-03-25 23:35:48 +0000997 VG_(get_and_pp_StackTrace)( tid, VG_(clo_backtrace_size) );
fitzhardinge39de4b42003-10-31 07:12:21 +0000998 SET_CLREQ_RETVAL( tid, count );
999 break; }
1000
rjwalsh0140af52005-06-04 20:42:33 +00001001 case VG_USERREQ__STACK_REGISTER: {
njn945ed2e2005-06-24 03:28:30 +00001002 UWord sid = VG_(register_stack)((Addr)arg[1], (Addr)arg[2]);
rjwalsh0140af52005-06-04 20:42:33 +00001003 SET_CLREQ_RETVAL( tid, sid );
1004 break; }
1005
1006 case VG_USERREQ__STACK_DEREGISTER: {
njn945ed2e2005-06-24 03:28:30 +00001007 VG_(deregister_stack)(arg[1]);
rjwalsh0140af52005-06-04 20:42:33 +00001008 SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */
1009 break; }
1010
1011 case VG_USERREQ__STACK_CHANGE: {
njn945ed2e2005-06-24 03:28:30 +00001012 VG_(change_stack)(arg[1], (Addr)arg[2], (Addr)arg[3]);
rjwalsh0140af52005-06-04 20:42:33 +00001013 SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */
1014 break; }
1015
fitzhardinge98abfc72003-12-16 02:05:15 +00001016 case VG_USERREQ__GET_MALLOCFUNCS: {
1017 struct vg_mallocfunc_info *info = (struct vg_mallocfunc_info *)arg[1];
1018
njnfc51f8d2005-06-21 03:20:17 +00001019 info->tl_malloc = VG_(tdict).tool_malloc;
1020 info->tl_calloc = VG_(tdict).tool_calloc;
1021 info->tl_realloc = VG_(tdict).tool_realloc;
1022 info->tl_memalign = VG_(tdict).tool_memalign;
1023 info->tl___builtin_new = VG_(tdict).tool___builtin_new;
1024 info->tl___builtin_vec_new = VG_(tdict).tool___builtin_vec_new;
1025 info->tl_free = VG_(tdict).tool_free;
1026 info->tl___builtin_delete = VG_(tdict).tool___builtin_delete;
1027 info->tl___builtin_vec_delete = VG_(tdict).tool___builtin_vec_delete;
fitzhardinge98abfc72003-12-16 02:05:15 +00001028
njncf81d552005-03-31 04:52:26 +00001029 info->arena_payload_szB = VG_(arena_payload_szB);
njn088bfb42005-08-17 05:01:37 +00001030 info->mallinfo = VG_(mallinfo);
sewardjb5f6f512005-03-10 23:59:00 +00001031 info->clo_trace_malloc = VG_(clo_trace_malloc);
fitzhardinge98abfc72003-12-16 02:05:15 +00001032
1033 SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */
1034
1035 break;
1036 }
1037
njn25e49d8e72002-09-23 09:36:25 +00001038 /* Requests from the client program */
1039
1040 case VG_USERREQ__DISCARD_TRANSLATIONS:
1041 if (VG_(clo_verbosity) > 2)
1042 VG_(printf)( "client request: DISCARD_TRANSLATIONS,"
1043 " addr %p, len %d\n",
1044 (void*)arg[1], arg[2] );
1045
sewardjfa8ec112005-01-19 11:55:34 +00001046 VG_(discard_translations)( arg[1], arg[2] );
njn25e49d8e72002-09-23 09:36:25 +00001047
njnd3040452003-05-19 15:04:06 +00001048 SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */
njn25e49d8e72002-09-23 09:36:25 +00001049 break;
1050
njn47363ab2003-04-21 13:24:40 +00001051 case VG_USERREQ__COUNT_ERRORS:
nethercotef2b11482004-08-02 12:36:01 +00001052 SET_CLREQ_RETVAL( tid, VG_(get_n_errs_found)() );
njn47363ab2003-04-21 13:24:40 +00001053 break;
1054
sewardje663cb92002-04-12 10:26:32 +00001055 default:
njn9cb54ac2005-06-12 04:19:17 +00001056 if (os_client_request(tid, arg)) {
1057 // do nothing, os_client_request() handled it
sewardjb5f6f512005-03-10 23:59:00 +00001058 } else if (VG_(needs).client_requests) {
nethercoted1b64b22004-11-04 18:22:28 +00001059 UWord ret;
sewardj34042512002-10-22 04:14:35 +00001060
njn25e49d8e72002-09-23 09:36:25 +00001061 if (VG_(clo_verbosity) > 2)
fitzhardinge98abfc72003-12-16 02:05:15 +00001062 VG_(printf)("client request: code %x, addr %p, len %d\n",
njn25e49d8e72002-09-23 09:36:25 +00001063 arg[0], (void*)arg[1], arg[2] );
1064
njn51d827b2005-05-09 01:02:08 +00001065 if ( VG_TDICT_CALL(tool_handle_client_request, tid, arg, &ret) )
sewardjb5f6f512005-03-10 23:59:00 +00001066 SET_CLREQ_RETVAL(tid, ret);
njn25e49d8e72002-09-23 09:36:25 +00001067 } else {
sewardj34042512002-10-22 04:14:35 +00001068 static Bool whined = False;
1069
sewardjb5f6f512005-03-10 23:59:00 +00001070 if (!whined && VG_(clo_verbosity) > 2) {
nethercote7cc9c232004-01-21 15:08:04 +00001071 // Allow for requests in core, but defined by tools, which
njnd7994182003-10-02 13:44:04 +00001072 // have 0 and 0 in their two high bytes.
1073 Char c1 = (arg[0] >> 24) & 0xff;
1074 Char c2 = (arg[0] >> 16) & 0xff;
1075 if (c1 == 0) c1 = '_';
1076 if (c2 == 0) c2 = '_';
sewardj34042512002-10-22 04:14:35 +00001077 VG_(message)(Vg_UserMsg, "Warning:\n"
njnd7994182003-10-02 13:44:04 +00001078 " unhandled client request: 0x%x (%c%c+0x%x). Perhaps\n"
1079 " VG_(needs).client_requests should be set?\n",
1080 arg[0], c1, c2, arg[0] & 0xffff);
sewardj34042512002-10-22 04:14:35 +00001081 whined = True;
1082 }
njn25e49d8e72002-09-23 09:36:25 +00001083 }
sewardje663cb92002-04-12 10:26:32 +00001084 break;
1085 }
1086}
1087
1088
sewardj6072c362002-04-19 14:40:57 +00001089/* ---------------------------------------------------------------------
njn6676d5b2005-06-19 18:49:19 +00001090 Sanity checking (permanently engaged)
sewardj6072c362002-04-19 14:40:57 +00001091 ------------------------------------------------------------------ */
1092
sewardjb5f6f512005-03-10 23:59:00 +00001093/* Internal consistency checks on the sched structures. */
sewardj6072c362002-04-19 14:40:57 +00001094static
sewardjb5f6f512005-03-10 23:59:00 +00001095void scheduler_sanity ( ThreadId tid )
sewardj6072c362002-04-19 14:40:57 +00001096{
sewardjb5f6f512005-03-10 23:59:00 +00001097 Bool bad = False;
jsgf855d93d2003-10-13 22:26:55 +00001098
sewardjb5f6f512005-03-10 23:59:00 +00001099 if (!VG_(is_running_thread)(tid)) {
1100 VG_(message)(Vg_DebugMsg,
1101 "Thread %d is supposed to be running, but doesn't own run_sema (owned by %d)\n",
njnc7561b92005-06-19 01:24:32 +00001102 tid, VG_(running_tid));
sewardjb5f6f512005-03-10 23:59:00 +00001103 bad = True;
jsgf855d93d2003-10-13 22:26:55 +00001104 }
sewardj5f07b662002-04-23 16:52:51 +00001105
sewardjb5f6f512005-03-10 23:59:00 +00001106 if (VG_(gettid)() != VG_(threads)[tid].os_state.lwpid) {
1107 VG_(message)(Vg_DebugMsg,
njnd06ed472005-03-13 05:12:31 +00001108 "Thread %d supposed to be in LWP %d, but we're actually %d\n",
1109 tid, VG_(threads)[tid].os_state.lwpid, VG_(gettid)());
sewardjb5f6f512005-03-10 23:59:00 +00001110 bad = True;
sewardj5f07b662002-04-23 16:52:51 +00001111 }
sewardj6072c362002-04-19 14:40:57 +00001112}
1113
njn6676d5b2005-06-19 18:49:19 +00001114void VG_(sanity_check_general) ( Bool force_expensive )
1115{
1116 ThreadId tid;
1117
1118 VGP_PUSHCC(VgpCoreCheapSanity);
1119
1120 if (VG_(clo_sanity_level) < 1) return;
1121
1122 /* --- First do all the tests that we can do quickly. ---*/
1123
1124 sanity_fast_count++;
1125
1126 /* Check stuff pertaining to the memory check system. */
1127
1128 /* Check that nobody has spuriously claimed that the first or
1129 last 16 pages of memory have become accessible [...] */
1130 if (VG_(needs).sanity_checks) {
1131 VGP_PUSHCC(VgpToolCheapSanity);
1132 vg_assert(VG_TDICT_CALL(tool_cheap_sanity_check));
1133 VGP_POPCC(VgpToolCheapSanity);
1134 }
1135
1136 /* --- Now some more expensive checks. ---*/
1137
1138 /* Once every 25 times, check some more expensive stuff. */
1139 if ( force_expensive
1140 || VG_(clo_sanity_level) > 1
1141 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
1142
1143 VGP_PUSHCC(VgpCoreExpensiveSanity);
1144 sanity_slow_count++;
1145
njn6676d5b2005-06-19 18:49:19 +00001146 if (VG_(needs).sanity_checks) {
1147 VGP_PUSHCC(VgpToolExpensiveSanity);
1148 vg_assert(VG_TDICT_CALL(tool_expensive_sanity_check));
1149 VGP_POPCC(VgpToolExpensiveSanity);
1150 }
1151
njn6676d5b2005-06-19 18:49:19 +00001152 /* Look for stack overruns. Visit all threads. */
njnd666ea72005-06-26 17:26:22 +00001153 for (tid = 1; tid < VG_N_THREADS; tid++) {
njn6676d5b2005-06-19 18:49:19 +00001154 SSizeT remains;
1155
1156 if (VG_(threads)[tid].status == VgTs_Empty ||
1157 VG_(threads)[tid].status == VgTs_Zombie)
1158 continue;
1159
njnaf839f52005-06-23 03:27:57 +00001160 remains = VG_(stack_unused)(tid);
njn6676d5b2005-06-19 18:49:19 +00001161 if (remains < VKI_PAGE_SIZE)
1162 VG_(message)(Vg_DebugMsg,
1163 "WARNING: Thread %d is within %d bytes "
1164 "of running out of stack!",
1165 tid, remains);
1166 }
1167
njn6676d5b2005-06-19 18:49:19 +00001168 VGP_POPCC(VgpCoreExpensiveSanity);
1169 }
1170
1171 if (VG_(clo_sanity_level) > 1) {
1172 VGP_PUSHCC(VgpCoreExpensiveSanity);
1173 /* Check sanity of the low-level memory manager. Note that bugs
1174 in the client's code can cause this to fail, so we don't do
1175 this check unless specially asked for. And because it's
1176 potentially very expensive. */
1177 VG_(sanity_check_malloc_all)();
1178 VGP_POPCC(VgpCoreExpensiveSanity);
1179 }
1180 VGP_POPCC(VgpCoreCheapSanity);
1181}
sewardj6072c362002-04-19 14:40:57 +00001182
sewardje663cb92002-04-12 10:26:32 +00001183/*--------------------------------------------------------------------*/
njn278b3d62005-05-30 23:20:51 +00001184/*--- end ---*/
sewardje663cb92002-04-12 10:26:32 +00001185/*--------------------------------------------------------------------*/