Mega-merge of my last 2 weeks hacking.  This basically does the groundwork
for pthread_* support.  Major changes:

* Valgrind now contains a (skeletal!) user-space pthreads
  implementation.  The exciting bits are in new file vg_scheduler.c.
  This contains thread management and scheduling, including nasty crud
  to do with making some syscalls (read,write,nanosleep) nonblocking.
  Also implementation of pthread_ functions: create join
  mutex_{create,destroy,lock,unlock} and cancel.

* As a side effect of the above, major improvements to signal handling
  and to the client-request machinery.  This is now used to intercept
  malloc/free etc too; the hacky way this is done before is gone.
  Another side effect is that vg_dispatch.S is greatly simplified.
  Also, the horrible hacks to do with delivering signals to threads
  blocked in syscalls are gone, since the new mechanisms cover this case
  easily.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@52 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_from_ucode.c b/coregrind/vg_from_ucode.c
index 5e32084..0514cf9 100644
--- a/coregrind/vg_from_ucode.c
+++ b/coregrind/vg_from_ucode.c
@@ -1069,44 +1069,48 @@
 }
 
 
-/* Jump to the next translation, by loading its original addr into
-   %eax and returning to the scheduler.  Or, if is a RET transfer,
-   don't return; instead jump to vg_dispatch_when_RET, which checks
-   whether this is a signal handler returning, and takes suitable
-   evasive action.
-*/
-static void synth_jmp_reg ( Int reg, 
-                            Bool is_ret_dispatch,
-                            Bool is_call_dispatch )
+static void load_ebp_from_JmpKind ( JmpKind jmpkind )
 {
+   switch (jmpkind) {
+      case JmpBoring: 
+         break;
+      case JmpCall:
+      case JmpRet: 
+         emit_movv_lit_reg ( 4, VG_TRC_EBP_JMP_SPECIAL, R_EBP );
+         break;
+      case JmpSyscall: 
+         emit_movv_lit_reg ( 4, VG_TRC_EBP_JMP_SYSCALL, R_EBP );
+         break;
+      case JmpClientReq: 
+         emit_movv_lit_reg ( 4, VG_TRC_EBP_JMP_CLIENTREQ, R_EBP );
+         break;
+      default: 
+         VG_(panic)("load_ebp_from_JmpKind");
+   }
+}
+
+/* Jump to the next translation, by loading its original addr into
+   %eax and returning to the scheduler.  Signal special requirements
+   by loading a special value into %ebp first.  
+*/
+static void synth_jmp_reg ( Int reg, JmpKind jmpkind )
+{
+   load_ebp_from_JmpKind ( jmpkind );
    if (reg != R_EAX)
       emit_movv_reg_reg ( 4, reg, R_EAX );
-   if (is_ret_dispatch || is_call_dispatch) {
-      /* The (hopefully) rare case. */
-      vg_assert(!(is_ret_dispatch && is_call_dispatch));
-      emit_movv_lit_reg ( 4, VG_EBP_DISPATCH_CHECKED, R_EBP );
-   }
    emit_ret();
 }
 
 
 /* Same deal as synth_jmp_reg. */
-static void synth_jmp_lit ( Addr addr )
+static void synth_jmp_lit ( Addr addr, JmpKind jmpkind )
 {
+   load_ebp_from_JmpKind ( jmpkind );
    emit_movv_lit_reg ( 4, addr, R_EAX );
    emit_ret();
 }
 
 
-/* Dispatch, but with a call-target check. */
-static void synth_jmp_lit_call_dispatch ( Addr addr )
-{
-   emit_movv_lit_reg ( 4, addr, R_EAX );
-   emit_movv_lit_reg ( 4, VG_EBP_DISPATCH_CHECKED, R_EBP );
-   emit_ret();
-}
-
-
 static void synth_jcond_lit ( Condcode cond, Addr addr )
 {
   /* Do the following:
@@ -1124,7 +1128,7 @@
   */
    emit_get_eflags();
    emit_jcondshort_delta ( invertCondition(cond), 5+1 );
-   synth_jmp_lit ( addr );
+   synth_jmp_lit ( addr, JmpBoring );
 }
 
 
@@ -1138,7 +1142,7 @@
    */
    emit_cmpl_zero_reg ( reg );
    emit_jcondshort_delta ( CondNZ, 5+1 );
-   synth_jmp_lit ( addr );
+   synth_jmp_lit ( addr, JmpBoring );
 }
 
 
@@ -2472,25 +2476,29 @@
          vg_assert(u->tag2 == NoValue);
          vg_assert(u->tag1 == RealReg || u->tag1 == Literal);
          if (u->cond == CondAlways) {
-            if (u->tag1 == RealReg) {
-               synth_jmp_reg ( u->val1, u->ret_dispatch, u->call_dispatch );
-            } else {
-               vg_assert(!u->ret_dispatch);
-               if (u->call_dispatch)
-                  synth_jmp_lit_call_dispatch ( 
-                     u->tag1==Literal ? u->lit32 : u->val1 );
-               else
-                  synth_jmp_lit ( 
-                     u->tag1==Literal ? u->lit32 : u->val1 );
+            switch (u->tag1) {
+               case RealReg:
+                  synth_jmp_reg ( u->val1, u->jmpkind );
+                  break;
+               case Literal:
+                  synth_jmp_lit ( u->lit32, u->jmpkind );
+                  break;
+               default: 
+                  VG_(panic)("emitUInstr(JMP, unconditional, default)");
+                  break;
             }
          } else {
-            if (u->tag1 == RealReg) {
-               VG_(panic)("emitUInstr: conditional jump to reg");
-            } else {
-               vg_assert(!u->ret_dispatch);
-               vg_assert(!u->call_dispatch);
-               synth_jcond_lit ( u->cond, 
-                                 u->tag1==Literal ? u->lit32 : u->val1 );
+            switch (u->tag1) {
+               case RealReg:
+                  VG_(panic)("emitUInstr(JMP, conditional, RealReg)");
+                  break;
+               case Literal:
+                  vg_assert(u->jmpkind == JmpBoring);
+                  synth_jcond_lit ( u->cond, u->lit32 );
+                  break;
+               default: 
+                  VG_(panic)("emitUInstr(JMP, conditional, default)");
+                  break;
             }
          }
          break;