blob: 8a975852a40ffc866241f4e5475861c44d1660e7 [file] [log] [blame]
jsgf855d93d2003-10-13 22:26:55 +00001
2/*--------------------------------------------------------------------*/
3/*--- Proxy LWP machinery. vg_proxylwp.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
9
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 Julian Seward
jsgf855d93d2003-10-13 22:26:55 +000011 jseward@acm.org
12
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
28 The GNU General Public License is contained in the file COPYING.
29*/
30
31
nethercotef1e5e152004-09-01 23:58:16 +000032#include "core.h"
jsgf855d93d2003-10-13 22:26:55 +000033
jsgf855d93d2003-10-13 22:26:55 +000034enum RequestType {
35 PX_BAD = -1,
36 PX_SetSigmask, /* sched->proxy; proxy->sched */
37 PX_RunSyscall, /* sched->proxy; proxy->sched */
38 PX_Signal, /* proxy->sched */
39 PX_SigACK, /* sched->proxy */
40 PX_Ping, /* use for sanity-checking */
41 PX_Exiting, /* reply sent by proxy for exit sync */
42};
43
jsgf855d93d2003-10-13 22:26:55 +000044
45#define VG_PROXY_MAGIC 0xef83b192
46struct ProxyLWP {
47 UInt magic; /* magic number */
48 ThreadId tid; /* scheduler's tid */
49 ThreadState *tst; /* thread state */
50 Int lwp; /* kernel's ID for LWP */
51 Int exitcode; /* ProxyLWP exit code */
52
53 Int topx, frommain; /* pipe fds */
nethercote73b526f2004-10-31 18:48:21 +000054 vki_siginfo_t siginfo; /* received signal */
jsgf855d93d2003-10-13 22:26:55 +000055 Bool terminating; /* in the middle of exiting */
56
57 /* State of proxy */
58 enum PXState state;
59
60 jmp_buf jumpbuf;
61};
62
fitzhardinge31ba9052004-01-16 02:15:23 +000063static void sys_wait_results(Bool block, ThreadId tid, enum RequestType reqtype, Bool restart);
jsgf855d93d2003-10-13 22:26:55 +000064
65struct PX_Request {
66 enum RequestType request;
67
nethercote73b526f2004-10-31 18:48:21 +000068 vki_sigset_t sigmask; /* sigmask applied by SigACK */
jsgf855d93d2003-10-13 22:26:55 +000069};
70
71/* All replies are multiplexed over a single pipe, so we need to disinguish them */
72struct PX_Reply {
73 ThreadId tid; /* tid this reply pertains to */
74 enum RequestType req; /* what this relates to */
75
76 union {
77 Int syscallno; /* system call completed */
nethercote73b526f2004-10-31 18:48:21 +000078 vki_siginfo_t siginfo; /* signal */
jseward4e6184d2003-12-22 22:53:35 +000079 } u;
jsgf855d93d2003-10-13 22:26:55 +000080};
81
82/* results pipe */
83static Int result_send = -1, result_recv = -1;
84
85/* reentrant printf for proxy use */
86#if 0
87static void px_printf(const Char *fmt, ...)
88{
89 Char buf[1024];
90 Char *cp = buf;
91 va_list vargs;
92
93 void addbuf(Char c) { *cp++ = c; }
94
95 cp += VG_(sprintf)(buf, "[%d, %d]: ", VG_(getpid)(), VG_(gettid)());
96
97 va_start(vargs,fmt);
98 VG_(vprintf)(addbuf, fmt, vargs);
99 va_end(vargs);
100 VG_(send_bytes_to_logging_sink)(buf, cp-buf);
101}
102#else
103static void px_printf(const Char *fmt, ...)
104{
105}
106#endif
107
108static const Char *pxs_name(enum PXState s)
109{
110 switch(s) {
111#define S(x) case PXS_##x: return #x
112 S(BAD);
113 S(WaitReq);
114 S(RunSyscall);
115 S(IntReply);
116 S(SysDone);
117 S(SigACK);
118#undef S
119 default: return "???";
120 }
121}
122
123static const Char *px_name(enum RequestType r)
124{
125 switch(r) {
126#define S(x) case PX_##x: return #x
127 S(BAD);
128 S(SetSigmask);
129 S(RunSyscall);
130 S(Signal);
131 S(SigACK);
132 S(Ping);
133 S(Exiting);
134#undef S
135 default: return "???";
136 }
137}
138
nethercote73b526f2004-10-31 18:48:21 +0000139#define PROXYLWP_OFFSET (VKI_PAGE_SIZE - sizeof(ProxyLWP))
jsgf855d93d2003-10-13 22:26:55 +0000140
141/*
142 Allocate a page for the ProxyLWP and its stack.
143
144 This uses the trick for finding the LWP's private data by knowing
145 that the stack is a single page, and that the ProxyLWP structure is
146 at the end of it. Therefore, given any %esp in the stack, you can
147 find the ProxyLWP structure (see LWP_TSD()).
148 */
149static ProxyLWP *LWP_alloc(void)
150{
nethercote73b526f2004-10-31 18:48:21 +0000151 UChar *p = VG_(get_memory_from_mmap)(VKI_PAGE_SIZE, "alloc_LWP");
jsgf855d93d2003-10-13 22:26:55 +0000152 ProxyLWP *ret;
fitzhardinge98abfc72003-12-16 02:05:15 +0000153 vg_assert(p == (UChar *)PGROUNDDN(p)); /* px must be page aligned */
jsgf855d93d2003-10-13 22:26:55 +0000154
155 ret = (ProxyLWP *)(p + PROXYLWP_OFFSET);
156
157 ret->magic = VG_PROXY_MAGIC;
158
159 return ret;
160}
161
162/* Free a thread structure */
163static void LWP_free(ProxyLWP *px)
164{
fitzhardinge98abfc72003-12-16 02:05:15 +0000165 UChar *p = (UChar *)PGROUNDDN(px);
jsgf855d93d2003-10-13 22:26:55 +0000166
167 vg_assert(px->magic == VG_PROXY_MAGIC);
168 px->magic = 0;
169 vg_assert((p + PROXYLWP_OFFSET) == (UChar *)px);
170
nethercote73b526f2004-10-31 18:48:21 +0000171 VG_(munmap)(p, VKI_PAGE_SIZE);
jsgf855d93d2003-10-13 22:26:55 +0000172}
173
174/* Get a particular ProxyLWP's LWP structure from its esp (relies on
175 stacks being page aligned, with the ProxyLWP structure at the
176 end). */
177static inline ProxyLWP *LWP_TSD(void *esp)
178{
fitzhardinge98abfc72003-12-16 02:05:15 +0000179 UChar *p = (UChar *)PGROUNDDN(esp);
jsgf855d93d2003-10-13 22:26:55 +0000180 ProxyLWP *ret;
181
182 ret = (ProxyLWP *)(p + PROXYLWP_OFFSET);
183 vg_assert(ret->magic == VG_PROXY_MAGIC);
184
185 return ret;
186}
187
188/* Get top of stack */
189static inline void *LWP_stack(ProxyLWP *px)
190{
191 vg_assert(px->magic == VG_PROXY_MAGIC);
192
193 return (void *)(((void **)px) - 1);
194}
195
196static void proxy_fork_cleanup(ThreadId tid);
197
198/* Init the proxy mechanism */
199void VG_(proxy_init)(void)
200{
201 Int p[2];
202 Int res;
203
204 /* this will ignore any duplicate registrations */
205 VG_(atfork)(NULL, NULL, proxy_fork_cleanup);
206
207 vg_assert(result_recv == -1);
208 vg_assert(result_send == -1);
209
210 res = VG_(pipe)(p);
211 vg_assert(res == 0);
212
213 result_recv = VG_(safe_fd)(p[0]);
214 result_send = VG_(safe_fd)(p[1]);
215
216 /* Make reading end non-blocking */
217 VG_(fcntl)(result_recv, VKI_F_SETFL, VKI_O_NONBLOCK);
218}
219
220/* After fork, the forking thread is in a strange state of having a
221 couple of pipes still linked to the parent. */
222static void proxy_fork_cleanup(ThreadId tid)
223{
224 ThreadId t;
225
226 VG_(close)(result_recv);
227 VG_(close)(result_send);
228
229 result_recv = result_send = -1;
230
231 VG_(proxy_init)();
232
233 for(t = 1; t < VG_N_THREADS; t++) {
234 ThreadState *tst = VG_(get_ThreadState)(t);
235 ProxyLWP *proxy = tst->proxy;
236
237 if (tst->status == VgTs_Empty) {
238 vg_assert(proxy == NULL);
239 continue;
240 }
241
242 vg_assert(proxy != NULL);
243
244 /* We need to do a manual teardown, since the proxy this structure
245 describes is our parent's */
246 VG_(close)(proxy->topx);
247 VG_(close)(proxy->frommain);
248
249 LWP_free(proxy);
250 tst->proxy = NULL;
251 }
252
fitzhardinge33730212003-11-10 21:21:00 +0000253 /* Create a proxy for calling thread.
254
255 Since fork() is non-blocking, the thread status should already
256 be Runnable.
jsgf855d93d2003-10-13 22:26:55 +0000257 */
fitzhardinge33730212003-11-10 21:21:00 +0000258 vg_assert(VG_(is_valid_tid)(tid));
259 vg_assert(VG_(threads)[tid].proxy == NULL);
260 vg_assert(VG_(threads)[tid].status == VgTs_Runnable);
jsgf855d93d2003-10-13 22:26:55 +0000261
fitzhardinge33730212003-11-10 21:21:00 +0000262 VG_(proxy_create)(tid);
263 VG_(proxy_setsigmask)(tid);
jsgf855d93d2003-10-13 22:26:55 +0000264}
265
266Int VG_(proxy_resfd)(void)
267{
268 return result_recv;
269}
270
271void VG_(proxy_shutdown)(void)
272{
273 VG_(close)(result_recv);
274 VG_(close)(result_send);
275
276 result_recv = result_send = -1;
277}
278
279/* This is called from within a proxy LWP signal handler. This
280 function records the siginfo, then longjmps back into the proxy
281 main state machine loop. The presumption is that the signal
282 handler is being run with all signals blocked; the longjmp is
283 there to make sure they stay masked until the application thread is
284 ready to run its signal handler. */
nethercote73b526f2004-10-31 18:48:21 +0000285void VG_(proxy_handlesig)(const vki_siginfo_t *siginfo, Addr ip, Int sysnum)
jsgf855d93d2003-10-13 22:26:55 +0000286{
287 UChar local;
288 ProxyLWP *px = LWP_TSD(&local);
jsgf855d93d2003-10-13 22:26:55 +0000289
290 vg_assert(siginfo->si_signo != 0);
291 if (px->siginfo.si_signo != 0) {
292 px_printf("proxy_handlesig: tid %d already has %d pending, new sig %d\n",
293 px->lwp, px->siginfo.si_signo, siginfo->si_signo);
294 }
295 vg_assert(px->siginfo.si_signo == 0);
296
297 px->siginfo = *siginfo;
298
299 px_printf("proxy got signal %d\n", siginfo->si_signo);
300
301 /* First look to see if the EIP is within our interesting ranges
302 near a syscall to work out what should happen. */
nethercote24e0d442004-10-18 17:36:40 +0000303 if (vga_sys_before <= ip && ip <= vga_sys_restarted) {
jsgf855d93d2003-10-13 22:26:55 +0000304 /* We are before the syscall actually ran, or it did run and
305 wants to be restarted. Either way, set the return code to
306 indicate a restart. This is not really any different from
307 anywhere else, except that we can make some assertions about
308 the proxy and machine state here. */
309 vg_assert(px->state == PXS_RunSyscall);
nethercotebb4222b2004-09-10 17:42:11 +0000310 vg_assert(PLATFORM_SYSCALL_RET(px->tst->arch) == -VKI_ERESTARTSYS);
nethercote24e0d442004-10-18 17:36:40 +0000311 } else if (vga_sys_after <= ip && ip <= vga_sys_done) {
jsgf855d93d2003-10-13 22:26:55 +0000312 /* We're after the syscall. Either it was interrupted by the
313 signal, or the syscall completed normally. In either case
nethercotee5a3e2b2004-10-13 14:42:57 +0000314 the usual register contains the correct syscall return value, and
315 the new state is effectively PXS_SysDone. */
fitzhardinge33730212003-11-10 21:21:00 +0000316 vg_assert(px->state == PXS_RunSyscall ||
317 px->state == PXS_SysDone);
jsgf855d93d2003-10-13 22:26:55 +0000318 px->state = PXS_SysDone;
nethercotee5a3e2b2004-10-13 14:42:57 +0000319 PLATFORM_SYSCALL_RET(px->tst->arch) = sysnum;
jsgf855d93d2003-10-13 22:26:55 +0000320 }
321 px_printf(" signalled in state %s\n", pxs_name(px->state));
322
323 __builtin_longjmp(px->jumpbuf, 1);
324}
325
326static Bool send_reply(const struct PX_Reply *reply)
327{
328 const Int size = sizeof(struct PX_Reply);
329
330 return VG_(write)(result_send, reply, size) == size;
331}
332
333static Bool recv_reply(struct PX_Reply *reply)
334{
335 const Int size = sizeof(struct PX_Reply);
336
337 return VG_(read)(result_recv, reply, size) == size;
338}
339
340/* Proxy LWP thread. This is run as a separate cloned() thread, so it
341 MUST NOT touch any core Valgrind data structures directly: the only
342 exception is while we're running a PX_RunSyscall command, we may
343 look at and update the thread's register state. It interacts with
344 the rest of Valgrind by receiving messages through its pipe and
345 sending results through result_send. */
346static Int proxylwp(void *v)
347{
348 ProxyLWP *px = (ProxyLWP *)v;
349 Int frommain = px->frommain;
350 ThreadState *tst = px->tst;
nethercote73b526f2004-10-31 18:48:21 +0000351 vki_sigset_t allsig;
352 vki_sigset_t appsigmask; /* signal mask the client has asked for */
fitzhardinge89f9a322003-10-30 07:25:59 +0000353 Int ret = 1000;
nethercote73b526f2004-10-31 18:48:21 +0000354 static const vki_stack_t ss = { .ss_flags = VKI_SS_DISABLE };
jsgf855d93d2003-10-13 22:26:55 +0000355
356 /* Block everything until we're told otherwise (LWP should have
357 been started with all signals blocked anyway) */
nethercote73b526f2004-10-31 18:48:21 +0000358 VG_(sigfillset)(&allsig);
359 VG_(sigdelset)(&allsig, VKI_SIGVGKILL); /* but allow SIGVGKILL to interrupt */
jsgf855d93d2003-10-13 22:26:55 +0000360
nethercote73b526f2004-10-31 18:48:21 +0000361 VG_(sigprocmask)(VKI_SIG_SETMASK, &allsig, NULL);
jsgf855d93d2003-10-13 22:26:55 +0000362
363 appsigmask = allsig;
364
365 /* no signal stack for us */
nethercote73b526f2004-10-31 18:48:21 +0000366 VG_(sigaltstack)(&ss, NULL);
jsgf855d93d2003-10-13 22:26:55 +0000367
368 for(;;) {
369 struct PX_Reply reply, sigreply;
370 struct PX_Request req;
371 Int res;
372
373 if (__builtin_setjmp(px->jumpbuf)) {
374 /* We were hit by a signal. This is the signal-driven part
375 of the state machine.
376
377 This code prepares a reply which is suitable for whatever
378 was interrupted by this signal. If "no reply" is the
379 right response, then it sets reply.req = PX_BAD.
380
381 NOTE: the ST:N notation represents the correspondence
382 between states where we can be interrupted in the main
383 state machine loop, and where those states are handled
384 here.
385 */
386
387 if (px->siginfo.si_signo != VKI_SIGVGKILL) {
388 /* First, send the signal info */
389 sigreply.tid = px->tid;
390 sigreply.req = PX_Signal;
jseward4e6184d2003-12-22 22:53:35 +0000391 sigreply.u.siginfo = px->siginfo;
jsgf855d93d2003-10-13 22:26:55 +0000392
393 if (!send_reply(&sigreply)) {
394 ret = 44; /* incomplete or failed write */
395 goto out;
396 }
397 } else {
398 /* We got VKI_SIGVGKILL, which means we just skip all the
fitzhardingeabab8392004-03-02 21:38:51 +0000399 below and exit. (Don't bother dealing with any pending
400 requests, because we'll probably just get confused.) */
jsgf855d93d2003-10-13 22:26:55 +0000401 px->state = PXS_WaitReq;
402 px->siginfo.si_signo = 0;
fitzhardingeabab8392004-03-02 21:38:51 +0000403 ret = 0;
404 goto out;
jsgf855d93d2003-10-13 22:26:55 +0000405 }
406
407 px->siginfo.si_signo = 0;
408
409 /* Now work out what our new state is, and what to do on the way. */
410 switch(px->state) {
411 case PXS_WaitReq:
412 /* We were interrupted while waiting for a request. See
413 if we had actually read the request, and do the
414 appropriate thing if so. */
415 reply.req = req.request;
416 reply.tid = px->tid;
417
418 switch(req.request) {
419 case PX_BAD:
420 /* ST:1 */
421 /* nothing read; just wait for SigACK */
422 px->state = PXS_SigACK;
423 break;
424
425 case PX_RunSyscall:
426 /* ST:2 */
427 /* They asked for a syscall, but we were signalled
428 before even getting started. Claim the syscall was
429 interrupted.
430
431 XXX how to distunguish between restartable and
432 non-restartable syscalls? Does it matter?
433 */
jseward4e6184d2003-12-22 22:53:35 +0000434 reply.u.syscallno = tst->syscallno;
jsgf855d93d2003-10-13 22:26:55 +0000435
nethercotebb4222b2004-09-10 17:42:11 +0000436 PLATFORM_SYSCALL_RET(tst->arch) = -VKI_ERESTARTSYS;
jsgf855d93d2003-10-13 22:26:55 +0000437 px->state = PXS_IntReply;
438 break;
439
440 case PX_SetSigmask:
441 /* ST:2 */
442 /* ST:3 */
443 /* They asked for a signal mask update. Ignore it,
444 because they're going to give us a new mask when
445 they send a SigACK, and we want all signals blocked
446 in the meantime. However, we set the state to
447 PXS_IntReply to make sure the reply from the
448 PX_SetSigmask is sent. */
449 vg_assert(reply.req == PX_SetSigmask);
450 px->state = PXS_IntReply;
451 break;
452
453 case PX_Ping:
454 /* ST:2 */
455 /* We read a Ping request, so we need to send a Ping
456 reply. */
457 vg_assert(reply.req == PX_Ping);
458 px->state = PXS_IntReply;
459 break;
460
461 case PX_Exiting:
462 case PX_Signal:
463 ret = 10; /* completely bogus - noone should send us a signal */
464 goto out;
465
466 case PX_SigACK:
467 ret = 11; /* Also bogus. No way we should get a
468 signal while waiting for a
469 SigACK. */
470 goto out;
471 }
472 break;
473
474 case PXS_RunSyscall:
475 /* ST:4 */
476 /* We were actually running the syscall when interrupted.
477 reply should already be set up, including return in eax. */
478 vg_assert(reply.req == PX_RunSyscall);
jseward4e6184d2003-12-22 22:53:35 +0000479 vg_assert(reply.u.syscallno == tst->syscallno);
jsgf855d93d2003-10-13 22:26:55 +0000480 vg_assert(tst->status == VgTs_WaitSys);
481 px->state = PXS_IntReply;
482 break;
483
484 case PXS_SysDone:
485 /* The syscall is done; we just need to send the results
486 back. */
487 vg_assert(reply.req == PX_RunSyscall);
jseward4e6184d2003-12-22 22:53:35 +0000488 vg_assert(reply.u.syscallno == tst->syscallno);
jsgf855d93d2003-10-13 22:26:55 +0000489 px->state = PXS_IntReply;
490 break;
491
492 case PXS_IntReply:
493 case PXS_SigACK:
494 ret = 13; /* Bogus. Same as ret=11 above. */
495 goto out;
496
497 case PXS_BAD:
498 ret = 33;
499 goto out;
500 }
501
502 /* End of signal handling states. If the scheduler LWP is
503 currently running application code, tell it to drop back
504 into the scheduler loop ASAP to handle the signal. */
505 if (VG_(clo_lowlat_signals))
506 VG_(need_resched)(px->tid);
507 }
508
fitzhardingeabab8392004-03-02 21:38:51 +0000509 /* state_machine: */
jsgf855d93d2003-10-13 22:26:55 +0000510 px_printf("proxylwp main: state %s\n", pxs_name(px->state));
511
512 switch(px->state) {
513 case PXS_WaitReq:
514 case PXS_SigACK:
515 req.request = PX_BAD; /* init request so we know if the read() read anything */
516
517 if (px->state == PXS_WaitReq) {
518 /* allow signals when waiting for a normal request */
nethercote73b526f2004-10-31 18:48:21 +0000519 VG_(sigprocmask)(VKI_SIG_SETMASK, &appsigmask, NULL);
jsgf855d93d2003-10-13 22:26:55 +0000520 }
521
522 /* ST:1 */
523
524 res = VG_(read)(frommain, &req, sizeof(req));
525
526 /* ST:2 */
527
528 /* process message with signals blocked */
nethercote73b526f2004-10-31 18:48:21 +0000529 VG_(sigprocmask)(VKI_SIG_SETMASK, &allsig, NULL);
jsgf855d93d2003-10-13 22:26:55 +0000530
fitzhardinge89f9a322003-10-30 07:25:59 +0000531 if (res == 0) {
532 ret = 0;
jsgf855d93d2003-10-13 22:26:55 +0000533 goto out; /* EOF - we're quitting */
fitzhardinge89f9a322003-10-30 07:25:59 +0000534 }
jsgf855d93d2003-10-13 22:26:55 +0000535
536 if (res < 0) {
537 px_printf("read(frommain) failed %d\n", res);
538 ret = 1; /* error */
539 goto out;
540 }
541 if (res != sizeof(req)) {
542 ret = 2; /* error - partial read */
543 goto out;
544 }
545
546 px_printf("read req: %s\n", px_name(req.request));
547
548 reply.tid = px->tid;
549 reply.req = req.request;
550
551 switch(req.request) {
552 case PX_Ping:
553 /* do nothing; just send reply */
554 break;
555
556 case PX_SigACK:
557 /* The thread ACKed the signal, and sent the mask they
558 want while running the handler. */
559 vg_assert(px->state == PXS_SigACK);
560 appsigmask = req.sigmask;
nethercote73b526f2004-10-31 18:48:21 +0000561 VG_(sigdelset)(&appsigmask, VKI_SIGVGKILL); /* but allow SIGVGKILL */
562 VG_(sigdelset)(&appsigmask, VKI_SIGVGINT); /* and SIGVGINT to interrupt */
jsgf855d93d2003-10-13 22:26:55 +0000563 px->state = PXS_WaitReq;
564 reply.req = PX_BAD; /* don't reply */
565 break;
566
567 case PX_SetSigmask:
568 appsigmask = req.sigmask;
nethercote73b526f2004-10-31 18:48:21 +0000569 VG_(sigdelset)(&appsigmask, VKI_SIGVGKILL); /* but allow SIGVGKILL */
570 VG_(sigdelset)(&appsigmask, VKI_SIGVGINT); /* and SIGVGINT to interrupt */
jsgf855d93d2003-10-13 22:26:55 +0000571
572 vg_assert(px->state == PXS_WaitReq ||
573 px->state == PXS_SigACK);
574
575 if (px->state != PXS_SigACK) {
576 /* If we're not waiting for a PX_SigACK, set the apps mask
577 to get at least one of the pending signals, which will
578 be delivered synchronously, so that some progress is
579 made before the we tell the client the mask has been
580 set.. Then reset the mask back to all blocked. */
nethercote73b526f2004-10-31 18:48:21 +0000581 VG_(sigprocmask)(VKI_SIG_SETMASK, &appsigmask, NULL);
jsgf855d93d2003-10-13 22:26:55 +0000582 /* ST:3 */
nethercote73b526f2004-10-31 18:48:21 +0000583 VG_(sigprocmask)(VKI_SIG_SETMASK, &allsig, NULL);
jsgf855d93d2003-10-13 22:26:55 +0000584 } else {
585 /* Waiting for SigACK. We want all signals blocked,
586 and when the SigACK arrives, it will give us the
587 thread's signal mask for its handler. */
588 }
589 break;
590
591 case PX_RunSyscall:
592 /* Run a syscall for our thread; results will be poked
593 back into tst */
jseward4e6184d2003-12-22 22:53:35 +0000594 reply.u.syscallno = tst->syscallno;
jsgf855d93d2003-10-13 22:26:55 +0000595
596 vg_assert(px->state == PXS_WaitReq ||
597 px->state == PXS_SigACK);
598 if (px->state == PXS_SigACK) {
599 /* If we're in the middle of signal handling, make the
600 client's syscalls fail with ERESTARTSYS until its signal
601 handler runs - there should be at most one, if it was
602 on the way to us as we got the signal.
603 */
604 px_printf("RunSyscall in SigACK: rejecting syscall %d with ERESTARTSYS\n",
jseward4e6184d2003-12-22 22:53:35 +0000605 reply.u.syscallno);
nethercotebb4222b2004-09-10 17:42:11 +0000606 PLATFORM_SYSCALL_RET(tst->arch) = -VKI_ERESTARTSYS;
jsgf855d93d2003-10-13 22:26:55 +0000607 } else {
fitzhardinge89f9a322003-10-30 07:25:59 +0000608 Int syscallno = tst->syscallno;
jsgf855d93d2003-10-13 22:26:55 +0000609
610 px->state = PXS_RunSyscall;
611 /* If we're interrupted before we get to the syscall
612 itself, we want the syscall restarted. */
nethercotebb4222b2004-09-10 17:42:11 +0000613 PLATFORM_SYSCALL_RET(tst->arch) = -VKI_ERESTARTSYS;
jsgf855d93d2003-10-13 22:26:55 +0000614
615 /* set our process group ID to match parent */
616 if (VG_(getpgrp)() != VG_(main_pgrp))
617 VG_(setpgid)(0, VG_(main_pgrp));
618
nethercote73b526f2004-10-31 18:48:21 +0000619 VG_(sigprocmask)(VKI_SIG_SETMASK, &appsigmask, NULL);
jsgf855d93d2003-10-13 22:26:55 +0000620
621 /* ST:4 */
622
nethercote6eb106b2004-10-18 17:41:36 +0000623 VGA_(thread_syscall)(syscallno, &tst->arch,
624 &px->state, PXS_SysDone);
jsgf855d93d2003-10-13 22:26:55 +0000625
626 /* ST:5 */
627
nethercote73b526f2004-10-31 18:48:21 +0000628 VG_(sigprocmask)(VKI_SIG_SETMASK, &allsig, NULL);
jsgf855d93d2003-10-13 22:26:55 +0000629 /* whew - made it here without being interrupted */
630 px->state = PXS_WaitReq;
631
632 if (VG_(clo_lowlat_syscalls))
633 VG_(need_resched)(px->tid);
634 }
635 break;
636
637 case PX_BAD:
638 case PX_Signal:
639 case PX_Exiting:
640 /* we never expect to see these */
641 ret = 3;
642 goto out;
643 }
644 break;
645
646 case PXS_IntReply:
647 /* This state only exists so that we fall out and write the
648 interrupted syscall reply before moving to SigACK */
649 px->state = PXS_SigACK;
650 break;
651
652 case PXS_RunSyscall:
653 case PXS_SysDone:
654 case PXS_BAD:
655 default:
656 /* Never expect to see these states here */
657 ret = 5;
658 goto out;
659 }
660
661 /* If we have something sensible to say, say it */
662 if (reply.req != PX_BAD) {
663 px_printf("sending reply %s\n", px_name(reply.req));
664
665 if (!send_reply(&reply)) {
666 ret = 4; /* error - didn't write full message */
667 goto out;
668 }
669 reply.req = PX_BAD;
670 }
671 }
672
673 out:
674 px_printf("proxy exiting with ret=%d\n", ret);
675
676 {
677 struct PX_Reply reply;
678 reply.req = PX_Exiting;
679 reply.tid = px->tid;
680 px_printf("exit: sending %s\n", px_name(reply.req));
681
682 send_reply(&reply);
683 }
684
685 px->frommain = -1;
686 VG_(close)(frommain);
687
688 px->exitcode = ret;
689 return ret;
690}
691
692/* Send a signal to a proxy LWP */
693void VG_(proxy_sendsig)(ThreadId tid, Int sig)
694{
695 ThreadState *tst = VG_(get_ThreadState)(tid);
696 ProxyLWP *proxy = tst->proxy;
697 Int lwp;
698
699 if (proxy == NULL)
700 return;
701
702 lwp = proxy->lwp; /* proxy->lwp may change async */
703
704 if (lwp != 0) {
705 /* SIGKILL and SIGSTOP always apply to all threads (need to
706 route for route_signals case?) */
707 if (sig == VKI_SIGKILL || sig == VKI_SIGSTOP)
nethercote73b526f2004-10-31 18:48:21 +0000708 VG_(kill)(VG_(main_pid), sig);
jsgf855d93d2003-10-13 22:26:55 +0000709 else
nethercote73b526f2004-10-31 18:48:21 +0000710 VG_(tkill)(lwp, sig);
jsgf855d93d2003-10-13 22:26:55 +0000711 }
712
713 /* If a thread is sending a signal to itself and the signal isn't
714 blocked (ie, it will be delivered), wait until the signal
715 message gets sent back, thus making the signal synchronous. */
716 if (sig != 0 &&
717 !VG_(is_sig_ign)(sig) &&
718 tid == VG_(get_current_or_recent_tid)() &&
nethercote73b526f2004-10-31 18:48:21 +0000719 !VG_(sigismember)(&tst->eff_sig_mask, sig)) {
jsgf855d93d2003-10-13 22:26:55 +0000720 /* If the LWP is actually blocked in a sigtimedwait, then it
721 will eat the signal rather than make it pending and deliver
722 it by the normal mechanism. In this case, just wait for the
723 syscall to dinish. */
724 if (tst->status == VgTs_WaitSys && tst->syscallno == __NR_rt_sigtimedwait)
fitzhardinge31ba9052004-01-16 02:15:23 +0000725 sys_wait_results(True, tid, PX_RunSyscall, True);
jsgf855d93d2003-10-13 22:26:55 +0000726 else
fitzhardinge31ba9052004-01-16 02:15:23 +0000727 sys_wait_results(True, tid, PX_Signal, True);
jsgf855d93d2003-10-13 22:26:55 +0000728 }
729}
730
731/* If a thread is blocked in a syscall, this function will interrupt
732 the proxy LWP's syscall by hitting it with a VKI_SIGVGINT signal.
733 This signal will not be reported to the client application. */
734void VG_(proxy_abort_syscall)(ThreadId tid)
735{
736 ThreadState *tst = VG_(get_ThreadState)(tid);
737 ProxyLWP *proxy = tst->proxy;
738 Int lwp;
739
740 if (tst->status != VgTs_WaitSys)
741 return;
742
743 vg_assert(proxy != NULL);
744
745 lwp = proxy->lwp;
746
747 if (lwp != 0)
nethercote73b526f2004-10-31 18:48:21 +0000748 VG_(tkill)(lwp, VKI_SIGVGINT);
jsgf855d93d2003-10-13 22:26:55 +0000749
fitzhardinge31ba9052004-01-16 02:15:23 +0000750 sys_wait_results(True, tid, PX_RunSyscall, False);
jsgf855d93d2003-10-13 22:26:55 +0000751
752 vg_assert(tst->status == VgTs_Runnable);
753}
754
755static Int do_futex(void *addr, Int op, Int val, struct vki_timespec *time, void *addr2)
756{
757 return VG_(do_syscall)(__NR_futex, addr, op, val, time, addr2);
758}
759
mueller2822eba2003-11-27 02:16:41 +0000760static Int have_settid = -1; /* -1 -> unknown */
jsgf855d93d2003-10-13 22:26:55 +0000761
762/*
763 Create a proxy LWP using whatever varient of clone makes the most
764 sense for the current kernel. We use futexes for termination
765 notification wherever possible. Returns 0 on success, or a -ve
766 error code on failure.
767*/
768static Int proxy_clone(ProxyLWP *proxy)
769{
fitzhardinge40d239c2003-11-27 08:11:10 +0000770 Int ret = -1;
771
mueller2822eba2003-11-27 02:16:41 +0000772 if (have_settid != 0) {
jsgf855d93d2003-10-13 22:26:55 +0000773 ret = VG_(clone)(proxylwp,
774 LWP_stack(proxy),
775 VKI_CLONE_FS | VKI_CLONE_FILES | VKI_CLONE_VM |
fitzhardinge40d239c2003-11-27 08:11:10 +0000776 VKI_CLONE_SIGHAND | VKI_CLONE_THREAD |
777 VKI_CLONE_PARENT_SETTID |
778 VKI_CLONE_CHILD_CLEARTID | VKI_CLONE_DETACHED,
jsgf855d93d2003-10-13 22:26:55 +0000779 proxy, &proxy->lwp, &proxy->lwp);
fitzhardinge40d239c2003-11-27 08:11:10 +0000780
781 if ( have_settid == -1 && (ret < 0 || proxy->lwp == 0) ) {
mueller2822eba2003-11-27 02:16:41 +0000782 have_settid = 0;
fitzhardinge40d239c2003-11-27 08:11:10 +0000783
784 /* Assume that not having parent_settid also means that we've
785 got 2.4-style signal handling, which means we need to do
786 more work. */
787 VG_(do_signal_routing) = True;
788
789 if (ret > 0) {
790 /* If clone actually succeeded and just ignored the
791 CLONE_PARENT_SETTID flag, then use the LWP it created
792 for us. */
793 proxy->lwp = ret;
794 }
mueller2822eba2003-11-27 02:16:41 +0000795 }
muellere9840282003-11-27 09:07:47 +0000796 else
797 have_settid = 1;
fitzhardinge40d239c2003-11-27 08:11:10 +0000798 }
799
800 if (ret < 0) {
801 vg_assert(have_settid == 0);
muellere9840282003-11-27 09:07:47 +0000802 vg_assert(proxy->lwp == 0);
fitzhardinge40d239c2003-11-27 08:11:10 +0000803
jsgf855d93d2003-10-13 22:26:55 +0000804 ret = VG_(clone)(proxylwp,
805 LWP_stack(proxy),
806 VKI_CLONE_FS | VKI_CLONE_FILES | VKI_CLONE_VM |
807 VKI_CLONE_SIGHAND | VKI_CLONE_THREAD,
808 proxy, NULL, NULL);
809 proxy->lwp = ret;
810 }
811
812 return (ret < 0) ? ret : 0;
813}
814
815/* Wait on a proxy LWP. Returns True if the LWP has exited. */
816static Bool proxy_wait(ProxyLWP *proxy, Bool block, Int *status)
817{
818 Bool ret = False;
819
mueller2822eba2003-11-27 02:16:41 +0000820 if (have_settid == -1)
jsgf855d93d2003-10-13 22:26:55 +0000821 return False;
822
mueller2822eba2003-11-27 02:16:41 +0000823 if (have_settid) {
jsgf855d93d2003-10-13 22:26:55 +0000824 if (block) {
825 Int lwp = proxy->lwp;
826
muellere9840282003-11-27 09:07:47 +0000827
mueller2822eba2003-11-27 02:16:41 +0000828 if(proxy->lwp != 0)
jsgf855d93d2003-10-13 22:26:55 +0000829 do_futex(&proxy->lwp, VKI_FUTEX_WAIT, lwp, NULL, NULL);
830
831 if (status)
832 *status = proxy->exitcode;
833 ret = True;
834 } else {
835 if (proxy->lwp == 0) {
836 *status = proxy->exitcode;
837 ret = True;
838 }
839 }
840 } else {
nethercote73b526f2004-10-31 18:48:21 +0000841 Int flags = __VKI_WCLONE;
jsgf855d93d2003-10-13 22:26:55 +0000842 Int res;
843
844 if (!block)
845 flags |= VKI_WNOHANG;
846 res = VG_(waitpid)(proxy->lwp, status, flags);
847 if (res == proxy->lwp) {
848 vg_assert(*status == proxy->exitcode);
849 ret = True;
850 }
851 }
852
853 return ret;
854}
855
856/* Create a proxy for a new thread */
857void VG_(proxy_create)(ThreadId tid)
858{
859 ThreadState *tst = VG_(get_ThreadState)(tid);
860 ProxyLWP *proxy;
861 Int p[2];
nethercote73b526f2004-10-31 18:48:21 +0000862 vki_sigset_t mask;
jsgf855d93d2003-10-13 22:26:55 +0000863 Int ret;
864
865 vg_assert(tst->proxy == NULL);
866 vg_assert(tst->status == VgTs_Runnable);
867
868 proxy = LWP_alloc();
869
870 VG_(pipe)(p);
871
nethercote418dfc52004-11-01 16:46:58 +0000872 proxy->tid = tid;
873 proxy->tst = tst;
874 proxy->exitcode = 0;
875 proxy->lwp = 0;
jsgf855d93d2003-10-13 22:26:55 +0000876 proxy->siginfo.si_signo = 0;
nethercote418dfc52004-11-01 16:46:58 +0000877 proxy->frommain = VG_(safe_fd)(p[0]);
878 proxy->topx = VG_(safe_fd)(p[1]);
879 proxy->state = PXS_WaitReq; /* start by waiting for requests */
880 proxy->terminating = False;
jsgf855d93d2003-10-13 22:26:55 +0000881
882 /* Make sure proxy LWP starts with all signals blocked (not even
883 SEGV, BUS, ILL or FPE) */
884 VG_(block_all_host_signals)(&mask);
885
886 ret = proxy_clone(proxy);
nethercote5fd72bb2004-11-04 19:28:38 +0000887
jsgf855d93d2003-10-13 22:26:55 +0000888 if (ret < 0) {
nethercote5fd72bb2004-11-04 19:28:38 +0000889 VG_(printf)("Error %d trying to create proxy LWP for tid %d\n",
890 ret, tid);
891 VG_(core_panic)("Can't start proxy LWPs");
jsgf855d93d2003-10-13 22:26:55 +0000892 }
893
894 VG_(restore_all_host_signals)(&mask);
895
896 tst->proxy = proxy;
897}
898
899/* Clean up proxy after thread dies */
900void VG_(proxy_delete)(ThreadId tid, Bool force)
901{
902 ThreadState *tst = VG_(get_ThreadState)(tid);
903 ProxyLWP *proxy = tst->proxy;
904 Bool res;
905 Int status;
906 Int lwp;
907
908 if (proxy == NULL)
909 return; /* nothing to do */
910
911 lwp = proxy->lwp;
912
913#if 0
914 MAYBE_PRINTF("VG_(proxy_delete)(tid=%d (lwp=%d), force=%s; tst->status=%d\n",
915 tid, lwp, force ? "true" : "false", tst->status);
916#endif
917 vg_assert(proxy->tid == tid);
918 if (proxy->terminating)
919 return; /* already going away */
920
921 proxy->terminating = True;
922
923 VG_(close)(proxy->topx);
924 proxy->topx = -1;
925
926 /* proxy thread will close proxy->frommain itself */
927
928 if (force && lwp != 0) {
929 /* wouldn't need to force it if it were already dead */
930 vg_assert(tst->status != VgTs_Empty);
931 //VG_(printf)("kill %d with SIGVGKILL\n", lwp);
nethercote73b526f2004-10-31 18:48:21 +0000932 VG_(tkill)(lwp, VKI_SIGVGKILL);
jsgf855d93d2003-10-13 22:26:55 +0000933 } else
934 vg_assert(tst->status == VgTs_Empty); /* just killed */
935
936 status = -1;
937 res = False;
938
939 /* We need to wait for the PX_Exiting message before doing the
940 proxy_wait, because if we don't read the results pipe, the proxy
941 may be blocked writing to it, causing a deadlock with us as we
942 wait for it to exit. */
fitzhardinge31ba9052004-01-16 02:15:23 +0000943 sys_wait_results(True, tid, PX_Exiting, True);
jsgf855d93d2003-10-13 22:26:55 +0000944 res = proxy_wait(proxy, True, &status);
945
nethercote57205dc2003-11-13 16:49:22 +0000946 if ((!res || status != 0) && VG_(clo_verbosity) > 1)
jsgf855d93d2003-10-13 22:26:55 +0000947 VG_(printf)("proxy %d for tid %d exited status %d, res %d\n",
948 lwp, tid, status, res);
949
950 LWP_free(proxy);
951 tst->proxy = NULL;
952}
953
954/* Read back the results of any completed syscalls.
955
956 At this point, there should be only one pending syscall per thread.
957 Those threads should be in VgTs_WaitSys state. Each syscall return
958 may have multiple signals associated with it, so we read those and
959 set up some pending signals in our signal simulation. When we
960 finally get the message saying the syscall is complete, we mark the
961 thread as runnable and return.
962
963 If block is set to True, then this call will block until anything
964 happens (ie, some progress was made).
965
966 If reqtype != PX_BAD, then this will block until some reply for
967 that request type appears (assuming you're expecting that kind of
968 reply, otherwise it will block forever). If tid != 0, then it will
969 wait for a reply for that particular tid.
970 */
fitzhardinge31ba9052004-01-16 02:15:23 +0000971static void sys_wait_results(Bool block, ThreadId tid, enum RequestType reqtype, Bool restart)
jsgf855d93d2003-10-13 22:26:55 +0000972{
973 Bool found_reply = (reqtype == PX_BAD);
974 struct PX_Reply res;
975
976 vg_assert(VG_(gettid)() == VG_(main_pid));
977
978 do {
979 if (reqtype != PX_BAD || block) {
980 /* wait for activity on recv_res */
981 struct vki_pollfd pollfd;
982 Int ret;
983
984 /* result_recv could be -1 if we're asking for results before any
985 syscalls are issued - which is OK - but we can't block on
986 it. */
987 vg_assert(result_recv != -1);
988
989 pollfd.fd = result_recv;
990 pollfd.events = VKI_POLLIN;
991
992 do {
993 ret = VG_(poll)(&pollfd, 1, -1);
994 } while(ret == -VKI_EINTR);
995
996 if (ret <= 0) {
997 VG_(printf)("sys_wait_results: poll failed fd=%d errno=%d\n",
998 pollfd.fd, ret);
999 return;
1000 }
1001 }
1002
1003 while(recv_reply(&res)) {
1004 ThreadState *tst;
1005
1006 if (reqtype != PX_BAD &&
1007 res.req == reqtype &&
1008 (tid == 0 || tid == res.tid))
1009 found_reply = True;
1010
1011 tst = VG_(get_ThreadState)(res.tid);
1012
1013 switch(res.req) {
1014 case PX_SetSigmask:
1015 /* Don't need to do anything */
1016 if (VG_(clo_trace_signals) || VG_(clo_trace_syscalls))
nethercoteef0c7662004-11-06 15:38:43 +00001017 VG_(printf)("sys_wait_results: got PX_SetSigmask for TID %d\n",
jsgf855d93d2003-10-13 22:26:55 +00001018 res.tid);
1019 break;
1020
1021 case PX_RunSyscall:
1022 if (VG_(clo_trace_syscalls))
nethercoteef0c7662004-11-06 15:38:43 +00001023 VG_(printf)("sys_wait_results: got PX_RunSyscall for SYSCALL[%d,%d](%3d) --> %lld (%llx)\n",
1024 VG_(getpid)(), res.tid, tst->syscallno,
1025 (Long)(Word)PLATFORM_SYSCALL_RET(tst->arch),
1026 (ULong)PLATFORM_SYSCALL_RET(tst->arch));
jsgf855d93d2003-10-13 22:26:55 +00001027
1028 if (tst->status != VgTs_WaitSys)
1029 VG_(printf)("tid %d in status %d\n",
1030 tst->tid, tst->status);
1031
jseward4e6184d2003-12-22 22:53:35 +00001032 vg_assert(res.u.syscallno == tst->syscallno);
jsgf855d93d2003-10-13 22:26:55 +00001033 vg_assert(tst->status == VgTs_WaitSys);
1034
fitzhardinge31ba9052004-01-16 02:15:23 +00001035 VG_(post_syscall)(res.tid, restart);
jsgf855d93d2003-10-13 22:26:55 +00001036 break;
1037
1038 case PX_Signal:
thughes8abf3922004-10-16 10:59:49 +00001039 if (VG_(do_signal_routing) &&
1040 res.u.siginfo.si_code == VKI_SI_USER &&
1041 res.u.siginfo._sifields._kill._pid == VG_(getpid)()) {
1042 Int ptr = tst->sigqueue_tail;
1043
1044 while (tst->sigqueue[ptr].si_signo != res.u.siginfo.si_signo) {
1045 vg_assert(ptr != tst->sigqueue_head);
1046 ptr = (ptr + 1) % VG_N_SIGNALQUEUE;
1047 }
1048
1049 res.u.siginfo = tst->sigqueue[ptr];
1050 tst->sigqueue[ptr].si_signo = 0;
1051
1052 while (tst->sigqueue_tail != tst->sigqueue_head &&
1053 tst->sigqueue[tst->sigqueue_tail].si_signo == 0) {
1054 tst->sigqueue_tail = (tst->sigqueue_tail + 1) % VG_N_SIGNALQUEUE;
1055 }
1056 }
1057
1058 if (VG_(clo_trace_signals) || VG_(clo_trace_syscalls))
nethercoteef0c7662004-11-06 15:38:43 +00001059 VG_(printf)("sys_wait_results: got PX_Signal for TID %d, signal %d\n",
1060 res.tid, res.u.siginfo.si_signo);
jsgf855d93d2003-10-13 22:26:55 +00001061
jseward4e6184d2003-12-22 22:53:35 +00001062 vg_assert(res.u.siginfo.si_signo != 0);
jsgf855d93d2003-10-13 22:26:55 +00001063 if (VG_(threads)[res.tid].proxy &&
1064 !VG_(threads)[res.tid].proxy->terminating)
jseward4e6184d2003-12-22 22:53:35 +00001065 VG_(deliver_signal)(res.tid, &res.u.siginfo, True);
jsgf855d93d2003-10-13 22:26:55 +00001066 break;
1067
1068 case PX_Ping:
1069 /* Got a ping response. Great. */
1070 break;
1071
1072 case PX_Exiting:
1073 /* They're exiting. Hooray! */
1074 break;
1075
1076 case PX_BAD:
1077 case PX_SigACK:
1078 default:
1079 VG_(core_panic)("sys_wait_results: got PX_BAD/PX_SigACK!\n");
1080 }
1081 }
1082 } while(!found_reply);
1083}
1084
1085/* External version */
1086void VG_(proxy_results)(void)
1087{
fitzhardinge31ba9052004-01-16 02:15:23 +00001088 sys_wait_results(False, 0, PX_BAD, True);
jsgf855d93d2003-10-13 22:26:55 +00001089}
1090
fitzhardinge31ba9052004-01-16 02:15:23 +00001091void VG_(proxy_wait_sys)(ThreadId tid, Bool restart)
fitzhardingea09a1b52003-11-07 23:09:48 +00001092{
1093 ThreadState *tst = VG_(get_ThreadState)(tid);
1094
1095 vg_assert(tst->status == VgTs_WaitSys);
1096
fitzhardinge31ba9052004-01-16 02:15:23 +00001097 sys_wait_results(True, tid, PX_RunSyscall, restart);
fitzhardingea09a1b52003-11-07 23:09:48 +00001098}
1099
jsgf855d93d2003-10-13 22:26:55 +00001100/* Tell proxy about it's thread's updated signal mask */
1101void VG_(proxy_setsigmask)(ThreadId tid)
1102{
1103 ThreadState *tst = VG_(get_ThreadState)(tid);
1104 ProxyLWP *proxy = tst->proxy;
1105 Int res;
1106 struct PX_Request req;
1107
1108 vg_assert(proxy != NULL);
1109 vg_assert(proxy->tid == tid);
1110
1111 req.request = PX_SetSigmask;
1112 req.sigmask = tst->sig_mask;
1113
1114 tst->eff_sig_mask = tst->sig_mask;
1115
1116 /* clear the results pipe before we try to write to a proxy to
1117 prevent a deadlock */
1118 VG_(proxy_results)();
1119 res = VG_(write)(proxy->topx, &req, sizeof(req));
1120 vg_assert(res == sizeof(req));
1121
1122 /* wait for proxy to ack mask update; mask changes don't really
1123 have to be synchronous, but they do have to be fully ordered
1124 with respect to each other (ie, if thread A then thread B
1125 updates their signal masks, A's update must be done before B's
1126 is). */
fitzhardinge31ba9052004-01-16 02:15:23 +00001127 sys_wait_results(True, tid, PX_SetSigmask, True);
jsgf855d93d2003-10-13 22:26:55 +00001128}
1129
nethercote73b526f2004-10-31 18:48:21 +00001130void VG_(proxy_sigack)(ThreadId tid, const vki_sigset_t *mask)
jsgf855d93d2003-10-13 22:26:55 +00001131{
1132 ThreadState *tst = VG_(get_ThreadState)(tid);
1133 ProxyLWP *proxy = tst->proxy;
1134 Int res;
1135 struct PX_Request req;
1136
1137 vg_assert(proxy != NULL);
1138 vg_assert(proxy->tid == tid);
1139
1140 if (proxy_wait(proxy, False, NULL))
1141 return;
1142
1143 req.request = PX_SigACK;
1144 req.sigmask = *mask;
1145
1146 tst->eff_sig_mask = *mask;
1147
1148#if 0
1149 /* Clear the results pipe before we try to write to a proxy to
1150 prevent a deadlock.
1151
1152 XXX this breaks things. This is called as a result of a
1153 PX_Signal message, and is called from within sys_wait_results.
1154 If that sys_wait_results was blocking of a particular message,
1155 it will never wake up if we eat those messages by calling
1156 sys_wait_results ourselves from here. Maybe make
1157 sys_wait_results non-recursive?
1158 */
1159 VG_(proxy_results)();
1160#endif
1161
1162 res = VG_(write)(proxy->topx, &req, sizeof(req));
1163 vg_assert(res == sizeof(req));
1164}
1165
1166/* Wait for a signal to be delivered to any thread */
1167void VG_(proxy_waitsig)(void)
1168{
1169 if (VG_(do_signal_routing))
1170 VG_(route_signals)();
1171 else
fitzhardinge31ba9052004-01-16 02:15:23 +00001172 sys_wait_results(True, VG_INVALID_THREADID /* any */, PX_Signal, True);
jsgf855d93d2003-10-13 22:26:55 +00001173}
1174
1175/* Issue a syscall to the thread's ProxyLWP */
1176Int VG_(sys_issue)(int tid)
1177{
1178 ThreadState *tst = VG_(get_ThreadState)(tid);
1179 ProxyLWP *proxy = tst->proxy;
1180 Int res;
1181 struct PX_Request req;
1182
1183 vg_assert(proxy != NULL);
1184 vg_assert(proxy->tid == tid);
fitzhardingea09a1b52003-11-07 23:09:48 +00001185 vg_assert(tst->status == VgTs_WaitSys);
1186
1187 /* Clear the results pipe before we try to write to a proxy to
1188 prevent a deadlock (the proxyLWP may be trying to write a result
1189 back to the scheduler LWP, and therefore not be reading its
1190 input pipe, which would then block the write below).
1191
1192 XXX I think this can't happen - the pipe has 4k of buffering,
1193 and can therefore fit many messages, but we can only have one
1194 outstanding - the write below will not block forever. Fetching
1195 results here can cause all kinds of confusion, because we
1196 definitely don't want the complexity of trying to deliver a
1197 signal right now.
1198 */
1199 if (0)
1200 VG_(proxy_results)();
jsgf855d93d2003-10-13 22:26:55 +00001201
1202 req.request = PX_RunSyscall;
fitzhardinge89f9a322003-10-30 07:25:59 +00001203
nethercotebb4222b2004-09-10 17:42:11 +00001204 tst->syscallno = PLATFORM_SYSCALL_NUM(tst->arch);
1205 PLATFORM_SYSCALL_RET(tst->arch) = -VKI_ERESTARTSYS;
fitzhardinge89f9a322003-10-30 07:25:59 +00001206
jsgf855d93d2003-10-13 22:26:55 +00001207 res = VG_(write)(proxy->topx, &req, sizeof(req));
1208
1209 if (res != sizeof(req)) {
fitzhardingea09a1b52003-11-07 23:09:48 +00001210 VG_(message)(Vg_DebugMsg, "sys_issue: write to tid %d failed %d (not %d)\n",
1211 tid, res, sizeof(req));
jsgf855d93d2003-10-13 22:26:55 +00001212 }
1213 return 0;
1214}
1215
1216/* Relatively expensive sanity tests for the syscall machinery */
nethercote885dd912004-08-03 23:14:00 +00001217void VG_(sanity_check_proxy)(void)
jsgf855d93d2003-10-13 22:26:55 +00001218{
1219 Int tid;
1220 Bool sane = True;
1221 static const struct PX_Request req = { .request = PX_Ping };
1222
1223 for(tid = 0; tid < VG_N_THREADS; tid++) {
1224 ThreadState *tst = &VG_(threads)[tid];
1225 ProxyLWP *px;
mueller2822eba2003-11-27 02:16:41 +00001226 Int status = 0;
jsgf855d93d2003-10-13 22:26:55 +00001227 Int ret;
1228
1229 if (tst->status == VgTs_Empty)
1230 continue;
1231
1232 if (tst->proxy == NULL) {
fitzhardinge89f9a322003-10-30 07:25:59 +00001233 VG_(message)(Vg_DebugMsg, "TID %d: NULL proxy");
jsgf855d93d2003-10-13 22:26:55 +00001234 sane = False;
1235 continue;
1236 }
1237
1238 px = tst->proxy;
1239
1240 if (px->tid != tid) {
fitzhardinge89f9a322003-10-30 07:25:59 +00001241 VG_(message)(Vg_DebugMsg,
1242 "TID %d: proxy LWP %d doesn't have right tid (%d)\n",
1243 tid, px->lwp, px->tid);
jsgf855d93d2003-10-13 22:26:55 +00001244 sane = False;
1245 }
1246
1247 if (proxy_wait(px, False, &status)) {
fitzhardinge89f9a322003-10-30 07:25:59 +00001248 VG_(message)(Vg_DebugMsg,
1249 "TID %d: proxy LWP %d exited with status %d\n",
1250 tid, px->lwp, status);
jsgf855d93d2003-10-13 22:26:55 +00001251 sane = False;
1252 continue;
1253 }
1254
1255 /* No point checking if proxy is busy in a syscall, but all
1256 other times it should respond promptly. */
1257 if (tst->status != VgTs_WaitSys) {
1258 ret = VG_(write)(px->topx, &req, sizeof(req));
1259 if (ret != sizeof(req)) {
fitzhardinge89f9a322003-10-30 07:25:59 +00001260 VG_(message)(Vg_DebugMsg,
1261 "TID %d: failed to write PX_Ping to lwp %d: %d\n",
1262 tid, px->lwp, ret);
jsgf855d93d2003-10-13 22:26:55 +00001263 sane = False;
1264 }
fitzhardinge31ba9052004-01-16 02:15:23 +00001265 sys_wait_results(True, tid, PX_Ping, True);
jsgf855d93d2003-10-13 22:26:55 +00001266 /* Can't make an assertion here, fortunately; this will
1267 either come back or it won't. */
1268 }
1269 }
1270
1271 vg_assert(sane);
1272}
1273
fitzhardinge47735af2004-01-21 01:27:27 +00001274/* Get the PID/TID of the ProxyLWP. */
nethercote85cdd342004-08-01 22:36:40 +00001275__attribute__((unused))
1276static Int proxy_id(ThreadId tid)
fitzhardinge47735af2004-01-21 01:27:27 +00001277{
1278 ThreadState *tst = VG_(get_ThreadState)(tid);
nethercote85cdd342004-08-01 22:36:40 +00001279 return tst->proxy->lwp;
fitzhardinge47735af2004-01-21 01:27:27 +00001280}
1281
jsgf855d93d2003-10-13 22:26:55 +00001282/*--------------------------------------------------------------------*/
1283/*--- Proxy LWP machinery. vg_proxylwp.c ---*/
1284/*--------------------------------------------------------------------*/