]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
These files are no longer needed. Bye!
authorJulian Seward <jseward@acm.org>
Fri, 11 Mar 2005 00:22:10 +0000 (00:22 +0000)
committerJulian Seward <jseward@acm.org>
Fri, 11 Mar 2005 00:22:10 +0000 (00:22 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3266

coregrind/vg_proxylwp.c [deleted file]
docs/proxylwp.sxw [deleted file]
memcheck/mc_from_ucode.c [deleted file]

diff --git a/coregrind/vg_proxylwp.c b/coregrind/vg_proxylwp.c
deleted file mode 100644 (file)
index 419879b..0000000
+++ /dev/null
@@ -1,1321 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Proxy LWP machinery.                           vg_proxylwp.c ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Valgrind, a dynamic binary instrumentation
-   framework.
-
-   Copyright (C) 2000-2004 Julian Seward 
-      jseward@acm.org
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307, USA.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-
-#include "core.h"
-
-enum PXState
-{
-   PXS_BAD = -1,
-   PXS_WaitReq,      /* waiting for a request */
-   PXS_RunSyscall,   /* running a syscall */
-   PXS_IntReply,     /* request interrupted - need to send reply */
-   PXS_SysDone,      /* small window between syscall
-                        complete and results written out */
-   PXS_SigACK,       /* waiting for a signal ACK */
-};
-
-
-enum RequestType {
-   PX_BAD = -1,
-   PX_SetSigmask,              /* sched->proxy; proxy->sched */
-   PX_RunSyscall,              /* sched->proxy; proxy->sched */
-   PX_Signal,                  /* proxy->sched */
-   PX_SigACK,                  /* sched->proxy */
-   PX_Ping,                    /* use for sanity-checking */
-   PX_Exiting,                 /* reply sent by proxy for exit sync */
-};
-
-
-#define VG_PROXY_MAGIC 0xef83b192
-struct ProxyLWP {
-   UInt                        magic;          /* magic number */
-   ThreadId            tid;            /* scheduler's tid */
-   ThreadState         *tst;           /* thread state */
-   Int                 lwp;            /* kernel's ID for LWP */
-   Int                 exitcode;       /* ProxyLWP exit code */
-
-   Int                 topx, frommain; /* pipe fds */
-   vki_siginfo_t       siginfo;        /* received signal */
-   Bool                        terminating;    /* in the middle of exiting */
-
-   /* State of proxy */
-   enum PXState                state;
-
-   jmp_buf             jumpbuf;
-};
-
-static void sys_wait_results(Bool block, ThreadId tid, enum RequestType reqtype, Bool restart);
-
-struct PX_Request {
-   enum RequestType    request;
-
-   vki_sigset_t                sigmask;        /* sigmask applied by SigACK */
-};
-
-/* All replies are multiplexed over a single pipe, so we need to disinguish them */
-struct PX_Reply {
-   ThreadId            tid;            /* tid this reply pertains to */
-   enum RequestType    req;            /* what this relates to */
-
-   union {
-      Int              syscallno;      /* system call completed */
-      vki_siginfo_t    siginfo;        /* signal */
-   } u;
-};
-
-/* results pipe */
-static Int result_send = -1, result_recv = -1;
-
-/* reentrant printf for proxy use */
-#if 0
-static void px_printf(const Char *fmt, ...)
-{
-   Char buf[1024];
-   Char *cp = buf;
-   va_list vargs;
-
-   void addbuf(Char c) { *cp++ = c; }
-
-   cp += VG_(sprintf)(buf, "[%d, %d]: ", VG_(getpid)(), VG_(gettid)());
-
-   va_start(vargs,fmt);
-   VG_(vprintf)(addbuf, fmt, vargs);
-   va_end(vargs);
-   VG_(send_bytes_to_logging_sink)(buf, cp-buf);
-}
-#else
-static void px_printf(const Char *fmt, ...)
-{
-}
-#endif
-
-static const Char *pxs_name(enum PXState s)
-{
-   switch(s) {
-#define S(x)   case PXS_##x: return #x
-      S(BAD);
-      S(WaitReq);
-      S(RunSyscall);
-      S(IntReply);
-      S(SysDone);
-      S(SigACK);
-#undef S
-   default: return "???";
-   }
-}
-
-static const Char *px_name(enum RequestType r)
-{
-   switch(r) {
-#define S(x)   case PX_##x: return #x
-      S(BAD);
-      S(SetSigmask);
-      S(RunSyscall);
-      S(Signal);
-      S(SigACK);
-      S(Ping);
-      S(Exiting);
-#undef S
-   default: return "???";
-   }
-}
-
-#define PROXYLWP_OFFSET        (VKI_PAGE_SIZE - sizeof(ProxyLWP))
-
-/* 
-   Allocate a page for the ProxyLWP and its stack.
-
-   This uses the trick for finding the LWP's private data by knowing
-   that the stack is a single page, and that the ProxyLWP structure is
-   at the end of it.  Therefore, given any %esp in the stack, you can
-   find the ProxyLWP structure (see LWP_TSD()).
- */
-static ProxyLWP *LWP_alloc(void)
-{
-   UChar *p = VG_(get_memory_from_mmap)(VKI_PAGE_SIZE, "alloc_LWP");
-   ProxyLWP *ret;
-   vg_assert(p == (UChar *)PGROUNDDN(p)); /* px must be page aligned */
-
-   ret = (ProxyLWP *)(p + PROXYLWP_OFFSET);
-
-   ret->magic = VG_PROXY_MAGIC;
-
-   return ret;
-}
-
-/* Free a thread structure */
-static void LWP_free(ProxyLWP *px)
-{
-   UChar *p = (UChar *)PGROUNDDN(px);
-   
-   vg_assert(px->magic == VG_PROXY_MAGIC);
-   px->magic = 0;
-   vg_assert((p + PROXYLWP_OFFSET) == (UChar *)px);
-
-   VG_(munmap)(p, VKI_PAGE_SIZE);
-}
-
-/* Get a particular ProxyLWP's LWP structure from its esp (relies on
-   stacks being page aligned, with the ProxyLWP structure at the
-   end). */
-static inline ProxyLWP *LWP_TSD(void *esp)
-{
-   UChar *p = (UChar *)PGROUNDDN(esp);
-   ProxyLWP *ret;
-
-   ret = (ProxyLWP *)(p + PROXYLWP_OFFSET);
-   vg_assert(ret->magic == VG_PROXY_MAGIC);
-
-   return ret;
-}
-
-/* Get top of stack */
-static inline void *LWP_stack(ProxyLWP *px)
-{
-   vg_assert(px->magic == VG_PROXY_MAGIC);
-
-   return (void *)(((void **)px) - 1);
-}
-
-static void proxy_fork_cleanup(ThreadId tid);
-
-/* Init the proxy mechanism */
-void VG_(proxy_init)(void)
-{
-   Int p[2];
-   Int res;
-
-   /* this will ignore any duplicate registrations */
-   VG_(atfork)(NULL, NULL, proxy_fork_cleanup);
-
-   vg_assert(result_recv == -1);
-   vg_assert(result_send == -1);
-
-   res = VG_(pipe)(p);
-   vg_assert(res == 0);
-
-   result_recv = VG_(safe_fd)(p[0]);
-   result_send = VG_(safe_fd)(p[1]);
-   
-   /* Make reading end non-blocking */
-   VG_(fcntl)(result_recv, VKI_F_SETFL, VKI_O_NONBLOCK);
-}
-
-/* After fork, the forking thread is in a strange state of having a
-   couple of pipes still linked to the parent. */
-static void proxy_fork_cleanup(ThreadId tid)
-{
-   ThreadId t;
-
-   VG_(close)(result_recv);
-   VG_(close)(result_send);
-
-   result_recv = result_send = -1;
-
-   VG_(proxy_init)();
-
-   for(t = 1; t < VG_N_THREADS; t++) {
-      ThreadState *tst = VG_(get_ThreadState)(t);
-      ProxyLWP *proxy = tst->proxy;
-
-      if (tst->status == VgTs_Empty) {
-        vg_assert(proxy == NULL);
-        continue;
-      }
-
-      vg_assert(proxy != NULL);
-
-      /* We need to do a manual teardown, since the proxy this structure
-        describes is our parent's */
-      VG_(close)(proxy->topx);
-      VG_(close)(proxy->frommain);
-   
-      LWP_free(proxy);
-      tst->proxy = NULL;
-   }
-
-   /* Create a proxy for calling thread.
-
-      Since fork() is non-blocking, the thread status should already
-      be Runnable.
-    */
-   vg_assert(VG_(is_valid_tid)(tid));
-   vg_assert(VG_(threads)[tid].proxy == NULL);
-   vg_assert(VG_(threads)[tid].status == VgTs_Runnable);
-
-   VG_(proxy_create)(tid);
-   VG_(proxy_setsigmask)(tid);
-}
-
-Int VG_(proxy_resfd)(void)
-{
-   return result_recv;
-}
-
-void VG_(proxy_shutdown)(void)
-{
-   VG_(close)(result_recv);
-   VG_(close)(result_send);
-
-   result_recv = result_send = -1;
-}
-
-/* This is called from within a proxy LWP signal handler.  This
-   function records the siginfo, then longjmps back into the proxy
-   main state machine loop.  The presumption is that the signal
-   handler is being run with all signals blocked; the longjmp is
-   there to make sure they stay masked until the application thread is
-   ready to run its signal handler. */
-void VG_(proxy_handlesig)(const vki_siginfo_t *siginfo, Addr ip, Int sysnum)
-{
-   UChar local;
-   ProxyLWP *px = LWP_TSD(&local);
-
-   vg_assert(siginfo->si_signo != 0);
-   if (px->siginfo.si_signo != 0) {
-      px_printf("proxy_handlesig: tid %d already has %d pending, new sig %d\n",
-               px->lwp, px->siginfo.si_signo, siginfo->si_signo);
-   }
-   vg_assert(px->siginfo.si_signo == 0);
-
-   px->siginfo = *siginfo;
-
-   px_printf("proxy got signal %d\n", siginfo->si_signo);
-
-   /* First look to see if the EIP is within our interesting ranges
-      near a syscall to work out what should happen. */
-   if (VGA_(sys_before) <= ip && ip <= VGA_(sys_restarted)) {
-      /* We are before the syscall actually ran, or it did run and
-        wants to be restarted.  Either way, set the return code to
-        indicate a restart.  This is not really any different from
-        anywhere else, except that we can make some assertions about
-        the proxy and machine state here. */
-      vg_assert(px->state == PXS_RunSyscall);
-      vg_assert(SYSCALL_RET(px->tst->arch) == -VKI_ERESTARTSYS);
-   } else if (VGA_(sys_after) <= ip && ip <= VGA_(sys_done)) {
-      /* We're after the syscall.  Either it was interrupted by the
-        signal, or the syscall completed normally.  In either case
-         the usual register contains the correct syscall return value, and
-         the new state is effectively PXS_SysDone. */
-      vg_assert(px->state == PXS_RunSyscall ||
-               px->state == PXS_SysDone);
-      px->state = PXS_SysDone;
-      SYSCALL_RET(px->tst->arch) = sysnum;
-   }
-   px_printf("  signalled in state %s\n", pxs_name(px->state));
-
-   __builtin_longjmp(px->jumpbuf, 1);
-}
-
-static Bool send_reply(const struct PX_Reply *reply)
-{
-   const Int size = sizeof(struct PX_Reply);
-
-   return VG_(write)(result_send, reply, size) == size;
-}
-
-static Bool recv_reply(struct PX_Reply *reply)
-{
-   const Int size = sizeof(struct PX_Reply);
-
-   return VG_(read)(result_recv, reply, size) == size;
-}
-
-/* Run a syscall for a particular thread, getting the arguments from
-   the thread's registers, and returning the result in the thread's
-   eax.
-
-   Assumes that the only thread state which matters is the contents of
-   %eax-%ebp and the return value in %eax.
- */
-static void thread_syscall(Int syscallno, 
-                           ThreadArchState *arch, 
-                           enum PXState *state , enum PXState poststate)
-{
-   VGA_(do_thread_syscall)(syscallno,
-                           arch->vex.PLATFORM_SYSCALL_ARG1,
-                           arch->vex.PLATFORM_SYSCALL_ARG2,
-                           arch->vex.PLATFORM_SYSCALL_ARG3,
-                           arch->vex.PLATFORM_SYSCALL_ARG4,
-                           arch->vex.PLATFORM_SYSCALL_ARG5,
-                           arch->vex.PLATFORM_SYSCALL_ARG6,
-                           (HWord*)&arch->vex.PLATFORM_SYSCALL_RET, // result
-                           state,       // state to update
-                           poststate);   // state when syscall has finished
-}
-
-
-
-/* Proxy LWP thread.  This is run as a separate cloned() thread, so it
-   MUST NOT touch any core Valgrind data structures directly: the only
-   exception is while we're running a PX_RunSyscall command, we may
-   look at and update the thread's register state.  It interacts with
-   the rest of Valgrind by receiving messages through its pipe and
-   sending results through result_send. */
-static Int proxylwp(void *v)
-{
-   ProxyLWP *px = (ProxyLWP *)v;
-   Int frommain = px->frommain;
-   ThreadState *tst = px->tst;
-   vki_sigset_t allsig;
-   vki_sigset_t appsigmask;    /* signal mask the client has asked for */
-   Int ret = 1000;
-   static const vki_stack_t ss = { .ss_flags = VKI_SS_DISABLE };
-
-   /* Block everything until we're told otherwise (LWP should have
-      been started with all signals blocked anyway) */
-   VG_(sigfillset)(&allsig);
-   VG_(sigdelset)(&allsig, VKI_SIGVGKILL);     /* but allow SIGVGKILL to interrupt */
-
-   VG_(sigprocmask)(VKI_SIG_SETMASK, &allsig, NULL);
-
-   appsigmask = allsig;
-
-   /* no signal stack for us */
-   VG_(sigaltstack)(&ss, NULL);
-
-   for(;;) {
-      struct PX_Reply reply, sigreply;
-      struct PX_Request req;
-      Int res;
-
-      if (__builtin_setjmp(px->jumpbuf)) {
-        /* We were hit by a signal.  This is the signal-driven part
-           of the state machine. 
-
-           This code prepares a reply which is suitable for whatever
-           was interrupted by this signal.  If "no reply" is the
-           right response, then it sets reply.req = PX_BAD.
-
-           NOTE: the ST:N notation represents the correspondence
-           between states where we can be interrupted in the main
-           state machine loop, and where those states are handled
-           here.
-        */
-
-        if (px->siginfo.si_signo != VKI_SIGVGKILL) {
-           /* First, send the signal info */
-           sigreply.tid = px->tid;
-           sigreply.req = PX_Signal;
-           sigreply.u.siginfo = px->siginfo;
-
-           if (!send_reply(&sigreply)) {
-              ret = 44;                /* incomplete or failed write */
-              goto out;
-           }
-        } else {
-           /* We got VKI_SIGVGKILL, which means we just skip all the
-              below and exit.  (Don't bother dealing with any pending
-              requests, because we'll probably just get confused.) */
-           px->state = PXS_WaitReq;
-           px->siginfo.si_signo = 0;
-           ret = 0;
-           goto out;
-        }
-
-        px->siginfo.si_signo = 0;
-
-        /* Now work out what our new state is, and what to do on the way. */
-        switch(px->state) {
-        case PXS_WaitReq:
-           /* We were interrupted while waiting for a request.  See
-              if we had actually read the request, and do the
-              appropriate thing if so. */
-           reply.req = req.request;
-           reply.tid = px->tid;
-
-           switch(req.request) {
-           case PX_BAD:
-              /* ST:1 */
-              /* nothing read; just wait for SigACK */
-              px->state = PXS_SigACK;
-              break;
-
-           case PX_RunSyscall:
-              /* ST:2 */
-              /* They asked for a syscall, but we were signalled
-                 before even getting started.  Claim the syscall was
-                 interrupted.
-
-                 XXX how to distunguish between restartable and
-                 non-restartable syscalls?  Does it matter?
-              */
-              reply.u.syscallno = tst->syscallno;
-
-              SYSCALL_RET(tst->arch) = -VKI_ERESTARTSYS;
-              px->state = PXS_IntReply;
-              break;
-
-           case PX_SetSigmask:
-              /* ST:2 */
-              /* ST:3 */
-              /* They asked for a signal mask update. Ignore it,
-                 because they're going to give us a new mask when
-                 they send a SigACK, and we want all signals blocked
-                 in the meantime.  However, we set the state to
-                 PXS_IntReply to make sure the reply from the
-                 PX_SetSigmask is sent. */
-              vg_assert(reply.req == PX_SetSigmask);
-              px->state = PXS_IntReply;
-              break;
-
-           case PX_Ping:
-              /* ST:2 */
-              /* We read a Ping request, so we need to send a Ping
-                 reply. */
-              vg_assert(reply.req == PX_Ping);
-              px->state = PXS_IntReply;
-              break;
-
-           case PX_Exiting:
-           case PX_Signal:
-              ret = 10;        /* completely bogus - noone should send us a signal */
-              goto out;
-
-           case PX_SigACK:
-              ret = 11;        /* Also bogus.  No way we should get a
-                                  signal while waiting for a
-                                  SigACK. */
-              goto out;
-           }
-           break;
-
-        case PXS_RunSyscall:
-           /* ST:4 */
-           /* We were actually running the syscall when interrupted.
-              reply should already be set up, including return in eax. */
-           vg_assert(reply.req == PX_RunSyscall);
-           vg_assert(reply.u.syscallno == tst->syscallno);
-           vg_assert(tst->status == VgTs_WaitSys);
-           px->state = PXS_IntReply;
-           break;
-
-        case PXS_SysDone:
-           /* The syscall is done; we just need to send the results
-              back. */
-           vg_assert(reply.req == PX_RunSyscall);
-           vg_assert(reply.u.syscallno == tst->syscallno);
-           px->state = PXS_IntReply;
-           break;
-
-        case PXS_IntReply:
-        case PXS_SigACK:
-           ret = 13;           /* Bogus.  Same as ret=11 above. */
-           goto out;
-
-        case PXS_BAD:
-           ret = 33;
-           goto out;
-        }
-
-        /* End of signal handling states.  If the scheduler LWP is
-           currently running application code, tell it to drop back
-           into the scheduler loop ASAP to handle the signal. */
-        if (VG_(clo_lowlat_signals))
-           VG_(need_resched)(px->tid);
-      }
-
-      /* state_machine: */
-      px_printf("proxylwp main: state %s\n", pxs_name(px->state));
-
-      switch(px->state) {
-      case PXS_WaitReq:
-      case PXS_SigACK:
-        req.request = PX_BAD;  /* init request so we know if the read() read anything */
-
-        if (px->state == PXS_WaitReq) {
-           /* allow signals when waiting for a normal request */
-           VG_(sigprocmask)(VKI_SIG_SETMASK, &appsigmask, NULL);
-        }
-
-        /* ST:1 */
-
-        res = VG_(read)(frommain, &req, sizeof(req));
-
-        /* ST:2 */
-
-        /* process message with signals blocked */
-        VG_(sigprocmask)(VKI_SIG_SETMASK, &allsig, NULL);
-
-        if (res == 0) {
-           ret = 0;
-           goto out;           /* EOF - we're quitting */
-        }
-        
-        if (res < 0) {
-           px_printf("read(frommain) failed %d\n", res);
-           ret = 1;            /* error */
-           goto out;
-        }
-        if (res != sizeof(req)) {
-           ret = 2;            /* error - partial read */
-           goto out;
-        }
-
-        px_printf("read req: %s\n", px_name(req.request));
-
-        reply.tid = px->tid;
-        reply.req = req.request;
-
-        switch(req.request) {
-        case PX_Ping:
-           /* do nothing; just send reply */
-           break;
-
-        case PX_SigACK:
-           /* The thread ACKed the signal, and sent the mask they
-              want while running the handler. */
-           vg_assert(px->state == PXS_SigACK);
-           appsigmask = req.sigmask;
-           VG_(sigdelset)(&appsigmask, VKI_SIGVGKILL);  /* but allow SIGVGKILL */
-           VG_(sigdelset)(&appsigmask, VKI_SIGVGINT);   /*       and SIGVGINT to interrupt */
-           px->state = PXS_WaitReq;
-           reply.req = PX_BAD; /* don't reply */
-           break;
-           
-        case PX_SetSigmask:
-           appsigmask = req.sigmask;
-           VG_(sigdelset)(&appsigmask, VKI_SIGVGKILL);  /* but allow SIGVGKILL */
-           VG_(sigdelset)(&appsigmask, VKI_SIGVGINT);   /*       and SIGVGINT to interrupt */
-
-           vg_assert(px->state == PXS_WaitReq || 
-                     px->state == PXS_SigACK);
-
-           if (px->state != PXS_SigACK) {
-              /* If we're not waiting for a PX_SigACK, set the apps mask
-                 to get at least one of the pending signals, which will
-                 be delivered synchronously, so that some progress is
-                 made before the we tell the client the mask has been
-                 set..  Then reset the mask back to all blocked. */
-              VG_(sigprocmask)(VKI_SIG_SETMASK, &appsigmask, NULL);
-              /* ST:3 */
-              VG_(sigprocmask)(VKI_SIG_SETMASK, &allsig, NULL);
-           } else {
-              /* Waiting for SigACK.  We want all signals blocked,
-                 and when the SigACK arrives, it will give us the
-                 thread's signal mask for its handler. */
-           }
-           break;
-
-        case PX_RunSyscall:
-           /* Run a syscall for our thread; results will be poked
-              back into tst */
-           reply.u.syscallno = tst->syscallno;
-
-           vg_assert(px->state == PXS_WaitReq || 
-                     px->state == PXS_SigACK);
-           if (px->state == PXS_SigACK) {
-              /* If we're in the middle of signal handling, make the
-                 client's syscalls fail with ERESTARTSYS until its signal
-                 handler runs - there should be at most one, if it was
-                 on the way to us as we got the signal.  
-              */
-              px_printf("RunSyscall in SigACK: rejecting syscall %d with ERESTARTSYS\n",
-                        reply.u.syscallno);
-              SYSCALL_RET(tst->arch) = -VKI_ERESTARTSYS;
-           } else {
-              Int syscallno = tst->syscallno;
-              
-              px->state = PXS_RunSyscall;
-              /* If we're interrupted before we get to the syscall
-                 itself, we want the syscall restarted. */
-              SYSCALL_RET(tst->arch) = -VKI_ERESTARTSYS;
-
-              /* set our process group ID to match parent */
-              if (VG_(getpgrp)() != VG_(main_pgrp))
-                 VG_(setpgid)(0, VG_(main_pgrp));
-
-              VG_(sigprocmask)(VKI_SIG_SETMASK, &appsigmask, NULL);
-
-              /* ST:4 */
-              
-              thread_syscall(syscallno, &tst->arch, &px->state, PXS_SysDone);
-
-              /* ST:5 */
-
-              VG_(sigprocmask)(VKI_SIG_SETMASK, &allsig, NULL);
-              /* whew - made it here without being interrupted */
-              px->state = PXS_WaitReq;
-
-              if (VG_(clo_lowlat_syscalls))
-                 VG_(need_resched)(px->tid);
-           }
-           break;
-           
-        case PX_BAD:
-        case PX_Signal:
-        case PX_Exiting:
-           /* we never expect to see these */
-           ret = 3;
-           goto out;
-        }
-        break;
-
-      case PXS_IntReply:
-        /* This state only exists so that we fall out and write the
-           interrupted syscall reply before moving to SigACK */
-        px->state = PXS_SigACK;
-        break;
-
-      case PXS_RunSyscall:
-      case PXS_SysDone:
-      case PXS_BAD:
-      default:
-        /* Never expect to see these states here */
-        ret = 5;
-        goto out;
-      }
-
-      /* If we have something sensible to say, say it */
-      if (reply.req != PX_BAD) {
-        px_printf("sending reply %s\n", px_name(reply.req));
-
-        if (!send_reply(&reply)) {
-           ret = 4;            /* error - didn't write full message */
-           goto out;
-        }
-        reply.req = PX_BAD;
-      }
-   }
-      
-  out:
-   px_printf("proxy exiting with ret=%d\n", ret);
-
-   {
-      struct PX_Reply reply;
-      reply.req = PX_Exiting;
-      reply.tid = px->tid;
-      px_printf("exit: sending %s\n", px_name(reply.req));
-      
-      send_reply(&reply);
-   }
-
-   px->frommain = -1;
-   VG_(close)(frommain);
-
-   px->exitcode = ret;
-   return ret;
-}
-
-/* Send a signal to a proxy LWP */
-void VG_(proxy_sendsig)(ThreadId fromTid, ThreadId toTid, Int sig)
-{
-   /* toTid must be genuine, but fromTid can be
-      VG_INVALID_THREADID. */
-   ThreadState* tst   = VG_(get_ThreadState)(toTid);
-   ProxyLWP*    proxy = tst->proxy;
-   Bool         signallingMyself;
-   Int          lwp;
-
-   if (proxy == NULL)
-      return;
-
-   lwp = proxy->lwp;           /* proxy->lwp may change async */
-
-   if (lwp != 0) {
-      /* SIGKILL and SIGSTOP always apply to all threads (need to
-        route for route_signals case?) */
-      if (sig == VKI_SIGKILL || sig == VKI_SIGSTOP)
-        VG_(kill)(VG_(main_pid), sig);
-      else
-        VG_(tkill)(lwp, sig);
-   }
-
-   /* If a thread is sending a signal to itself and the signal isn't
-      blocked (ie, it will be delivered), wait until the signal
-      message gets sent back, thus making the signal synchronous. */
-   signallingMyself 
-      = fromTid != VG_INVALID_THREADID
-        && fromTid == toTid;
-
-   if (sig != 0 && 
-       !VG_(is_sig_ign)(sig) &&
-       signallingMyself && 
-       !VG_(sigismember)(&tst->eff_sig_mask, sig)) {
-      /* If the LWP is actually blocked in a sigtimedwait, then it
-        will eat the signal rather than make it pending and deliver
-        it by the normal mechanism.  In this case, just wait for the
-        syscall to dinish. */
-      if (tst->status == VgTs_WaitSys && tst->syscallno == __NR_rt_sigtimedwait)
-        sys_wait_results(True, toTid, PX_RunSyscall, True);
-      else
-        sys_wait_results(True, toTid, PX_Signal, True);
-   }
-}
-
-/* If a thread is blocked in a syscall, this function will interrupt
-   the proxy LWP's syscall by hitting it with a VKI_SIGVGINT signal.
-   This signal will not be reported to the client application. */
-void VG_(proxy_abort_syscall)(ThreadId tid)
-{
-   ThreadState *tst = VG_(get_ThreadState)(tid);
-   ProxyLWP *proxy = tst->proxy;
-   Int lwp;
-
-   if (tst->status != VgTs_WaitSys)
-      return;
-
-   vg_assert(proxy != NULL);
-
-   lwp = proxy->lwp;
-   
-   if (lwp != 0)
-      VG_(tkill)(lwp, VKI_SIGVGINT);
-
-   sys_wait_results(True, tid, PX_RunSyscall, False);
-
-   vg_assert(tst->status == VgTs_Runnable);
-}
-
-static Int do_futex(void *addr, Int op, Int val, struct vki_timespec *time,
-                    void *addr2)
-{
-   return VG_(do_syscall5)(__NR_futex, (UWord)addr, op, val, (UWord)time,
-                                       (UWord)addr2);
-}
-
-static Int have_settid = -1;   /* -1 -> unknown */
-
-/*
-  Create a proxy LWP using whatever varient of clone makes the most
-   sense for the current kernel.  We use futexes for termination
-   notification wherever possible.  Returns 0 on success, or a -ve
-   error code on failure.
-*/
-static Int proxy_clone(ProxyLWP *proxy)
-{
-   Int ret = -1;
-
-   if (have_settid != 0) {
-      ret = VG_(clone)(proxylwp, 
-                      LWP_stack(proxy),
-                      VKI_CLONE_FS | VKI_CLONE_FILES | VKI_CLONE_VM |
-                      VKI_CLONE_SIGHAND | VKI_CLONE_THREAD | 
-                      VKI_CLONE_PARENT_SETTID |
-                      VKI_CLONE_CHILD_CLEARTID | VKI_CLONE_DETACHED,
-                      proxy, &proxy->lwp, &proxy->lwp);
-
-      if ( have_settid == -1 && (ret < 0 || proxy->lwp == 0) ) {
-         have_settid = 0;
-        
-        /* Assume that not having parent_settid also means that we've
-           got 2.4-style signal handling, which means we need to do
-           more work. */
-         VG_(do_signal_routing) = True;
-
-        if (ret > 0) {
-           /* If clone actually succeeded and just ignored the
-              CLONE_PARENT_SETTID flag, then use the LWP it created
-              for us. */
-           proxy->lwp = ret;
-        }
-       }
-       else 
-           have_settid = 1;
-   }
-
-   if (ret < 0) {
-      vg_assert(have_settid == 0);
-      vg_assert(proxy->lwp == 0);
-
-      ret = VG_(clone)(proxylwp, 
-                      LWP_stack(proxy),
-                      VKI_CLONE_FS | VKI_CLONE_FILES | VKI_CLONE_VM |
-                      VKI_CLONE_SIGHAND | VKI_CLONE_THREAD, 
-                      proxy, NULL, NULL);
-      proxy->lwp = ret;
-   }
-
-   return (ret < 0) ? ret : 0;
-}
-
-/* Wait on a proxy LWP.  Returns True if the LWP has exited. */
-static Bool proxy_wait(ProxyLWP *proxy, Bool block, Int *status)
-{
-   Bool ret = False;
-
-   if (have_settid == -1)
-      return False;
-
-   if (have_settid) {
-      if (block) {
-        Int lwp = proxy->lwp;
-
-        if(proxy->lwp != 0)
-            /* JEREMY: amd64 hangs here at exit */
-           do_futex(&proxy->lwp, VKI_FUTEX_WAIT, lwp, NULL, NULL);
-        if (status)
-           *status = proxy->exitcode;
-        ret = True;
-      } else {
-        if (proxy->lwp == 0) {
-           *status = proxy->exitcode;
-           ret = True;
-        }
-      }
-   } else {
-      Int flags = __VKI_WCLONE;
-      Int res;
-      if (!block)
-        flags |= VKI_WNOHANG;
-      res = VG_(waitpid)(proxy->lwp, status, flags);
-      if (res == proxy->lwp) {
-        vg_assert(*status == proxy->exitcode);
-        ret = True;
-      }
-   }
-
-   return ret;
-}
-
-/* Create a proxy for a new thread */
-void VG_(proxy_create)(ThreadId tid)
-{
-   ThreadState *tst = VG_(get_ThreadState)(tid);
-   ProxyLWP *proxy;
-   Int p[2];
-   vki_sigset_t mask;
-   Int ret;
-
-   vg_assert(tst->proxy == NULL);
-   vg_assert(tst->status == VgTs_Runnable);
-
-   proxy = LWP_alloc();
-
-   VG_(pipe)(p);
-
-   proxy->tid              = tid;
-   proxy->tst              = tst;
-   proxy->exitcode         = 0;
-   proxy->lwp              = 0;
-   proxy->siginfo.si_signo = 0;
-   proxy->frommain         = VG_(safe_fd)(p[0]);
-   proxy->topx             = VG_(safe_fd)(p[1]);
-   proxy->state            = PXS_WaitReq;  /* start by waiting for requests */
-   proxy->terminating      = False;
-
-   /* Make sure proxy LWP starts with all signals blocked (not even
-      SEGV, BUS, ILL or FPE) */
-   VG_(block_all_host_signals)(&mask);
-
-   ret = proxy_clone(proxy);
-
-   if (ret < 0) {
-      VG_(printf)("Error %d trying to create proxy LWP for tid %d\n",
-                  ret, tid);
-      VG_(core_panic)("Can't start proxy LWPs");
-   }
-
-   VG_(restore_all_host_signals)(&mask);
-
-   tst->proxy = proxy;
-}
-
-/* Clean up proxy after thread dies */
-void VG_(proxy_delete)(ThreadId tid, Bool force)
-{
-   ThreadState *tst = VG_(get_ThreadState)(tid);
-   ProxyLWP *proxy = tst->proxy;
-   Bool res;
-   Int status;
-   Int lwp;
-
-   if (proxy == NULL)
-      return;                  /* nothing to do */
-
-   lwp = proxy->lwp;
-
-#if 0
-   MAYBE_PRINTF("VG_(proxy_delete)(tid=%d (lwp=%d), force=%s; tst->status=%d\n",
-               tid, lwp, force ? "true" : "false", tst->status);
-#endif
-   vg_assert(proxy->tid == tid);
-   if (proxy->terminating)
-      return;          /* already going away */
-
-   proxy->terminating = True;
-   VG_(close)(proxy->topx);
-   proxy->topx = -1;
-   /* proxy thread will close proxy->frommain itself */
-   if (force && lwp != 0) {
-      /* wouldn't need to force it if it were already dead */
-      vg_assert(tst->status != VgTs_Empty);
-      //VG_(printf)("kill %d with SIGVGKILL\n", lwp);
-      VG_(tkill)(lwp, VKI_SIGVGKILL);
-   } else
-      vg_assert(tst->status == VgTs_Empty); /* just killed */
-
-   status = -1;
-   res = False;
-   /* We need to wait for the PX_Exiting message before doing the
-      proxy_wait, because if we don't read the results pipe, the proxy
-      may be blocked writing to it, causing a deadlock with us as we
-      wait for it to exit. */
-   sys_wait_results(True, tid, PX_Exiting, True);
-   res = proxy_wait(proxy, True, &status);
-   if ((!res || status != 0) && VG_(clo_verbosity) > 1)
-      VG_(printf)("proxy %d for tid %d exited status %d, res %d\n",
-                 lwp, tid, status, res);
-   LWP_free(proxy);
-   tst->proxy = NULL;
-}
-
-/* Read back the results of any completed syscalls.
-
-   At this point, there should be only one pending syscall per thread.
-   Those threads should be in VgTs_WaitSys state.  Each syscall return
-   may have multiple signals associated with it, so we read those and
-   set up some pending signals in our signal simulation.  When we
-   finally get the message saying the syscall is complete, we mark the
-   thread as runnable and return.
-
-   If block is set to True, then this call will block until anything
-   happens (ie, some progress was made).
-
-   If reqtype != PX_BAD, then this will block until some reply for
-   that request type appears (assuming you're expecting that kind of
-   reply, otherwise it will block forever).  If tid != 0, then it will
-   wait for a reply for that particular tid.
- */
-static void sys_wait_results(Bool block, ThreadId tid, enum RequestType reqtype, Bool restart)
-{
-   Bool found_reply = (reqtype == PX_BAD);
-   struct PX_Reply res;
-   
-   vg_assert(VG_(gettid)() == VG_(main_pid));
-
-   do {
-      if (reqtype != PX_BAD || block) {
-        /* wait for activity on recv_res */
-        struct vki_pollfd pollfd;
-        Int ret;
-
-        /* result_recv could be -1 if we're asking for results before any
-           syscalls are issued - which is OK - but we can't block on
-           it. */
-        vg_assert(result_recv != -1);
-
-        pollfd.fd = result_recv;
-        pollfd.events = VKI_POLLIN;
-
-        do {
-           ret = VG_(poll)(&pollfd, 1, -1);
-        } while(ret == -VKI_EINTR);
-        if (ret <= 0) {
-           VG_(printf)("sys_wait_results: poll failed fd=%d errno=%d\n",
-                       pollfd.fd, ret);
-           return;
-        }
-      }
-
-      while(recv_reply(&res)) {
-        ThreadState *tst;
-
-        if (reqtype != PX_BAD &&
-            res.req == reqtype &&
-            (tid == 0 || tid == res.tid))
-           found_reply = True;
-
-        tst = VG_(get_ThreadState)(res.tid);
-
-        switch(res.req) {
-        case PX_SetSigmask:
-           /* Don't need to do anything */
-           if (VG_(clo_trace_signals) || VG_(clo_trace_syscalls))
-              VG_(printf)("sys_wait_results: got PX_SetSigmask for TID %d\n",
-                           res.tid);
-           break;
-
-        case PX_RunSyscall:
-           if (VG_(clo_trace_syscalls))
-              VG_(printf)("sys_wait_results: got PX_RunSyscall for SYSCALL[%d,%d](%3d) --> %lld (%llx)\n",
-                          VG_(getpid)(), res.tid, tst->syscallno,
-                            (Long)(Word)SYSCALL_RET(tst->arch),
-                           (ULong)SYSCALL_RET(tst->arch));
-
-           if (tst->status != VgTs_WaitSys)
-              VG_(printf)("tid %d in status %d\n",
-                          tst->tid, tst->status);
-        
-           vg_assert(res.u.syscallno == tst->syscallno);
-           vg_assert(tst->status == VgTs_WaitSys);
-
-           VG_(post_syscall)(res.tid, restart);
-           break;
-
-        case PX_Signal:
-            if (VG_(do_signal_routing) &&
-                res.u.siginfo.si_code == VKI_SI_USER &&
-                res.u.siginfo._sifields._kill._pid == VG_(getpid)()) {
-               Int ptr = tst->sigqueue_tail;
-
-               while (tst->sigqueue[ptr].si_signo != res.u.siginfo.si_signo) {
-                  vg_assert(ptr != tst->sigqueue_head);
-                  ptr = (ptr + 1) % VG_N_SIGNALQUEUE;
-               }
-               
-               res.u.siginfo = tst->sigqueue[ptr];
-               tst->sigqueue[ptr].si_signo = 0;
-
-               while (tst->sigqueue_tail != tst->sigqueue_head &&
-                      tst->sigqueue[tst->sigqueue_tail].si_signo == 0) {
-                  tst->sigqueue_tail = (tst->sigqueue_tail + 1) % VG_N_SIGNALQUEUE;
-               }
-            }
-
-            if (VG_(clo_trace_signals) || VG_(clo_trace_syscalls))
-              VG_(printf)("sys_wait_results: got PX_Signal for TID %d, signal %d\n",
-                          res.tid, res.u.siginfo.si_signo);
-
-           vg_assert(res.u.siginfo.si_signo != 0);
-           if (VG_(threads)[res.tid].proxy && 
-               !VG_(threads)[res.tid].proxy->terminating)
-              VG_(deliver_signal)(res.tid, &res.u.siginfo, True);
-           break;
-
-        case PX_Ping:
-           /* Got a ping response. Great. */
-           break;
-
-        case PX_Exiting:
-           /* They're exiting.  Hooray! */
-           break;
-
-        case PX_BAD:
-        case PX_SigACK:
-        default:
-           VG_(core_panic)("sys_wait_results: got PX_BAD/PX_SigACK!\n");
-        }
-      }
-   } while(!found_reply);
-}
-
-/* External version */
-void VG_(proxy_results)(void)
-{
-   sys_wait_results(False, 0, PX_BAD, True);
-}
-
-void VG_(proxy_wait_sys)(ThreadId tid, Bool restart)
-{
-   ThreadState *tst = VG_(get_ThreadState)(tid);
-
-   vg_assert(tst->status == VgTs_WaitSys);
-
-   sys_wait_results(True, tid, PX_RunSyscall, restart);
-}
-
-/* Tell proxy about it's thread's updated signal mask */
-void VG_(proxy_setsigmask)(ThreadId tid)
-{
-   ThreadState *tst = VG_(get_ThreadState)(tid);
-   ProxyLWP *proxy = tst->proxy;
-   Int res;
-   struct PX_Request req;
-
-   vg_assert(proxy != NULL);
-   vg_assert(proxy->tid == tid);
-
-   req.request = PX_SetSigmask;
-   req.sigmask = tst->sig_mask;
-
-   tst->eff_sig_mask = tst->sig_mask;
-
-   /* clear the results pipe before we try to write to a proxy to
-      prevent a deadlock */
-   VG_(proxy_results)();
-   res = VG_(write)(proxy->topx, &req, sizeof(req));
-   vg_assert(res == sizeof(req));
-
-   /* wait for proxy to ack mask update; mask changes don't really
-      have to be synchronous, but they do have to be fully ordered
-      with respect to each other (ie, if thread A then thread B
-      updates their signal masks, A's update must be done before B's
-      is).  */
-   sys_wait_results(True, tid, PX_SetSigmask, True);
-}
-
-void VG_(proxy_sigack)(ThreadId tid, const vki_sigset_t *mask)
-{
-   ThreadState *tst = VG_(get_ThreadState)(tid);
-   ProxyLWP *proxy = tst->proxy;
-   Int res;
-   struct PX_Request req;
-
-   vg_assert(proxy != NULL);
-   vg_assert(proxy->tid == tid);
-   
-   if (proxy_wait(proxy, False, NULL))
-      return;
-
-   req.request = PX_SigACK;
-   req.sigmask = *mask;
-
-   tst->eff_sig_mask = *mask;
-
-#if 0
-   /* Clear the results pipe before we try to write to a proxy to
-      prevent a deadlock.
-
-      XXX this breaks things.  This is called as a result of a
-      PX_Signal message, and is called from within sys_wait_results.
-      If that sys_wait_results was blocking of a particular message,
-      it will never wake up if we eat those messages by calling
-      sys_wait_results ourselves from here.  Maybe make
-      sys_wait_results non-recursive?
-   */
-   VG_(proxy_results)();
-#endif
-
-   res = VG_(write)(proxy->topx, &req, sizeof(req));
-   vg_assert(res == sizeof(req));
-}
-
-/* Wait for a signal to be delivered to any thread */
-void VG_(proxy_waitsig)(void)
-{
-   if (VG_(do_signal_routing))
-      VG_(route_signals)();
-   else
-      sys_wait_results(True, VG_INVALID_THREADID /* any */, PX_Signal, True);
-}
-
-/* Issue a syscall to the thread's ProxyLWP */
-Int VG_(sys_issue)(ThreadId tid)
-{
-   ThreadState *tst = VG_(get_ThreadState)(tid);
-   ProxyLWP *proxy = tst->proxy;
-   Int res;
-   struct PX_Request req;
-
-   vg_assert(proxy != NULL);
-   vg_assert(proxy->tid == tid);
-   vg_assert(tst->status == VgTs_WaitSys);
-
-   /* Clear the results pipe before we try to write to a proxy to
-      prevent a deadlock (the proxyLWP may be trying to write a result
-      back to the scheduler LWP, and therefore not be reading its
-      input pipe, which would then block the write below).
-
-      XXX I think this can't happen - the pipe has 4k of buffering,
-      and can therefore fit many messages, but we can only have one
-      outstanding - the write below will not block forever.  Fetching
-      results here can cause all kinds of confusion, because we
-      definitely don't want the complexity of trying to deliver a
-      signal right now.
-   */
-   if (0)
-      VG_(proxy_results)();
-
-   req.request = PX_RunSyscall;
-
-   tst->syscallno = SYSCALL_NUM(tst->arch);
-   SYSCALL_RET(tst->arch) = -VKI_ERESTARTSYS;
-
-   res = VG_(write)(proxy->topx, &req, sizeof(req));
-
-   if (res != sizeof(req)) {
-      VG_(message)(Vg_DebugMsg, "sys_issue: write to tid %u failed %d (not %d)\n",
-                  tid, res, sizeof(req));
-   }
-   return 0;
-}
-
-/* Relatively expensive sanity tests for the syscall machinery */
-void VG_(sanity_check_proxy)(void)
-{
-   ThreadId tid;
-   Bool sane = True;
-   static const struct PX_Request req = { .request = PX_Ping };
-
-   for(tid = 0; tid < VG_N_THREADS; tid++) {
-      ThreadState *tst = &VG_(threads)[tid];
-      ProxyLWP *px;
-      Int status = 0;
-      Int ret;
-
-      if (tst->status == VgTs_Empty)
-        continue;
-
-      if (tst->proxy == NULL) {
-        VG_(message)(Vg_DebugMsg, "TID %d: NULL proxy");
-        sane = False;
-        continue;
-      }
-
-      px = tst->proxy;
-
-      if (px->tid != tid) {
-        VG_(message)(Vg_DebugMsg, 
-                     "TID %d: proxy LWP %d doesn't have right tid (%d)\n",
-                     tid, px->lwp, px->tid);
-        sane = False;
-      }
-
-      if (proxy_wait(px, False, &status)) {
-        VG_(message)(Vg_DebugMsg,
-                     "TID %d: proxy LWP %d exited with status %d\n",
-                     tid, px->lwp, status);
-        sane = False;
-        continue;
-      }
-
-      /* No point checking if proxy is busy in a syscall, but all
-        other times it should respond promptly. */
-      if (tst->status != VgTs_WaitSys) {
-        ret = VG_(write)(px->topx, &req, sizeof(req));
-        if (ret != sizeof(req)) {
-           VG_(message)(Vg_DebugMsg,
-                        "TID %d: failed to write PX_Ping to lwp %d: %d\n",
-                        tid, px->lwp, ret);
-           sane = False;
-        }
-        sys_wait_results(True, tid, PX_Ping, True);
-        /* Can't make an assertion here, fortunately; this will
-           either come back or it won't. */
-      }
-   }
-
-   vg_assert(sane);
-}
-
-/* Get the PID/TID of the ProxyLWP. */
-__attribute__((unused))
-static Int proxy_id(ThreadId tid)
-{
-   ThreadState *tst = VG_(get_ThreadState)(tid);
-   return tst->proxy->lwp;
-}
-
-/*--------------------------------------------------------------------*/
-/*--- Proxy LWP machinery.                           vg_proxylwp.c ---*/
-/*--------------------------------------------------------------------*/
diff --git a/docs/proxylwp.sxw b/docs/proxylwp.sxw
deleted file mode 100644 (file)
index 38ceeaf..0000000
Binary files a/docs/proxylwp.sxw and /dev/null differ
diff --git a/memcheck/mc_from_ucode.c b/memcheck/mc_from_ucode.c
deleted file mode 100644 (file)
index 705849d..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Generate code for tool-specific UInstrs.                     ---*/
-/*---                                              mc_from_ucode.c ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of MemCheck, a heavyweight Valgrind tool for
-   detecting memory errors.
-
-   Copyright (C) 2000-2004 Julian Seward 
-      jseward@acm.org
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307, USA.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-/*--------------------------------------------------------------------*/
-/*--- end                                          mc_from_ucode.c ---*/
-/*--------------------------------------------------------------------*/