This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[tree-ssa libmudflap] more threading fixes, warning cleanups


Hi -

The following monster patch might perhaps conclude several weeks
of painmaking debugging of various libmudflap/linuxthread
interactions, and includes cleanup of nearly all -Wall notices.

- FChE



--- ChangeLog.tree-ssa	23 Jul 2003 18:41:30 -0000	1.1.2.515
+++ ChangeLog.tree-ssa	23 Jul 2003 21:10:26 -0000
+2003-07-23  Frank Ch. Eigler  <fche@redhat.com>
+
+	* gcc.c (MFWRAP_SPEC): Also wrap pthread_join and pthread_exit.

Index: gcc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcc.c,v
retrieving revision 1.324.2.35
diff -u -r1.324.2.35 gcc.c
--- gcc.c	23 Jul 2003 16:59:44 -0000	1.324.2.35
+++ gcc.c	23 Jul 2003 21:10:27 -0000
@@ -601,7 +601,7 @@
 #define MFWRAP_SPEC " %{static: %{fmudflap|fmudflapth: \
  --wrap=malloc --wrap=free --wrap=calloc --wrap=realloc\
  --wrap=mmap --wrap=munmap --wrap=alloca\
-} %{fmudflapth: --wrap=pthread_create\
+} %{fmudflapth: --wrap=pthread_create --wrap=pthread_join --wrap=pthread_exit\
 }} %{fmudflap|fmudflapth: --wrap=main}"
 #endif
 #ifndef MFLIB_SPEC


+ 2003-07-23  Frank Ch. Eigler  <fche@redhat.com>
+ 
+ 	Multithreading fixes:
+ 	* mf-runtime.c (__mf_object): Store allocating/deallocating
+ 	thread id.
+ 	(options): Support new "-thread-stack" option.
+ 	Rename "-heur-argv-environ" option to "-heur-stdlib".
+ 	Disable "-lc-mask" and "-lc-shift" options.
+ 	(__mf_dynamic): Add function pointers for pthread_join/_exit.
+ 	(__assert_fail): New self-contained function for glibc.
+ 	* mf-hooks3.c: Essentially rewritten, particularly related to
+ 	use of __mf_pthread_info array.
+ 	(pthread_join, _exit): New hook functions.
+ 	* mf-impl.h (BEGIN_PROTECT): Handle starting_p case.
+ 	* testsuite/libmudflap.cth/pass40-frag.c: New test.
+ 
+ 	Warning cleanups:
+ 	* mf-heuristics.c: Add type casts for tracing, sub calls.
+ 	* mf-impl.h (BEGIN_PROTECT): Redefine to omit result type.
+ 	Update all callers to declare explicit result holder.
+ 	(END_PROTECT): Removed.
+ 	* testsuite/*/*frags.exp: Clean up default MUDFLAP_OPTIONS.

Index: mf-heuristics.c
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-heuristics.c,v
retrieving revision 1.1.2.16
diff -c -p -w -r1.1.2.16 mf-heuristics.c
*** mf-heuristics.c	4 Jul 2003 23:10:09 -0000	1.1.2.16
--- mf-heuristics.c	23 Jul 2003 21:10:56 -0000
*************** __mf_heuristic_check (uintptr_t ptr, uin
*** 44,57 ****
      {
        uintptr_t stack_top_guess = (uintptr_t)__builtin_frame_address(0);
  #if defined(__i386__) && defined (__linux__)
!       uintptr_t stack_segment_base = 0xC0000000;
  #else
        /* Cause tests to fail. */
        uintptr_t stack_segment_base = 0;
  #endif
  
