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/vg_clientmalloc.c b/vg_clientmalloc.c
index d2be752..d59a029 100644
--- a/vg_clientmalloc.c
+++ b/vg_clientmalloc.c
@@ -250,10 +250,9 @@
 /* Allocate memory, noticing whether or not we are doing the full
    instrumentation thing. */
 
-void* VG_(client_malloc) ( UInt size, UInt raw_alloc_kind )
+void* VG_(client_malloc) ( UInt size, VgAllocKind kind )
 {
    ShadowChunk* sc;
-   VgAllocKind kind;
 
    VGP_PUSHCC(VgpCliMalloc);
    client_malloc_init();
@@ -263,21 +262,15 @@
                count_freelist(), vg_freed_list_volume,
                size, raw_alloc_kind );
 #  endif
+
+   vg_cmalloc_n_mallocs ++;
+   vg_cmalloc_bs_mallocd += size;
+
    if (!VG_(clo_instrument)) {
       VGP_POPCC;
       return VG_(malloc) ( VG_AR_CLIENT, size );
    }
-   switch (raw_alloc_kind) {
-      case 0x4002: kind = Vg_AllocNewVec; break;
-      case 0x4001: kind = Vg_AllocNew; break;
-      case 0x4000: /* malloc */
-      case 6666:   /* calloc */
-                   kind = Vg_AllocMalloc; break;
-      default:     /* should not happen */
-                   /* therefore we make sure it doesn't -- JRS */
-                   VG_(panic)("VG_(client_malloc): raw_alloc_kind");
-                   break; /*NOTREACHED*/
-   }
+
    sc = client_malloc_shadow ( 0, size, kind );
    VGP_POPCC;
    return (void*)(sc->data);
@@ -295,6 +288,10 @@
                count_freelist(), vg_freed_list_volume,
                align, size );
 #  endif
+
+   vg_cmalloc_n_mallocs ++;
+   vg_cmalloc_bs_mallocd += size;
+
    if (!VG_(clo_instrument)) {
       VGP_POPCC;
       return VG_(malloc_aligned) ( VG_AR_CLIENT, align, size );
@@ -305,11 +302,10 @@
 }
 
 
-void VG_(client_free) ( void* ptrV, UInt raw_alloc_kind )
+void VG_(client_free) ( void* ptrV, VgAllocKind kind )
 {
    ShadowChunk* sc;
    UInt         ml_no;
-   VgAllocKind  kind;
 
    VGP_PUSHCC(VgpCliMalloc);
    client_malloc_init();
@@ -319,6 +315,9 @@
                count_freelist(), vg_freed_list_volume,
                ptrV, raw_alloc_kind );
 #  endif
+
+   vg_cmalloc_n_frees ++;
+
    if (!VG_(clo_instrument)) {
       VGP_POPCC;
       VG_(free) ( VG_AR_CLIENT, ptrV );
@@ -340,16 +339,6 @@
       return;
    }
 
-   switch (raw_alloc_kind) {
-      case 0x5002: kind = Vg_AllocNewVec; break;
-      case 0x5001: kind = Vg_AllocNew; break;
-      case 0x5000: 
-      default:
-         kind = Vg_AllocMalloc;
-         /* should only happen if bug in client code */
-         break;
-   }
-
    /* check if its a matching free() / delete / delete [] */
    if (kind != sc->allockind)
       VG_(record_freemismatch_error) ( (Addr) ptrV );
@@ -386,6 +375,9 @@
                nmemb, size1 );
 #  endif
 
+   vg_cmalloc_n_mallocs ++;
+   vg_cmalloc_bs_mallocd += nmemb * size1;
+
    if (!VG_(clo_instrument)) {
       VGP_POPCC;
       return VG_(calloc) ( VG_AR_CLIENT, nmemb, size1 );
@@ -430,6 +422,10 @@
                ptrV, size_new );
 #  endif
 
+   vg_cmalloc_n_frees ++;
+   vg_cmalloc_n_mallocs ++;
+   vg_cmalloc_bs_mallocd += size_new;
+
    if (!VG_(clo_instrument)) {
       vg_assert(ptrV != NULL && size_new != 0);
       VGP_POPCC;
@@ -573,364 +569,6 @@
    return;
 }
 
