This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa libmudflap] more threading fixes, warning cleanups
- From: "Frank Ch. Eigler" <fche at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 23 Jul 2003 17:20:24 -0400
- Subject: [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" } */
+