!       VERBOSE_TRACE ("mf: stack estimated as %08lx-%08lx\n", 
! 		     stack_top_guess, stack_segment_base);
  
        if (ptr_high <= stack_segment_base &&
  	  ptr >= stack_top_guess &&
--- 44,57 ----
      {
        uintptr_t stack_top_guess = (uintptr_t)__builtin_frame_address(0);
  #if defined(__i386__) && defined (__linux__)
!       uintptr_t stack_segment_base = 0xC0000000; /* XXX: Bad assumption. */
  #else
        /* Cause tests to fail. */
        uintptr_t stack_segment_base = 0;
  #endif
  
!       VERBOSE_TRACE ("mf: stack estimated as %p-%p\n", 
! 		     (void *) stack_top_guess, (void *) stack_segment_base);
  
        if (ptr_high <= stack_segment_base &&
  	  ptr >= stack_top_guess &&
*************** __mf_heuristic_check (uintptr_t ptr, uin
*** 125,134 ****
  			    }
  			  
  			  VERBOSE_TRACE ("mf: registering region #%d "
! 					 "%08lx-%08lx given %s",
! 					 i, (uintptr_t) low, (uintptr_t) high, buf);
  			  
! 			  __mfu_register ((uintptr_t) low, (uintptr_t) (high-low),
  					  __MF_TYPE_GUESS, 
  					  "/proc/self/maps segment");
  			  
--- 125,134 ----
  			    }
  			  
  			  VERBOSE_TRACE ("mf: registering region #%d "
! 					 "%p-%p given %s",
! 					 i, (void *) low, (void *) high, buf);
  			  
! 			  __mfu_register ((void *) low, (size_t) (high-low),
  					  __MF_TYPE_GUESS, 
  					  "/proc/self/maps segment");
  			  
Index: mf-hooks1.c
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-hooks1.c,v
retrieving revision 1.1.2.1
diff -c -p -w -r1.1.2.1 mf-hooks1.c
*** mf-hooks1.c	4 Jul 2003 23:10:09 -0000	1.1.2.1
--- mf-hooks1.c	23 Jul 2003 21:10:56 -0000
*************** WRAPPER(void *, malloc, size_t c)
*** 58,64 ****
  {
    size_t size_with_crumple_zones;
    DECLARE(void *, malloc, size_t c);
!   BEGIN_PROTECT (void *, malloc, c);
    
    size_with_crumple_zones = 
      CLAMPADD(c,CLAMPADD(__mf_opts.crumple_zone,
--- 58,65 ----
  {
    size_t size_with_crumple_zones;
    DECLARE(void *, malloc, size_t c);
!   void *result;
!   BEGIN_PROTECT (malloc, c);
  
    size_with_crumple_zones = 
      CLAMPADD(c,CLAMPADD(__mf_opts.crumple_zone,
*************** WRAPPER(void *, calloc, size_t c, size_t
*** 109,115 ****
    DECLARE(void *, calloc, size_t, size_t);
    DECLARE(void *, malloc, size_t);
    DECLARE(void *, memset, void *, int, size_t);
!   BEGIN_PROTECT (char *, calloc, c, n);
    
    size_with_crumple_zones = 
      CLAMPADD((c * n), /* XXX: CLAMPMUL */
--- 110,117 ----
    DECLARE(void *, calloc, size_t, size_t);
    DECLARE(void *, malloc, size_t);
    DECLARE(void *, memset, void *, int, size_t);
!   char *result;
!   BEGIN_PROTECT (calloc, c, n);
    
    size_with_crumple_zones = 
      CLAMPADD((c * n), /* XXX: CLAMPMUL */
*************** WRAPPER(void *, realloc, void *buf, size
*** 149,156 ****
    size_t size_with_crumple_zones;
    char *base = buf;
    unsigned saved_wipe_heap;
! 
!   BEGIN_PROTECT (char *, realloc, buf, c);
  
    if (LIKELY(buf))
      base -= __mf_opts.crumple_zone;
--- 151,158 ----
    size_t size_with_crumple_zones;
    char *base = buf;
    unsigned saved_wipe_heap;
!   char *result;
!   BEGIN_PROTECT (realloc, buf, c);
  
    if (LIKELY(buf))
      base -= __mf_opts.crumple_zone;
*************** WRAPPER(void, free, void *buf)
*** 206,220 ****
    static void *free_queue [__MF_FREEQ_MAX];
    static unsigned free_ptr = 0;
    static int freeq_initialized = 0;
!   DECLARE(void * , free, void *);  
  
!   BEGIN_PROTECT(void *, free, buf);
  
    if (UNLIKELY(buf == NULL))
      return;
  
-   TRACE ("free %p\n", __PRETTY_FUNCTION__, buf);
- 
    LOCKTH ();
    if (UNLIKELY(!freeq_initialized))
      {
--- 208,220 ----
    static void *free_queue [__MF_FREEQ_MAX];
    static unsigned free_ptr = 0;
    static int freeq_initialized = 0;
!   DECLARE(void, free, void *);  
   
!   BEGIN_PROTECT (free, buf);
  
    if (UNLIKELY(buf == NULL))
      return;
  
    LOCKTH ();
    if (UNLIKELY(!freeq_initialized))
      {
*************** WRAPPER(void, free, void *buf)
*** 256,264 ****
        base -= __mf_opts.crumple_zone;
        if (__mf_opts.trace_mf_calls)
  	{
! 	  VERBOSE_TRACE ("freeing pointer %08lx = %08lx - %u\n",
! 			 (uintptr_t) base, 
! 			 (uintptr_t) buf, 
  			 __mf_opts.crumple_zone);
  	}
        CALL_REAL(free, base);
--- 256,264 ----
        base -= __mf_opts.crumple_zone;
        if (__mf_opts.trace_mf_calls)
  	{
! 	  VERBOSE_TRACE ("freeing pointer %p = %p - %u\n",
! 			 (void *) base, 
! 			 (void *) buf, 
  			 __mf_opts.crumple_zone);
  	}
        CALL_REAL (free, base);
*************** WRAPPER(void *, mmap, 
*** 284,294 ****
  	void  *start,  size_t length, int prot, 
  	int flags, int fd, off_t offset)
  {
- 
    DECLARE(void *, mmap, void *, size_t, int, 
  			    int, int, off_t);
!   BEGIN_PROTECT(void *, mmap, start, length, 
! 		prot, flags, fd, offset);
  
    result = CALL_REAL(mmap, start, length, prot, 
  			flags, fd, offset);
--- 284,293 ----
  	void  *start,  size_t length, int prot, 
  	int flags, int fd, off_t offset)
  {
    DECLARE(void *, mmap, void *, size_t, int, 
  			    int, int, off_t);
!   void *result;
!   BEGIN_PROTECT (mmap, start, length, prot, flags, fd, offset);
  
    result = CALL_REAL (mmap, start, length, prot, 
  			flags, fd, offset);
*************** __mf_0fn_munmap (void *start, size_t len
*** 340,346 ****
  WRAPPER(int , munmap, void *start, size_t length)
  {
    DECLARE(int, munmap, void *, size_t);
!   BEGIN_PROTECT(int, munmap, start, length);
    
    result = CALL_REAL(munmap, start, length);
  
--- 339,346 ----
  WRAPPER(int , munmap, void *start, size_t length)
  {
    DECLARE(int, munmap, void *, size_t);
!   int result;
!   BEGIN_PROTECT (munmap, start, length);
    
    result = CALL_REAL (munmap, start, length);
  
*************** __mf_wrap_alloca_indirect (size_t c)
*** 389,395 ****
    struct alloca_tracking *track;
  
    TRACE ("%s\n", __PRETTY_FUNCTION__);
!   VERBOSE_TRACE ("alloca stack level %08lx\n", (uintptr_t) stack);
  
    /* XXX: thread locking! */
  
--- 389,395 ----
    struct alloca_tracking *track;
  
    TRACE ("%s\n", __PRETTY_FUNCTION__);
!   VERBOSE_TRACE ("alloca stack level %p\n", (void *) stack);
  
    /* XXX: thread locking! */
  
Index: mf-hooks3.c
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-hooks3.c,v
retrieving revision 1.1.2.1
diff -c -p -w -r1.1.2.1 mf-hooks3.c
*** mf-hooks3.c	4 Jul 2003 23:10:09 -0000	1.1.2.1
--- mf-hooks3.c	23 Jul 2003 21:10:56 -0000
*************** XXX: libgcc license?
*** 20,32 ****
  #include <string.h>
  #include <stdio.h>
  #include <stdlib.h>
- #include <sys/time.h>
  #include <sys/types.h>
  #include <unistd.h>
  #include <assert.h>
  #include <errno.h>
  #include <limits.h>
! #include <time.h>
  
  #include "mf-runtime.h"
  #include "mf-impl.h"
--- 20,32 ----
  #include <string.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <sys/types.h>
+ #include <sys/mman.h>
  #include <unistd.h>
  #include <assert.h>
  #include <errno.h>
  #include <limits.h>
! #include <sched.h>
  
  #include "mf-runtime.h"
  #include "mf-impl.h"
*************** XXX: libgcc license?
*** 41,63 ****
  
  #ifdef WRAP_pthreadstuff
  
  #ifndef LIBMUDFLAPTH
  #error "pthreadstuff is to be included only in libmudflapth"
  #endif
  
  
  
! /* Describes a thread (dead or alive). */
  struct pthread_info
  {
    short used_p;  /* Is this slot in use?  */
! 
    pthread_t self; /* The thread id.  */
-   short dead_p;  /* Has thread died?  */
- 
-   /* The user's thread entry point and argument.  */
-   void * (*user_fn)(void *);
-   void *user_arg;
  
    /* If libmudflapth allocated the stack, store its base/size.  */
    void *stack;
--- 41,59 ----
  
  #ifdef WRAP_pthreadstuff
  
+ 
  #ifndef LIBMUDFLAPTH
  #error "pthreadstuff is to be included only in libmudflapth"
  #endif
  
  
  
! /* Describe a thread (dead or alive). */
  struct pthread_info
  {
    short used_p;  /* Is this slot in use?  */
!   short dead_p;  /* Is this thread dead?  */
    pthread_t self; /* The thread id.  */
  
    /* If libmudflapth allocated the stack, store its base/size.  */
    void *stack;
*************** struct pthread_info
*** 68,147 ****
  };
  
  
! /* To avoid dynamic memory allocation, use static array.
!    It is used as a simple hash table.  */
  #define LIBMUDFLAPTH_THREADS_MAX 1024
  static struct pthread_info __mf_pthread_info[LIBMUDFLAPTH_THREADS_MAX];
  #define PTHREAD_HASH(p) ((unsigned) (p) % LIBMUDFLAPTH_THREADS_MAX)
- /* XXX: locking required? */
  
  
! /* Find and return the pthread_info struct for the running thread.  */
  struct pthread_info* 
  __mf_find_threadinfo ()
  {
!   pthread_t self = pthread_self ();
!   unsigned hash = PTHREAD_HASH (self);
!   unsigned i;
    struct pthread_info *result = NULL;
  
!   for (i = hash; 
!        (i+1) % LIBMUDFLAPTH_THREADS_MAX != hash; 
!        i = (i+1) % LIBMUDFLAPTH_THREADS_MAX)
!     {
!       struct pthread_info* pi = & __mf_pthread_info [i];
!       if (pi->used_p && pi->self == self) 
  	{
  	  result = pi;
  	  break;
  	}
      }
- 
-   /* XXX: This is too slow for the main thread.  It will not show up
-      in the table since it was not created with pthread_create(), but
-      will have to search the entire table.  */
- 
-   return result;
  }
  
! 
! struct pthread_info* 
! __mf_create_threadinfo ()
  {
!   pthread_t self = pthread_self ();
!   unsigned hash = PTHREAD_HASH (self);
!   unsigned i;
!   struct pthread_info *result = NULL;
  
!   for (i = hash; 
!        (i+1) % LIBMUDFLAPTH_THREADS_MAX != hash; 
!        i = (i+1) % LIBMUDFLAPTH_THREADS_MAX)
      {
!       struct pthread_info* pi = & __mf_pthread_info [i];
!       if (! pi->used_p)
  	{
! 	  pi->used_p = 1;
! 	  pi->self = self;
! 	  result = pi;
! 	  break;
  	}
      }
  
    return result;
  }
  
  
  
  enum __mf_state_enum *
  __mf_state_perthread ()
  {
!   static enum __mf_state_enum __mf_state_global = active;
!   struct pthread_info *pi = __mf_find_threadinfo ();
! 
!   if (pi == NULL)
!     return & __mf_state_global;
!   else
!     return & pi->state;
  }
  
  
--- 64,233 ----
  };
  
  
! /* Describe the startup information for a new user thread.  */
! struct pthread_start_info
! {
!   /* The user's thread entry point and argument.  */
!   void * (*user_fn)(void *);
!   void *user_arg;
! 
!   /* Set by user thread when this startup struct may be disposed of.  */
!   struct pthread_info *thread_info;
! };
! 
! 
! 
! 
! /* To avoid dynamic memory allocation, use static array to store these
!    thread description structs.  The second (_idx) array is used as a
!    simple caching hash table, mapping PTHREAD_HASH(thread) to its
!    index in __mf_pthread_info[]. */
! 
  #define LIBMUDFLAPTH_THREADS_MAX 1024
  static struct pthread_info __mf_pthread_info[LIBMUDFLAPTH_THREADS_MAX];
+ static unsigned __mf_pthread_info_idx[LIBMUDFLAPTH_THREADS_MAX];
  #define PTHREAD_HASH(p) ((unsigned) (p) % LIBMUDFLAPTH_THREADS_MAX)
  
  
! /* Find any old empty entry in __mf_pthread_info; mark it used and
!    return it.  Return NULL if there are no more available slots.  */
  struct pthread_info* 
+ __mf_allocate_blank_threadinfo (unsigned* idx)
+ {
+   static unsigned probe = LIBMUDFLAPTH_THREADS_MAX-1;
+   unsigned probe_at_start = probe;
+   static pthread_mutex_t mutex =
+ #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
+     PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+ #else
+     PTHREAD_MUTEX_INITIALIZER;
+ #endif
+   int rc;
+ 
+   rc = pthread_mutex_lock (& mutex);
+   assert (rc == 0);
+ 
+   /* Look for a blank spot starting one past the last one we found. */
+   do
+     {
+       probe = (probe + 1) % LIBMUDFLAPTH_THREADS_MAX;
+       struct pthread_info* pi = & __mf_pthread_info [probe];
+       if (! pi->used_p)
+ 	{
+ 	  /* memset (pi, 0, sizeof (*pi)); */
+ 	  pi->used_p = 1;
+ 	  if (idx != NULL) *idx = probe;
+ 	  /* VERBOSE_TRACE ("allocated threadinfo slot %u\n", probe); */
+ 	  rc = pthread_mutex_unlock (& mutex);
+ 	  assert (rc == 0);
+ 	  return pi;
+ 	}
+     }
+   while (probe != probe_at_start);
+   
+   rc = pthread_mutex_unlock (& mutex);
+   assert (rc == 0);
+   return NULL;
+ }
+ 
+ 
+ /* Find and return the pthread_info struct for the current thread.
+    There might already be one in __mf_pthread_info for this thread, in
+    which case return it.  There may not be one (if this is a main
+    thread, an auxiliary -lpthread manager, or an actual user thread
+    making an early call into libmudflap.  In these cases, create a new
+    entry.  If not it's not the main thread, put it into reentrant
+    initial state.
+ */
+ static struct pthread_info* 
  __mf_find_threadinfo ()
  {
!   pthread_t it = pthread_self ();
!   unsigned *hash = & __mf_pthread_info_idx [PTHREAD_HASH (it)];
    struct pthread_info *result = NULL;
+   static pthread_t last;
+   static int main_thread_seen_p;
  
!   /* Check out the lookup cache; failing that, do a linear search
!      around the table.  */
    {
+     struct pthread_info* pi = & __mf_pthread_info [*hash];
+     unsigned i;
+ 
+     if (pi->used_p && pi->self == it)
        result = pi;
+     else for (i = 0; i < LIBMUDFLAPTH_THREADS_MAX; i++)
+       {
+ 	struct pthread_info* pi2 = & __mf_pthread_info [i];
+ 	if (pi2->used_p && pi2->self == it) 
+ 	  {
+ 	    *hash = i;
+ 	    result = pi2;
  	    break;
  	  }
        }
    }    
  
!   if (result == NULL)
      {
!       /* Create a __mf_pthread_info record for the main thread.  It's
! 	 different from the auto-recognized worker bees because for
! 	 example we can assume that it's a fully stack/errno-equipped
! 	 thread. */
! 
!       /* This must be the main thread, until now unseen in libmudflap.  */
!       unsigned *hash = & __mf_pthread_info_idx [PTHREAD_HASH (it)];
!       struct pthread_info* pi = __mf_allocate_blank_threadinfo (hash);
!       assert (pi != NULL);
!       assert (pi->used_p);
!       result = pi;
!       result->self = it;
  
!       if (! main_thread_seen_p)
  	{
! 	  result->state = active;
! 	  /* NB: leave result->thread_errno unset, as main thread's errno
! 	     has already been registered in __mf_init.  */
! 	  /* NB: leave stack-related fields unset, to avoid
! 	     deallocation.  */
! 	  main_thread_seen_p = 1;
! 	  VERBOSE_TRACE ("identified self as main thread\n");
! 	}
!       else
  	{
! 	  result->state = reentrant;
! 	  /* NB: leave result->thread_errno unset, as worker thread's
! 	     errno is unlikely to be used, and user threads fill them
! 	     in during __mf_pthread_spawn().  */
! 	  /* NB: leave stack-related fields unset, leaving pthread_create
! 	     to fill them in for user threads, leaving them empty for
! 	     other threads.  */
! 	  VERBOSE_TRACE ("identified self as new aux or user thread\n");
  	}
      }
  
+   if (last != it)
+     {
+       VERBOSE_TRACE ("found threadinfo for %u, slot %u\n", 
+ 		     (unsigned) it,
+ 		     (unsigned) *hash);
+       last = it;
+     }
+ 
+   assert (result != NULL);
+   assert (result->self == it);
+ 
    return result;
  }
  
  
  
+ /* Return a pointer to the per-thread __mf_state variable.  */
  enum __mf_state_enum *
  __mf_state_perthread ()
  {
!   assert (! __mf_starting_p);
!   return & (__mf_find_threadinfo()->state);
  }
  
  
*************** __mf_pthread_cleanup (void *arg)
*** 152,173 ****
  
    /* XXX: This unregistration is not safe on platforms where distinct
       threads share errno (or at least its virtual address).  */
!   if (__mf_opts.heur_std_data)
      __mf_unregister (pi->thread_errno, sizeof (int));
    pi->dead_p = 1;
  
!   /* Some subsequent pthread_create will garbage_collect our stack.  */
  }
  
  
- 
  static void *
  __mf_pthread_spawner (void *arg)
  {
!   struct pthread_info *pi = arg;
    void *result = NULL;
  
!   pi->self = pthread_self ();
  
    if (__mf_opts.heur_std_data)
      {
--- 238,267 ----
  
    /* XXX: This unregistration is not safe on platforms where distinct
       threads share errno (or at least its virtual address).  */
!   if (pi->thread_errno != NULL)
      __mf_unregister (pi->thread_errno, sizeof (int));
+ 
+   /* XXX: Only detached threads should designate themselves as dead
+      here.  Non-detached threads are marked dead after their
+      personalized pthread_join() call.  */
+   pi->state = reentrant;
    pi->dead_p = 1;
  
!   VERBOSE_TRACE ("thread pi %p exiting\n", pi);
  }
  
  
  static void *
  __mf_pthread_spawner (void *arg)
  {
!   struct pthread_info *pi = __mf_find_threadinfo ();
    void *result = NULL;
  
!   /* Turn off reentrancy indications.  */
!   assert (pi->state == reentrant);
!   pi->state = active;
! 
!   VERBOSE_TRACE ("new user thread\n");
    
    if (__mf_opts.heur_std_data)
      {
*************** __mf_pthread_spawner (void *arg)
*** 182,191 ****
    /* We considered using pthread_key_t objects instead of these
       cleanup stacks, but they were less cooperative with the
       interposed malloc hooks in libmudflap.  */
!   pthread_cleanup_push (& __mf_pthread_cleanup, arg);
  
    /* Call user thread */
!   result = pi->user_fn (pi->user_arg);
  
    pthread_cleanup_pop (1 /* execute */);
  
--- 276,295 ----
    /* We considered using pthread_key_t objects instead of these
       cleanup stacks, but they were less cooperative with the
       interposed malloc hooks in libmudflap.  */
!   pthread_cleanup_push (& __mf_pthread_cleanup, pi);
  
    /* Call user thread */
!   {
!     /* Extract given entry point and argument.  */
!     struct pthread_start_info *psi = arg;
!     void * (*user_fn)(void *) = psi->user_fn;
!     void *user_arg = psi->user_arg;
! 
!     /* Signal the main thread to resume.  */
!     psi->thread_info = pi;
!       
!     result = (*user_fn)(user_arg);
!   }
  
    pthread_cleanup_pop (1 /* execute */);
  
*************** __mf_0fn_pthread_create (pthread_t *thr,
*** 213,224 ****
  WRAPPER(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr, 
  	 void * (*start) (void *), void *arg)
  {
!   DECLARE(void, free, void *p);
!   DECLARE(void *, malloc, size_t c);
    DECLARE(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr, 
  	  void * (*start) (void *), void *arg);
    int result;
-   struct pthread_info *pi;
    pthread_attr_t override_attr;
    void *override_stack;
    size_t override_stacksize;
--- 317,327 ----
  WRAPPER(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr, 
  	 void * (*start) (void *), void *arg)
  {
!   DECLARE(int, munmap, void *p, size_t l);
!   DECLARE(void *, mmap, void *p, size_t l, int prot, int flags, int fd, off_t of);
    DECLARE(int, pthread_create, pthread_t *thr, const pthread_attr_t *attr, 
  	  void * (*start) (void *), void *arg);
    int result;
    pthread_attr_t override_attr;
    void *override_stack;
    size_t override_stacksize;
*************** WRAPPER(int, pthread_create, pthread_t *
*** 226,255 ****
  
    TRACE ("pthread_create\n");
  
!   /* Garbage collect dead thread stacks.  */
    for (i = 0; i < LIBMUDFLAPTH_THREADS_MAX; i++)
      {
!       pi = & __mf_pthread_info [i];
!       if (pi->used_p
! 	  && pi->dead_p 
! 	  && !pthread_kill (pi->self, 0)) /* Really dead?  XXX: safe?  */ 
  	{
! 	  if (pi->stack != NULL)
! 	    CALL_REAL (free, pi->stack);
  
! 	  pi->stack = NULL;
! 	  pi->stack_size = 0;
! 	  pi->used_p = 0;
! 	}
!     }
  
!   /* Find a slot in __mf_pthread_info to track this thread.  */
!   pi = __mf_create_threadinfo ();
!   if (pi == NULL) /* no slots free - simulated out-of-memory.  */
!     {
!       errno = EAGAIN;
!       return -1;
      }
  
    /* Let's allocate a stack for this thread, if one is not already
       supplied by the caller.  We don't want to let e.g. the
--- 329,364 ----
  
    TRACE ("pthread_create\n");
  
!   /* Garbage-collect dead threads' stacks.  */
!   LOCKTH ();
    for (i = 0; i < LIBMUDFLAPTH_THREADS_MAX; i++)
      {
!       struct pthread_info *pi = & __mf_pthread_info [i];
!       if (! pi->used_p)
! 	continue;
!       if (! pi->dead_p)
! 	continue;
! 
!       /* VERBOSE_TRACE ("thread %u pi %p stack cleanup deferred (%u)\n",
! 	 (unsigned) pi->self, pi, pi->dead_p); */
! 	      
!       /* Delay actual deallocation by a few cycles, try to discourage the
! 	 race mentioned at the end of __mf_pthread_spawner().  */
!       if (pi->dead_p)
! 	pi->dead_p ++;
!       if (pi->dead_p >= 10 /* XXX */)
  	{
! 	  if (pi->stack)
! 	    CALL_REAL (munmap, pi->stack, pi->stack_size);
  
! 	  VERBOSE_TRACE ("slot %u freed, stack %p\n", i, pi->stack);
! 	  memset (pi, 0, sizeof (*pi));
  
! 	  /* One round of garbage collection is enough.  */
! 	  break;
! 	}
      }
+   UNLOCKTH ();
  
    /* Let's allocate a stack for this thread, if one is not already
       supplied by the caller.  We don't want to let e.g. the
*************** WRAPPER(int, pthread_create, pthread_t *
*** 269,275 ****
      }
  
    /* Do we need to allocate the new thread's stack?  */
!   if (override_stack == NULL)
      {
        uintptr_t alignment = 256; /* power of two */
  
--- 378,384 ----
      }
  
    /* Do we need to allocate the new thread's stack?  */
!   if (__mf_opts.thread_stack && override_stack == NULL)
      {
        uintptr_t alignment = 256; /* power of two */
  
*************** WRAPPER(int, pthread_create, pthread_t *
*** 277,305 ****
  	 threads to have nonconflicting entries in the lookup cache
  	 for their tracked stack objects.  */
        static unsigned perturb = 0;
!       const unsigned perturb_delta = 0; /* 32; */
        const unsigned perturb_count = 16;
        perturb += perturb_delta;
        if (perturb > perturb_delta*perturb_count) perturb = 0;
  
        /* Use glibc x86 defaults */
-       if (override_stacksize < alignment)
  /* Should have been defined in <limits.h> */
  #ifndef PTHREAD_STACK_MIN
  #define PTHREAD_STACK_MIN 65536
  #endif
! 	override_stacksize = max (PTHREAD_STACK_MIN, 2 * 1024 * 1024);
  
!       override_stack = CALL_REAL (malloc, override_stacksize);
!       if (override_stack == NULL)
  	{
  	  errno = EAGAIN;
- 	  pi->used_p = 0;
  	  return -1;
  	}
  
!       pi->stack = override_stack;
!       pi->stack_size = override_stacksize;
  
        /* The stackaddr pthreads attribute is a candidate stack pointer.
  	 It must point near the top or the bottom of this buffer, depending
--- 386,415 ----
  	 threads to have nonconflicting entries in the lookup cache
  	 for their tracked stack objects.  */
        static unsigned perturb = 0;
!       const unsigned perturb_delta = 32;
        const unsigned perturb_count = 16;
        perturb += perturb_delta;
        if (perturb > perturb_delta*perturb_count) perturb = 0;
  
        /* Use glibc x86 defaults */
  /* Should have been defined in <limits.h> */
  #ifndef PTHREAD_STACK_MIN
  #define PTHREAD_STACK_MIN 65536
  #endif
!       override_stacksize = max (PTHREAD_STACK_MIN, __mf_opts.thread_stack * 1024);
  
!       override_stack = CALL_REAL (mmap, NULL, override_stacksize, 
! 				  PROT_READ|PROT_WRITE, 
! 				  MAP_PRIVATE|MAP_ANONYMOUS,
! 				  0, 0);
!       if (override_stack == 0 || override_stack == MAP_FAILED)
  	{
  	  errno = EAGAIN;
  	  return -1;
  	}
  
!       VERBOSE_TRACE ("thread stack alloc %p size %lu\n", 
! 		     override_stack, (unsigned long) override_stacksize);
  
        /* The stackaddr pthreads attribute is a candidate stack pointer.
  	 It must point near the top or the bottom of this buffer, depending
*************** WRAPPER(int, pthread_create, pthread_t *
*** 315,338 ****
  				     override_stacksize - alignment - perturb) != 0)
  	{
  	  /* This should not happen.  */
! 	  CALL_REAL (free, pi->stack);
! 	  pi->stack = NULL;
  	  errno = EAGAIN;
- 	  pi->used_p = 0;
  	  return -1;
  	}
- 
    }
  
!   /* Fill in remaining fields.  */
!   pi->user_fn = start;
!   pi->user_arg = arg;
!   pi->dead_p = 0;
!   pi->state = active;
  
    /* Actually create the thread.  */
    result = CALL_REAL (pthread_create, thr, & override_attr,
! 		      & __mf_pthread_spawner, (void *) pi);
    
    /* May need to clean up if we created a pthread_attr_t of our own.  */
    if (attr == NULL)
--- 425,473 ----
  				     override_stacksize - alignment - perturb) != 0)
  	{
  	  /* This should not happen.  */
! 	  CALL_REAL (munmap, override_stack, override_stacksize);
  	  errno = EAGAIN;
  	  return -1;
  	}
    }
  
!   /* Actually start the child thread.  */
!   {
!     struct pthread_start_info psi;
!     struct pthread_info *pi = NULL;
!     
!     /* Fill in startup-control fields.  */
!     psi.user_fn = start;
!     psi.user_arg = arg;
!     psi.thread_info = NULL;
      
      /* Actually create the thread.  */
+     __mf_state = reentrant;
      result = CALL_REAL (pthread_create, thr, & override_attr,
! 			& __mf_pthread_spawner, (void *) & psi);
!     __mf_state = active;
!     /* We also hook pthread_join/pthread_exit to get into reentrant
!        mode during thread shutdown/cleanup.  */
! 
!     /* Wait until child thread has progressed far enough into its
!        __mf_pthread_spawner() call.  */
!     while (1) /* XXX: timeout? */
!       {
! 	volatile struct pthread_start_info *psip = & psi;
! 	pi = psip->thread_info;
! 	if (pi != NULL) 
! 	  break;
! 	sched_yield ();
!       }
! 
!     /* Fill in remaining fields in pthread_info. */
!     pi->stack = override_stack;
!     pi->stack_size = override_stacksize;
!     /* XXX: this might be too late for future heuristics that attempt
!        to use thread stack bounds.  We may need to put the new thread
!        to sleep. */
!   }
! 
  
    /* May need to clean up if we created a pthread_attr_t of our own.  */
    if (attr == NULL)
*************** WRAPPER(int, pthread_create, pthread_t *
*** 340,345 ****
--- 475,532 ----
  
    return result;
  }
+ 
+ 
+ 
+ #if PIC
+ /* A special bootstrap variant. */
+ int
+ __mf_0fn_pthread_join (pthread_t thr, void **rc)
+ {
+   return -1;
+ }
+ #endif
+ 
+ 
+ #undef pthread_join
+ WRAPPER(int, pthread_join, pthread_t thr, void **rc)
+ {
+   DECLARE(int, pthread_join, pthread_t thr, void **rc);
+   int result;
+ 
+   TRACE ("pthread_join\n");
+   __mf_state = reentrant;
+   result = CALL_REAL (pthread_join, thr, rc);
+   __mf_state = active;
+   
+   return result;
+ }
+ 
+ 
+ #if PIC
+ /* A special bootstrap variant. */
+ void
+ __mf_0fn_pthread_exit (void *rc)
+ {
+ }
+ #endif
+ 
+ 
+ #undef pthread_exit
+ WRAPPER(void, pthread_exit, void *rc)
+ {
+   DECLARE(void, pthread_exit, void *rc);
+ 
+   TRACE ("pthread_exit\n");
+   /* __mf_state = reentrant; */
+   CALL_REAL (pthread_exit, rc);
+   /* NOTREACHED */
+ }
+ 
+ 
+ 
+ 
+ 
  
  
  #endif /* pthreadstuff */
Index: mf-impl.h
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-impl.h,v
retrieving revision 1.1.2.24
diff -c -p -w -r1.1.2.24 mf-impl.h
*** mf-impl.h	4 Jul 2003 23:10:09 -0000	1.1.2.24
--- mf-impl.h	23 Jul 2003 21:10:56 -0000
*************** struct __mf_options
*** 133,138 ****
--- 133,143 ----
    /* Maintain this many stack frames for contexts. */
    unsigned backtrace;
  
+ #ifdef LIBMUDFLAPTH
+   /* Thread stack size.  */
+   unsigned thread_stack;
+ #endif
+ 
    /* Major operation mode */
    enum
    {
*************** enum __mf_dynamic_index
*** 182,188 ****
    dyn_munmap, dyn_realloc, 
    dyn_INITRESOLVE,  /* Marker for last init-time resolution. */
  #ifdef LIBMUDFLAPTH 
!   dyn_pthread_create
  #endif
  };
  
--- 187,195 ----
    dyn_munmap, dyn_realloc, 
    dyn_INITRESOLVE,  /* Marker for last init-time resolution. */
  #ifdef LIBMUDFLAPTH 
!   dyn_pthread_create,
!   dyn_pthread_join,
!   dyn_pthread_exit
  #endif
  };
  
*************** ret __mfwrap_ ## fname (__VA_ARGS__)
*** 330,338 ****
    if (UNLIKELY (size > 0 && __MF_CACHE_MISS_P (value, size))) \
      __mf_check ((void *) (value), (size), acc, "(" context ")"); \
   } while (0)
! #define BEGIN_PROTECT(ty, fname, ...)       \
!   ty result;                                \
!   if (UNLIKELY (__mf_state == reentrant))   \
    {                                         \
      extern unsigned long __mf_reentrancy;   \
      if (UNLIKELY (__mf_opts.verbose_trace)) { \
--- 337,348 ----
    if (UNLIKELY (size > 0 && __MF_CACHE_MISS_P (value, size))) \
      __mf_check ((void *) (value), (size), acc, "(" context ")"); \
   } while (0)
! #define BEGIN_PROTECT(fname, ...)       \
!   if (UNLIKELY (__mf_starting_p)) \
!   {                                         \
!     return CALL_BACKUP(fname, __VA_ARGS__); \
!   }                                         \
!   else if (UNLIKELY (__mf_state == reentrant))   \
    {                                         \
      extern unsigned long __mf_reentrancy;   \
      if (UNLIKELY (__mf_opts.verbose_trace)) { \
*************** ret __mfwrap_ ## fname (__VA_ARGS__)
*** 342,359 ****
      __mf_reentrancy ++; \
      return CALL_REAL(fname, __VA_ARGS__);   \
    }                                         \
-   else if (UNLIKELY (__mf_starting_p)) \
-   {                                         \
-     return CALL_BACKUP(fname, __VA_ARGS__); \
-   }                                         \
    else                                      \
    {                                         \
      TRACE ("%s\n", __PRETTY_FUNCTION__); \
    }
- 
- #define END_PROTECT(ty, fname, ...)              \
-   result = (ty) CALL_REAL(fname, __VA_ARGS__);   \
-   return result;
  
  
  /* Unlocked variants of main entry points from mf-runtime.h.  */
--- 352,361 ----
Index: mf-runtime.c
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/Attic/mf-runtime.c,v
retrieving revision 1.1.2.43
diff -c -p -w -r1.1.2.43 mf-runtime.c
*** mf-runtime.c	4 Jul 2003 23:10:09 -0000	1.1.2.43
--- mf-runtime.c	23 Jul 2003 21:10:56 -0000
*************** typedef struct __mf_object
*** 149,160 ****
--- 149,166 ----
    struct timeval alloc_time;
    char **alloc_backtrace;
    size_t alloc_backtrace_size;
+ #ifdef LIBMUDFLAPTH
+   pthread_t alloc_thread;
+ #endif
  
    int deallocated_p;
    uintptr_t dealloc_pc;
    struct timeval dealloc_time;
    char **dealloc_backtrace;
    size_t dealloc_backtrace_size;
+ #ifdef LIBMUDFLAPTH
+   pthread_t dealloc_thread;
+ #endif
  } __mf_object_t;
  
  
*************** __mf_set_default_options ()
*** 210,215 ****
--- 216,224 ----
    __mf_opts.mudflap_mode = mode_check;
    __mf_opts.violation_mode = viol_nop;
    __mf_opts.heur_std_data = 1;
+ #ifdef LIBMUDFLAPTH
+   __mf_opts.thread_stack = 0;
+ #endif
  }
  
  static struct option
*************** options [] =
*** 298,305 ****
      {"heur-start-end", 
       "support _start.._end heuristics",
       set_option, 1, &__mf_opts.heur_start_end},
!     {"heur-argv-environ", 
!      "register standard library data (argv, errno, ...)",
       set_option, 1, &__mf_opts.heur_std_data},
      {"free-queue-length", 
       "queue N deferred free() calls before performing them",
--- 307,314 ----
      {"heur-start-end", 
       "support _start.._end heuristics",
       set_option, 1, &__mf_opts.heur_start_end},
!     {"heur-stdlib", 
!      "register standard library data (argv, errno, stdin, ...)",
       set_option, 1, &__mf_opts.heur_std_data},
      {"free-queue-length", 
       "queue N deferred free() calls before performing them",
*************** options [] =
*** 310,328 ****
      {"crumple-zone", 
       "surround allocations with crumple zones of N bytes",
       read_integer_option, 0, &__mf_opts.crumple_zone},
      {"lc-mask", 
       "set lookup cache size mask to N (2**M - 1)",
       read_integer_option, 0, (int *)(&__mf_lc_mask)},
      {"lc-shift", 
       "set lookup cache pointer shift",
       read_integer_option, 0, (int *)(&__mf_lc_shift)},
      {"lc-adapt", 
       "adapt mask/shift parameters after N cache misses",
       read_integer_option, 1, &__mf_opts.adapt_cache},
      {"backtrace", 
       "keep an N-level stack trace of each call context",
       read_integer_option, 0, &__mf_opts.backtrace},
! 
      {0, 0, set_option, 0, NULL}
    };
  
--- 319,343 ----
      {"crumple-zone", 
       "surround allocations with crumple zones of N bytes",
       read_integer_option, 0, &__mf_opts.crumple_zone},
+     /* XXX: not type-safe.
      {"lc-mask", 
       "set lookup cache size mask to N (2**M - 1)",
       read_integer_option, 0, (int *)(&__mf_lc_mask)},
      {"lc-shift", 
       "set lookup cache pointer shift",
       read_integer_option, 0, (int *)(&__mf_lc_shift)},
+     */
      {"lc-adapt", 
       "adapt mask/shift parameters after N cache misses",
       read_integer_option, 1, &__mf_opts.adapt_cache},
      {"backtrace", 
       "keep an N-level stack trace of each call context",
       read_integer_option, 0, &__mf_opts.backtrace},
! #ifdef LIBMUDFLAPTH
!     {"thread-stack", 
!      "override thread stacks allocation: N kB",
!      read_integer_option, 0, &__mf_opts.thread_stack},
! #endif
      {0, 0, set_option, 0, NULL}
    };
  
*************** struct __mf_dynamic_entry __mf_dynamic [
*** 555,561 ****
    {NULL, "realloc", NULL},
    {NULL, "DUMMY", NULL}, /* dyn_INITRESOLVE */
  #ifdef LIBMUDFLAPTH
!   {NULL, "pthread_create", PTHREAD_CREATE_VERSION}
  #endif
  };
  
--- 570,578 ----
    {NULL, "realloc", NULL},
    {NULL, "DUMMY", NULL}, /* dyn_INITRESOLVE */
  #ifdef LIBMUDFLAPTH
!   {NULL, "pthread_create", PTHREAD_CREATE_VERSION},
!   {NULL, "pthread_join", NULL},
!   {NULL, "pthread_exit", NULL}
  #endif
  };
  
*************** int
*** 611,616 ****
--- 628,634 ----
  __wrap_main (int argc, char* argv[])
  {
    extern char **environ;
+   extern int main ();
    static int been_here = 0;
  
    if (__mf_opts.heur_std_data && ! been_here)
*************** void __mfu_check (void *ptr, size_t sz, 
*** 686,692 ****
      __mf_sigusr1_respond ();
  
    TRACE ("check ptr=%p b=%u size=%lu %s location=`%s'\n",
! 	 ptr, entry_idx, sz, (type == 0 ? "read" : "write"), location);
    
    switch (__mf_opts.mudflap_mode)
      {
--- 704,711 ----
      __mf_sigusr1_respond ();
  
    TRACE ("check ptr=%p b=%u size=%lu %s location=`%s'\n",
! 	 ptr, entry_idx, (unsigned long)sz,
! 	 (type == 0 ? "read" : "write"), location);
    
    switch (__mf_opts.mudflap_mode)
      {
*************** __mf_insert_new_object (uintptr_t low, u
*** 931,936 ****
--- 950,958 ----
  #if HAVE_GETTIMEOFDAY
    gettimeofday (& new_obj->data.alloc_time, NULL);
  #endif
+ #if LIBMUDFLAPTH
+   new_obj->data.alloc_thread = pthread_self ();
+ #endif
  
    if (__mf_opts.backtrace > 0 && (type == __MF_TYPE_HEAP || type == __MF_TYPE_HEAP_I))
      new_obj->data.alloc_backtrace_size = 
*************** __mf_register (void *ptr, size_t sz, int
*** 986,993 ****
  void
  __mfu_register (void *ptr, size_t sz, int type, const char *name)
  {
!   TRACE ("register ptr=%p size=%lu type=%x name='%s'\n", ptr, sz, 
! 	type, name ? name : "");
  
    if (__mf_opts.collect_stats)
      {
--- 1008,1015 ----
  void
  __mfu_register (void *ptr, size_t sz, int type, const char *name)
  {
!   TRACE ("register ptr=%p size=%lu type=%x name='%s'\n", 
! 	 ptr, (unsigned long) sz, type, name ? name : "");
  
    if (__mf_opts.collect_stats)
      {
*************** __mfu_register (void *ptr, size_t sz, in
*** 1047,1053 ****
  	      {
  		/* do nothing */
  		VERBOSE_TRACE ("duplicate static reg %p-%p `%s'\n", 
! 			       low, high, 
  			       (ovr_obj->data.name ? ovr_obj->data.name : ""));
  		break;
  	      }
--- 1069,1075 ----
  	      {
  		/* do nothing */
  		VERBOSE_TRACE ("duplicate static reg %p-%p `%s'\n", 
! 			       (void *) low, (void *) high, 
  			       (ovr_obj->data.name ? ovr_obj->data.name : ""));
  		break;
  	      }
*************** __mfu_register (void *ptr, size_t sz, in
*** 1060,1066 ****
  		ovr_obj->data.high == high)
  	      {
  		/* do nothing */
! 		VERBOSE_TRACE ("duplicate guess reg %p-%p\n", low, high);
  		break;
  	      }
  
--- 1082,1089 ----
  		ovr_obj->data.high == high)
  	      {
  		/* do nothing */
! 		VERBOSE_TRACE ("duplicate guess reg %p-%p\n", 
! 			       (void *) low, (void *) high);
  		break;
  	      }
  
*************** __mfu_register (void *ptr, size_t sz, in
*** 1087,1093 ****
  		assert (num_ovr_objs == num_overlapping_objs);
  
  		VERBOSE_TRACE ("splitting guess %p-%p, # overlaps: %u\n",
! 			       low, high, num_ovr_objs);
  
  		/* Add GUESS regions between the holes: before each
  		   overlapping region.  */
--- 1110,1116 ----
  		assert (num_ovr_objs == num_overlapping_objs);
  
  		VERBOSE_TRACE ("splitting guess %p-%p, # overlaps: %u\n",
! 			       (void *) low, (void *) high, num_ovr_objs);
  
  		/* Add GUESS regions between the holes: before each
  		   overlapping region.  */
*************** __mfu_unregister (void *ptr, size_t sz)
*** 1185,1191 ****
    if (UNLIKELY (__mf_opts.sigusr1_report))
    __mf_sigusr1_respond ();
  
!   TRACE ("unregister ptr=%p size=%lu\n", ptr, sz);
  
    switch (__mf_opts.mudflap_mode)
      { 
--- 1208,1214 ----
    if (UNLIKELY (__mf_opts.sigusr1_report))
    __mf_sigusr1_respond ();
  
!   TRACE ("unregister ptr=%p size=%lu\n", ptr, (unsigned long) sz);
  
    switch (__mf_opts.mudflap_mode)
      { 
*************** __mfu_unregister (void *ptr, size_t sz)
*** 1224,1230 ****
  	old_obj = objs[0];
  
  	if (UNLIKELY (num_overlapping_objs != 1 ||
! 		      ptr != old_obj->data.low)) /* XXX: what about sz? */
  	  {
  	    __mf_violation (ptr, sz,
  			    (uintptr_t) __builtin_return_address (0), NULL,
--- 1247,1253 ----
  	old_obj = objs[0];
  
  	if (UNLIKELY (num_overlapping_objs != 1 ||
! 		      (uintptr_t)ptr != old_obj->data.low)) /* XXX: what about sz? */
  	  {
  	    __mf_violation (ptr, sz,
  			    (uintptr_t) __builtin_return_address (0), NULL,
*************** __mfu_unregister (void *ptr, size_t sz)
*** 1256,1261 ****
--- 1279,1287 ----
  #if HAVE_GETTIMEOFDAY
  	    gettimeofday (& old_obj->data.dealloc_time, NULL);
  #endif
+ #ifdef LIBMUDFLAPTH
+ 	    old_obj->data.dealloc_thread = pthread_self ();
+ #endif
  
  	    if (__mf_opts.backtrace > 0 && old_obj->data.type == __MF_TYPE_HEAP)
  	      old_obj->data.dealloc_backtrace_size = 
*************** __mf_tree_analyze (__mf_object_tree_t *o
*** 1421,1427 ****
  	  uintptr_t addr;
  
  	  VERBOSE_TRACE ("analyze low=%p live=%u name=`%s'\n",
! 			 obj->data.low, obj->data.liveness, obj->data.name);
  
  	  s->live_obj_count ++;
  	  s->total_weight += (double) obj->data.liveness;
--- 1447,1453 ----
  	  uintptr_t addr;
  
  	  VERBOSE_TRACE ("analyze low=%p live=%u name=`%s'\n",
! 			 (void *) obj->data.low, obj->data.liveness, obj->data.name);
  
  	  s->live_obj_count ++;
  	  s->total_weight += (double) obj->data.liveness;
*************** static void
*** 1448,1454 ****
  __mf_adapt_cache ()
  {
    struct tree_stats s;
!   uintptr_t new_mask;
    unsigned char new_shift;
    float cache_utilization;
    float max_value;
--- 1474,1480 ----
  __mf_adapt_cache ()
  {
    struct tree_stats s;
!   uintptr_t new_mask = 0;
    unsigned char new_shift;
    float cache_utilization;
    float max_value;
*************** __mf_adapt_cache ()
*** 1484,1490 ****
    /* Converge toward this slowly to reduce flapping. */  
    smoothed_new_shift = 0.9*smoothed_new_shift + 0.1*i;
    new_shift = (unsigned) (smoothed_new_shift + 0.5);
!   assert (new_shift >= 0 && new_shift < sizeof (uintptr_t)*8);
  
    /* Count number of used buckets.  */
    cache_utilization = 0.0;
--- 1510,1516 ----
    /* Converge toward this slowly to reduce flapping. */  
    smoothed_new_shift = 0.9*smoothed_new_shift + 0.1*i;
    new_shift = (unsigned) (smoothed_new_shift + 0.5);
!   assert (new_shift < sizeof (uintptr_t)*8);
  
    /* Count number of used buckets.  */
    cache_utilization = 0.0;
*************** __mf_adapt_cache ()
*** 1499,1505 ****
    VERBOSE_TRACE ("adapt cache obj=%u/%u sizes=%lu/%.0f/%.0f => "
  		 "util=%u%% m=%p s=%u\n",
  		 s.obj_count, s.live_obj_count, s.total_size, s.total_weight, s.weighted_size,
! 		 (unsigned)(cache_utilization*100.0), new_mask, new_shift);
  
    /* We should reinitialize cache if its parameters have changed.  */
    if (new_mask != __mf_lc_mask ||
--- 1525,1531 ----
    VERBOSE_TRACE ("adapt cache obj=%u/%u sizes=%lu/%.0f/%.0f => "
  		 "util=%u%% m=%p s=%u\n",
  		 s.obj_count, s.live_obj_count, s.total_size, s.total_weight, s.weighted_size,
! 		 (unsigned)(cache_utilization*100.0), (void *) new_mask, new_shift);
  
    /* We should reinitialize cache if its parameters have changed.  */
    if (new_mask != __mf_lc_mask ||
*************** __mf_describe_object (__mf_object_t *obj
*** 1771,1777 ****
      {
        fprintf (stderr,
  	       "mudflap object %p: name=`%s'\n",
! 	       (uintptr_t) obj, (obj->name ? obj->name : ""));
        return;
      }
    else
--- 1797,1803 ----
      {
        fprintf (stderr,
  	       "mudflap object %p: name=`%s'\n",
! 	       (void *) obj, (obj->name ? obj->name : ""));
        return;
      }
    else
*************** __mf_describe_object (__mf_object_t *obj
*** 1780,1788 ****
    fprintf (stderr,
  	   "mudflap object %p: name=`%s'\n"
  	   "bounds=[%p,%p] size=%lu area=%s check=%ur/%uw liveness=%u%s\n"
! 	   "alloc time=%lu.%06lu pc=%p\n",
! 	   (uintptr_t) obj, (obj->name ? obj->name : ""), 
! 	   obj->low, obj->high, (obj->high - obj->low + 1),
  	   (obj->type == __MF_TYPE_NOACCESS ? "no-access" :
  	    obj->type == __MF_TYPE_HEAP ? "heap" :
  	    obj->type == __MF_TYPE_HEAP_I ? "heap-init" :
--- 1806,1819 ----
    fprintf (stderr,
  	   "mudflap object %p: name=`%s'\n"
  	   "bounds=[%p,%p] size=%lu area=%s check=%ur/%uw liveness=%u%s\n"
! 	   "alloc time=%lu.%06lu pc=%p"
! #ifdef LIBMUDFLAPTH
! 	   " thread=%u"
! #endif
! 	   "\n",
! 	   (void *) obj, (obj->name ? obj->name : ""), 
! 	   (void *) obj->low, (void *) obj->high,
! 	   (unsigned long) (obj->high - obj->low + 1),
  	   (obj->type == __MF_TYPE_NOACCESS ? "no-access" :
  	    obj->type == __MF_TYPE_HEAP ? "heap" :
  	    obj->type == __MF_TYPE_HEAP_I ? "heap-init" :
*************** __mf_describe_object (__mf_object_t *obj
*** 1792,1798 ****
  	    "unknown"),
  	   obj->read_count, obj->write_count, obj->liveness, 
  	   obj->watching_p ? " watching" : "",
! 	   obj->alloc_time.tv_sec, obj->alloc_time.tv_usec, obj->alloc_pc);
  
    if (__mf_opts.backtrace > 0)
    {
--- 1823,1834 ----
  	    "unknown"),
  	   obj->read_count, obj->write_count, obj->liveness, 
  	   obj->watching_p ? " watching" : "",
! 	   obj->alloc_time.tv_sec, obj->alloc_time.tv_usec, 
! 	   (void *) obj->alloc_pc
! #ifdef LIBMUDFLAPTH
! 	   , (unsigned) obj->alloc_thread
! #endif
! 	   );
  
    if (__mf_opts.backtrace > 0)
    {
*************** __mf_describe_object (__mf_object_t *obj
*** 1805,1812 ****
      {
        if (obj->deallocated_p)
  	{
! 	  fprintf (stderr, "dealloc time=%lu.%06lu pc=%p\n",
! 		   obj->dealloc_time.tv_sec, obj->dealloc_time.tv_usec, obj->dealloc_pc);
  
  	  if (__mf_opts.backtrace > 0)
  	  {
--- 1841,1858 ----
      {
        if (obj->deallocated_p)
  	{
! 	  fprintf (stderr, "dealloc time=%lu.%06lu pc=%p"
! #ifdef LIBMUDFLAPTH
! 		   " thread=%u"
! #endif
! 		   "\n",
! 		   obj->dealloc_time.tv_sec, obj->dealloc_time.tv_usec, 
! 		   (void *) obj->dealloc_pc
! #ifdef LIBMUDFLAPTH
! 		   , (unsigned) obj->dealloc_thread
! #endif
! 		   );
! 
  
  	  if (__mf_opts.backtrace > 0)
  	  {
*************** __mf_violation (void *ptr, size_t sz, ui
*** 2040,2047 ****
    static unsigned violation_number;
    DECLARE(void, free, void *ptr);
  
!   TRACE ("violation pc=%p location=%s type=%d ptr=%p size=%lu\n", pc, 
! 	 (location != NULL ? location : ""), type, ptr, sz);
  
    if (__mf_opts.collect_stats)
      __mf_count_violation [(type < 0) ? 0 :
--- 2086,2094 ----
    static unsigned violation_number;
    DECLARE(void, free, void *ptr);
  
!   TRACE ("violation pc=%p location=%s type=%d ptr=%p size=%lu\n", 
! 	 (void *) pc, 
! 	 (location != NULL ? location : ""), type, ptr, (unsigned long) sz);
  
    if (__mf_opts.collect_stats)
      __mf_count_violation [(type < 0) ? 0 :
*************** __mf_violation (void *ptr, size_t sz, ui
*** 2070,2076 ****
  	      (type == __MF_VIOL_UNREGISTER) ? "unregister" :
  	      (type == __MF_VIOL_WATCH) ? "watch" : "unknown"),
  	     now.tv_sec, now.tv_usec, 
! 	     ptr, sz, pc,
  	     (location != NULL ? " location=`" : ""),
  	     (location != NULL ? location : ""),
  	     (location != NULL ? "'" : ""));
--- 2117,2123 ----
  	      (type == __MF_VIOL_UNREGISTER) ? "unregister" :
  	      (type == __MF_VIOL_WATCH) ? "watch" : "unknown"),
  	     now.tv_sec, now.tv_usec, 
! 	     (void *) ptr, (unsigned long)sz, (void *) pc,
  	     (location != NULL ? " location=`" : ""),
  	     (location != NULL ? location : ""),
  	     (location != NULL ? "'" : ""));
*************** __mf_watch_or_not (void *ptr, size_t sz,
*** 2213,2219 ****
    unsigned count = 0;
  
    TRACE ("%s ptr=%p size=%lu",
! 	 (flag ? "watch" : "unwatch"), ptr, sz);
    
    switch (__mf_opts.mudflap_mode)
      {
--- 2260,2266 ----
    unsigned count = 0;
  
    TRACE ("%s ptr=%p size=%lu",
! 	 (flag ? "watch" : "unwatch"), ptr, (unsigned long) sz);
    
    switch (__mf_opts.mudflap_mode)
      {
*************** __mf_watch_or_not (void *ptr, size_t sz,
*** 2244,2250 ****
  	  {
  	    __mf_object_t *obj = & (all_ovr_objs[n]->data);
  
! 	    VERBOSE_TRACE (" [%p]", (uintptr_t) obj);
  	    if (obj->watching_p != flag)
  	      {
  		obj->watching_p = flag;
--- 2291,2297 ----
  	  {
  	    __mf_object_t *obj = & (all_ovr_objs[n]->data);
  
! 	    VERBOSE_TRACE (" [%p]", (void *) obj);
  	    if (obj->watching_p != flag)
  	      {
  		obj->watching_p = flag;
*************** __mf_sigusr1_respond ()
*** 2303,2305 ****
--- 2350,2406 ----
        handler_installed = 0; /* We may need to re-enable signal; this might be a SysV library. */
      }
  }
+ 
+ 
+ /* XXX: provide an alternative __assert_fail function that cannot
+    fail due to libmudflap infinite recursion.  */
+ #ifndef NDEBUG
+ 
+ static void
+ write_itoa (int fd, unsigned n)
+ {
+   enum x { bufsize = sizeof(n)*4 };
+   char buf [bufsize];
+   unsigned i;
+ 
+   for (i=0; i<bufsize-1; i++)
+     {
+       unsigned digit = n % 10;
+       buf[bufsize-2-i] = digit + '0';
+       n /= 10;
+       if (n == 0) 
+ 	{
+ 	  char *m = & buf [bufsize-2-i];
+ 	  buf[bufsize-1] = '\0';
+ 	  write (fd, m, strlen(m));
+ 	  break;
+ 	}
+     }
+ }
+ 
+ 
+ void
+ __assert_fail (const char *msg, const char *file, unsigned line, const char *func)
+ {
+ #define write2(string) write (2, (string), strlen ((string)));
+   write2("mf");
+ #ifdef LIBMUDFLAPTH
+   write2("(");
+   write_itoa (2, (unsigned) pthread_self ());  
+   write2(")");
+ #endif
+   write2(": assertion failure: `");
+   write (2, msg, strlen (msg));
+   write2("' in ");
+   write (2, func, strlen (func));
+   write2(" at ");
+   write (2, file, strlen (file));
+   write2(":");
+   write_itoa (2, line);
+   write2("\n");
+ #undef write2
+   abort ();
+ }
+ 
+ 
+ #endif
Index: testsuite/libmudflap.c/cfrags.exp
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/testsuite/libmudflap.c/Attic/cfrags.exp,v
retrieving revision 1.1.2.2
diff -c -p -w -r1.1.2.2 cfrags.exp
*** testsuite/libmudflap.c/cfrags.exp	16 May 2003 19:56:56 -0000	1.1.2.2
--- testsuite/libmudflap.c/cfrags.exp	23 Jul 2003 21:10:56 -0000
*************** global srcdir
*** 7,13 ****
  foreach flags [list {} {-static} {-O2} {-O3}] {
      foreach srcfile [lsort [glob -nocomplain ${srcdir}/libmudflap.c/*.c]] {
  	set bsrc [file tail $srcfile]
! 	setenv MUDFLAP_OPTIONS "-no-heur-argv-environ -viol-segv"
  	dg-runtest $srcfile $flags "-fmudflap"
      }
  }
--- 7,13 ----
  foreach flags [list {} {-static} {-O2} {-O3}] {
      foreach srcfile [lsort [glob -nocomplain ${srcdir}/libmudflap.c/*.c]] {
  	set bsrc [file tail $srcfile]
! 	setenv MUDFLAP_OPTIONS "-viol-segv"
  	dg-runtest $srcfile $flags "-fmudflap"
      }
  }
Index: testsuite/libmudflap.c++/c++frags.exp
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/testsuite/libmudflap.c++/Attic/c++frags.exp,v
retrieving revision 1.1.2.3
diff -c -p -w -r1.1.2.3 c++frags.exp
*** testsuite/libmudflap.c++/c++frags.exp	5 Mar 2003 19:08:05 -0000	1.1.2.3
--- testsuite/libmudflap.c++/c++frags.exp	23 Jul 2003 21:10:56 -0000
*************** global srcdir
*** 8,14 ****
  foreach flags [list {} {-static} {-O2} {-O3}] {
      foreach srcfile [lsort [glob -nocomplain ${srcdir}/libmudflap.c++/*.cxx]] {
  	set bsrc [file tail $srcfile]
! 	setenv MUDFLAP_OPTIONS "-no-heur-proc-map -no-heur-argv-environ -viol-segv"
  	dg-runtest $srcfile $flags "-fmudflap"
      }
  }
--- 8,14 ----
  foreach flags [list {} {-static} {-O2} {-O3}] {
      foreach srcfile [lsort [glob -nocomplain ${srcdir}/libmudflap.c++/*.cxx]] {
  	set bsrc [file tail $srcfile]
! 	setenv MUDFLAP_OPTIONS "-no-heur-proc-map -viol-segv"
  	dg-runtest $srcfile $flags "-fmudflap"
      }
  }
Index: testsuite/libmudflap.cth/cthfrags.exp
===================================================================
RCS file: /cvs/gcc/gcc/libmudflap/testsuite/libmudflap.cth/Attic/cthfrags.exp,v
retrieving revision 1.1.2.1
diff -c -p -w -r1.1.2.1 cthfrags.exp
*** testsuite/libmudflap.cth/cthfrags.exp	16 May 2003 19:56:56 -0000	1.1.2.1
--- testsuite/libmudflap.cth/cthfrags.exp	23 Jul 2003 21:10:56 -0000
*************** global srcdir
*** 7,13 ****
  foreach flags [list {} {-static} {-O2} {-O3}] {
      foreach srcfile [lsort [glob -nocomplain ${srcdir}/libmudflap.cth/*.c]] {
  	set bsrc [file tail $srcfile]
! 	setenv MUDFLAP_OPTIONS "-no-heur-argv-environ -viol-segv"
  	if {$libmudflapth} then {
  	    # --noinhibit-exec works around a ld problem that causes
  	    # "Dwarf Error: Invalid or unhandled FORM value: 14"
--- 7,13 ----
  foreach flags [list {} {-static} {-O2} {-O3}] {
      foreach srcfile [lsort [glob -nocomplain ${srcdir}/libmudflap.cth/*.c]] {
  	set bsrc [file tail $srcfile]
! 	setenv MUDFLAP_OPTIONS "-viol-segv"
  	if {$libmudflapth} then {
  	    # --noinhibit-exec works around a ld problem that causes
  	    # "Dwarf Error: Invalid or unhandled FORM value: 14"

Index: testsuite/libmudflap.cth/pass40-frag.c
===================================================================
RCS file: testsuite/libmudflap.cth/pass40-frag.c
diff -N testsuite/libmudflap.cth/pass40-frag.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/libmudflap.cth/pass40-frag.c	23 Jul 2003 21:15:57 -0000
***************
*** 0 ****
--- 1,57 ----
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <pthread.h>
+ 
+ static void *
+ func (void *p)  
+ {
+         return (NULL);
+ }               
+ 
+ static void
+ test (void)
+ {
+         int             rc;
+         pthread_attr_t  my_pthread_attr;
+         pthread_t       h;
+         long            i;
+ 
+         rc = pthread_attr_init (&my_pthread_attr);
+ 
+         for (i = 1; i <= 10000; ++i) {
+                 if (i%100 == 0) fprintf (stderr, "%i ", i);
+                 if (i%1000 == 0) fprintf (stderr, "\n");
+                 if (i==5000) __mf_set_options ("-thread-stack=192");
+ 
+                 rc = pthread_create (&h, &my_pthread_attr,
+                         func, NULL);
+                 if (rc)
+                         break;
+ 
+                 rc = pthread_join (h, NULL);
+                 if (rc)
+                         break;
+         }
+         
+         rc = pthread_attr_destroy (&my_pthread_attr);
+ }
+                 
+ int main ()
+ {
+         test ();
+                 
+         return (0);
+ }
+ 
+ /* { dg-timeout 20 } */
+ /* { dg-output "100 200 300 400 500 600 700 800 900 1000 \n" } */
+ /* { dg-output "1100 1200 1300 1400 1500 1600 1700 1800 1900 2000 \n" } */
+ /* { dg-output "2100 2200 2300 2400 2500 2600 2700 2800 2900 3000 \n" } */
+ /* { dg-output "3100 3200 3300 3400 3500 3600 3700 3800 3900 4000 \n" } */
+ /* { dg-output "4100 4200 4300 4400 4500 4600 4700 4800 4900 5000 \n" } */
+ /* { dg-output "5100 5200 5300 5400 5500 5600 5700 5800 5900 6000 \n" } */
+ /* { dg-output "6100 6200 6300 6400 6500 6600 6700 6800 6900 7000 \n" } */
+ /* { dg-output "7100 7200 7300 7400 7500 7600 7700 7800 7900 8000 \n" } */
+ /* { dg-output "8100 8200 8300 8400 8500 8600 8700 8800 8900 9000 \n" } */
+ /* { dg-output "9100 9200 9300 9400 9500 9600 9700 9800 9900 10000 \n" } */
+ 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]