-/*------------------------------------------------------------*/
-/*--- Replace the C library versions with our own.  Hairy. ---*/
-/*------------------------------------------------------------*/
-
-/* Below are new versions of malloc, __builtin_new, free, 
-   __builtin_delete, calloc and realloc.
-
-   malloc, __builtin_new, free, __builtin_delete, calloc and realloc
-   can be entered either on the real CPU or the simulated one.  If on
-   the real one, this is because the dynamic linker is running the
-   static initialisers for C++, before starting up Valgrind itself.
-   In this case it is safe to route calls through to
-   VG_(malloc)/vg_free, since that is self-initialising.
-
-   Once Valgrind is initialised, vg_running_on_simd_CPU becomes True.
-   The call needs to be transferred from the simulated CPU back to the
-   real one and routed to the vg_client_* functions.  To do that, the
-   args are passed to vg_trap_here, which the simulator detects.  The
-   bogus epilogue fn call is to guarantee that gcc doesn't tailcall
-   vg_trap_here, since that would cause the simulator's detection to
-   fail -- it only checks the targets of call transfers, not jumps.
-   And of course we have to be sure gcc won't inline either the
-   vg_trap_here or vg_bogus_epilogue.  Ha ha ha.  What a mess.
-*/
-
-/* Place afterwards to guarantee it won't get inlined ... */
-static UInt vg_trap_here_WRAPPER ( UInt arg1, UInt arg2, UInt what_to_do );
-static void vg_bogus_epilogue ( void );
-
-/* ALL calls to malloc wind up here. */
-void* malloc ( UInt n )
-{
-   if (VG_(clo_trace_malloc))
-      VG_(printf)("malloc[simd=%d](%d)", 
-                  (UInt)VG_(running_on_simd_CPU), n );
-
-   if (VG_(clo_sloppy_malloc)) { while ((n % 4) > 0) n++; }
-
-   vg_cmalloc_n_mallocs ++;
-   vg_cmalloc_bs_mallocd += n;
-
-   if (VG_(running_on_simd_CPU)) {
-      UInt v = vg_trap_here_WRAPPER ( 0, n, 0x4000 );
-      vg_bogus_epilogue();
-      if (VG_(clo_trace_malloc)) 
-         VG_(printf)(" = %p\n", v );
-      return (void*)v;
-   } else {
-      void* v = VG_(malloc)(VG_AR_CLIENT, n);
-      if (VG_(clo_trace_malloc)) 
-         VG_(printf)(" = %p\n", v );
-      return (void*)v;
-   }
-}
-
-void* __builtin_new ( UInt n )
-{
-   if (VG_(clo_trace_malloc))
-      VG_(printf)("__builtin_new[simd=%d](%d)", 
-                  (UInt)VG_(running_on_simd_CPU), n );
-
-   if (VG_(clo_sloppy_malloc)) { while ((n % 4) > 0) n++; }
-
-   vg_cmalloc_n_mallocs++;
-   vg_cmalloc_bs_mallocd += n;
-
-   if (VG_(running_on_simd_CPU)) {
-      UInt v = vg_trap_here_WRAPPER ( 0, n, 0x4001 );
-      vg_bogus_epilogue();
-      if (VG_(clo_trace_malloc)) 
-         VG_(printf)(" = %p\n", v );
-      return (void*)v;
-   } else {
-      void* v = VG_(malloc)(VG_AR_CLIENT, n);
-      if (VG_(clo_trace_malloc)) 
-         VG_(printf)(" = %p\n", v );
-      return v;
-   }
-}
-
-void* __builtin_vec_new ( Int n )
-{
-   if (VG_(clo_trace_malloc))
-      VG_(printf)("__builtin_vec_new[simd=%d](%d)", 
-                  (UInt)VG_(running_on_simd_CPU), n );
-
-   if (VG_(clo_sloppy_malloc)) { while ((n % 4) > 0) n++; }
-
-   vg_cmalloc_n_mallocs++;
-   vg_cmalloc_bs_mallocd += n;
-
-   if (VG_(running_on_simd_CPU)) {
-      UInt v = vg_trap_here_WRAPPER ( 0, n, 0x4002 );
-      vg_bogus_epilogue();
-      if (VG_(clo_trace_malloc)) 
-         VG_(printf)(" = %p\n", v );
-      return (void*)v;
-   } else {
-      void* v = VG_(malloc)(VG_AR_CLIENT, n);
-      if (VG_(clo_trace_malloc)) 
-         VG_(printf)(" = %p\n", v );
-      return v;
-   }
-}
-
-void free ( void* p )
-{
-   if (VG_(clo_trace_malloc))
-      VG_(printf)("free[simd=%d](%p)\n", 
-                  (UInt)VG_(running_on_simd_CPU), p );
-   vg_cmalloc_n_frees ++;
-
-   if (p == NULL) 
-      return;
-   if (VG_(running_on_simd_CPU)) {
-      (void)vg_trap_here_WRAPPER ( 0, (UInt)p, 0x5000 );
-      vg_bogus_epilogue();
-   } else {
-      VG_(free)(VG_AR_CLIENT, p);      
-   }
-}
-
-void __builtin_delete ( void* p )
-{
-   if (VG_(clo_trace_malloc))
-      VG_(printf)("__builtin_delete[simd=%d](%p)\n", 
-                  (UInt)VG_(running_on_simd_CPU), p );
-   vg_cmalloc_n_frees ++;
-
-   if (p == NULL) 
-      return;
-   if (VG_(running_on_simd_CPU)) {
-      (void)vg_trap_here_WRAPPER ( 0, (UInt)p, 0x5001 );
-      vg_bogus_epilogue();
-   } else {
-      VG_(free)(VG_AR_CLIENT, p);
-   }
-}
-
-void __builtin_vec_delete ( void* p )
-{
-   if (VG_(clo_trace_malloc))
-       VG_(printf)("__builtin_vec_delete[simd=%d](%p)\n", 
-                   (UInt)VG_(running_on_simd_CPU), p );
-   vg_cmalloc_n_frees ++;
-
-   if (p == NULL) 
-      return;
-   if (VG_(running_on_simd_CPU)) {
-      (void)vg_trap_here_WRAPPER ( 0, (UInt)p, 0x5002 );
-      vg_bogus_epilogue();
-   } else {
-      VG_(free)(VG_AR_CLIENT, p);
-   }
-}
-
-void* calloc ( UInt nmemb, UInt size )
-{
-   if (VG_(clo_trace_malloc))
-      VG_(printf)("calloc[simd=%d](%d,%d)", 
-                  (UInt)VG_(running_on_simd_CPU), nmemb, size );
-   vg_cmalloc_n_mallocs ++;
-   vg_cmalloc_bs_mallocd += size * nmemb;
-
-   if (VG_(running_on_simd_CPU)) {
-      UInt v = vg_trap_here_WRAPPER ( nmemb, size, 6666 );
-      vg_bogus_epilogue();
-      if (VG_(clo_trace_malloc)) 
-         VG_(printf)(" = %p\n", v );
-      return (void*)v;
-   } else {
-      void* v = VG_(calloc)(VG_AR_CLIENT, nmemb, size);
-      if (VG_(clo_trace_malloc)) 
-         VG_(printf)(" = %p\n", v );
-      return v;
-   }
-}
-
-void* realloc ( void* ptrV, UInt new_size )
-{
-   if (VG_(clo_trace_malloc))
-      VG_(printf)("realloc[simd=%d](%p,%d)", 
-                  (UInt)VG_(running_on_simd_CPU), ptrV, new_size );
-
-   if (VG_(clo_sloppy_malloc)) 
-      { while ((new_size % 4) > 0) new_size++; }
-
-   vg_cmalloc_n_frees ++;
-   vg_cmalloc_n_mallocs ++;
-   vg_cmalloc_bs_mallocd += new_size;
-
-   if (ptrV == NULL)
-      return malloc(new_size);
-   if (new_size == 0) {
-      free(ptrV);
-      if (VG_(clo_trace_malloc)) 
-         VG_(printf)(" = 0\n" );
-      return NULL;
-   }   
-   if (VG_(running_on_simd_CPU)) {
-      UInt v = vg_trap_here_WRAPPER ( (UInt)ptrV, new_size, 7777 );
-      vg_bogus_epilogue();
-      if (VG_(clo_trace_malloc)) 
-         VG_(printf)(" = %p\n", v );
-      return (void*)v;
-   } else {
-      void* v = VG_(realloc)(VG_AR_CLIENT, ptrV, new_size);
-      if (VG_(clo_trace_malloc)) 
-         VG_(printf)(" = %p\n", v );
-      return v;
-   }
-}
-
-void* memalign ( Int alignment, Int n )
-{
-   if (VG_(clo_trace_malloc))
-      VG_(printf)("memalign[simd=%d](al %d, size %d)", 
-                  (UInt)VG_(running_on_simd_CPU), alignment, n );
-
-   if (VG_(clo_sloppy_malloc)) { while ((n % 4) > 0) n++; }
-
-   vg_cmalloc_n_mallocs ++;
-   vg_cmalloc_bs_mallocd += n;
-
-   if (VG_(running_on_simd_CPU)) {
-      UInt v = vg_trap_here_WRAPPER ( alignment, n, 8888 );
-      vg_bogus_epilogue();
-      if (VG_(clo_trace_malloc)) 
-         VG_(printf)(" = %p\n", v );
-      return (void*)v;
-   } else {
-      void* v = VG_(malloc_aligned)(VG_AR_CLIENT, alignment, n);
-      if (VG_(clo_trace_malloc)) 
-         VG_(printf)(" = %p\n", v );
-      return (void*)v;
-   }
-}
-
-void* valloc ( Int size )
-{
-   return memalign(VKI_BYTES_PER_PAGE, size);
-}
-
-
-/* Various compatibility wrapper functions, for glibc and libstdc++. */
-void cfree ( void* p )
-{
-   free ( p );
-}
-
-void* mallinfo ( void )
-{ 
-   VG_(message)(Vg_UserMsg, 
-                "Warning: incorrectly-handled call to mallinfo()"); 
-   return NULL;
-}
-
-
-
-int mallopt ( int cmd, int value )
-{
-   /* In glibc-2.2.4, 1 denoted a successful return value for mallopt */
-   return 1;
-}
-
-
-/* Bomb out if we get any of these. */
-void pvalloc ( void )
-{ VG_(panic)("call to pvalloc\n"); }
-
-void malloc_stats ( void )
-{ VG_(panic)("call to malloc_stats\n"); }
-void malloc_usable_size ( void )
-{ VG_(panic)("call to malloc_usable_size\n"); }
-void malloc_trim ( void )
-{ VG_(panic)("call to malloc_trim\n"); }
-void malloc_get_state ( void )
-{ VG_(panic)("call to malloc_get_state\n"); }
-void malloc_set_state ( void )
-{ VG_(panic)("call to malloc_set_state\n"); }
-
-
-int __posix_memalign ( void **memptr, UInt alignment, UInt size )
-{
-    void *mem;
-
-    /* Test whether the SIZE argument is valid.  It must be a power of
-       two multiple of sizeof (void *).  */
-    if (size % sizeof (void *) != 0 || (size & (size - 1)) != 0)
-       return 22 /*EINVAL*/;
-
-    mem = memalign (alignment, size);
-
-    if (mem != NULL) {
-       *memptr = mem;
-       return 0;
-    }
-
-    return 12 /*ENOMEM*/;
-}
-
- 
-/*------------------------------------------------------------*/
-/*--- Magic supporting hacks.                              ---*/
-/*------------------------------------------------------------*/
-
-extern UInt VG_(trap_here) ( UInt arg1, UInt arg2, UInt what_to_do );
-
-static
-UInt vg_trap_here_WRAPPER ( UInt arg1, UInt arg2, UInt what_to_do )
-{
-   /* The point of this idiocy is to make a plain, ordinary call to
-      vg_trap_here which vg_dispatch_when_CALL can spot.  Left to
-      itself, with -fpic, gcc generates "call vg_trap_here@PLT" which
-      doesn't get spotted, for whatever reason.  I guess I could check
-      _all_ control flow transfers, but that would be an undesirable
-      performance overhead. 
-
-      If you compile without -fpic, gcc generates the obvious call
-      insn, so the wrappers below will work if they just call
-      vg_trap_here.  But I don't want to rule out building with -fpic,
-      hence this hack.  Sigh.
-   */
-   UInt v;
-
-#  define WHERE_TO       VG_(trap_here)
-#  define STRINGIFY(xx)  __STRING(xx)
-
-   asm("# call to vg_trap_here\n"
-       "\t pushl %3\n"
-       "\t pushl %2\n"
-       "\t pushl %1\n"
-       "\t call  "  STRINGIFY(WHERE_TO) "\n"
-       "\t addl $12, %%esp\n"
-       "\t movl %%eax, %0\n"
-       : "=r" (v)
-       : "r" (arg1), "r" (arg2), "r" (what_to_do)
-       : "eax", "esp", "cc", "memory");
-   return v;
-
-#  undef WHERE_TO
-#  undef STRINGIFY
-}
-
-/* Last, but not least ... */
-void vg_bogus_epilogue ( void )
-{
-   /* Runs on simulated CPU only. */
-}
-
-UInt VG_(trap_here) ( UInt arg1, UInt arg2, UInt what_to_do )
-{
-   /* Calls to this fn are detected in vg_dispatch.S and are handled
-      specially.  So this fn should never be entered.  */
-   VG_(panic)("vg_trap_here called!");
-   return 0; /*NOTREACHED*/
-}
-
 
 /*--------------------------------------------------------------------*/
 /*--- end                                        vg_clientmalloc.c ---*/