|
From: <sv...@va...> - 2008-08-24 08:31:26
|
Author: sewardj
Date: 2008-08-24 09:31:35 +0100 (Sun, 24 Aug 2008)
New Revision: 8545
Log:
When observing destructions of pthread_mutex_t, pthread_rwlock_t,
pthread_cond_t and sem_t objects, call libhb_so_dealloc on any
associated SOs (synchronisation objects) in the hope of reducing the
tendency of libhb to leak VTSs internally.
As part of this, intercept pthread_cond_destroy.
Modified:
branches/YARD/helgrind/helgrind.h
branches/YARD/helgrind/hg_intercepts.c
branches/YARD/helgrind/hg_main.c
Modified: branches/YARD/helgrind/helgrind.h
===================================================================
--- branches/YARD/helgrind/helgrind.h 2008-08-24 08:28:42 UTC (rev 8544)
+++ branches/YARD/helgrind/helgrind.h 2008-08-24 08:31:35 UTC (rev 8545)
@@ -82,6 +82,7 @@
_VG_USERREQ__HG_PTHREAD_COND_BROADCAST_PRE, /* pth_cond_t* */
_VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE, /* pth_cond_t*, pth_mx_t* */
_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST, /* pth_cond_t*, pth_mx_t* */
+ _VG_USERREQ__HG_PTHREAD_COND_DESTROY_PRE, /* pth_cond_t* */
_VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST, /* pth_rwlk_t* */
_VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE, /* pth_rwlk_t* */
_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE, /* pth_rwlk_t*, long isW */
Modified: branches/YARD/helgrind/hg_intercepts.c
===================================================================
--- branches/YARD/helgrind/hg_intercepts.c 2008-08-24 08:28:42 UTC (rev 8544)
+++ branches/YARD/helgrind/hg_intercepts.c 2008-08-24 08:31:35 UTC (rev 8545)
@@ -534,9 +534,10 @@
/* Handled: pthread_cond_wait pthread_cond_timedwait
pthread_cond_signal pthread_cond_broadcast
+ pthread_cond_destroy
- Unhandled: pthread_cond_init pthread_cond_destroy
- -- are these important?
+ Unhandled: pthread_cond_init
+ -- is this important?
*/
// pthread_cond_wait
@@ -719,6 +720,37 @@
}
+// pthread_cond_destroy
+PTH_FUNC(int, pthreadZucondZudestroyZAZa, // pthread_cond_destroy@*
+ pthread_cond_t* cond)
+{
+ int ret;
+ OrigFn fn;
+
+ VALGRIND_GET_ORIG_FN(fn);
+
+ if (TRACE_PTH_FNS) {
+ fprintf(stderr, "<< pthread_cond_destroy %p", cond);
+ fflush(stderr);
+ }
+
+ DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_DESTROY_PRE,
+ pthread_cond_t*,cond);
+
+ CALL_FN_W_W(ret, fn, cond);
+
+ if (ret != 0) {
+ DO_PthAPIerror( "pthread_cond_destroy", ret );
+ }
+
+ if (TRACE_PTH_FNS) {
+ fprintf(stderr, " codestr -> %d >>\n", ret);
+ }
+
+ return ret;
+}
+
+
/*----------------------------------------------------------------*/
/*--- pthread_rwlock_t functions ---*/
/*----------------------------------------------------------------*/
Modified: branches/YARD/helgrind/hg_main.c
===================================================================
--- branches/YARD/helgrind/hg_main.c 2008-08-24 08:28:42 UTC (rev 8544)
+++ branches/YARD/helgrind/hg_main.c 2008-08-24 08:31:35 UTC (rev 8545)
@@ -462,6 +462,7 @@
static void del_LockN ( Lock* lk )
{
tl_assert(is_sane_LockN(lk));
+ tl_assert(lk->hbso);
libhb_so_dealloc(lk->hbso);
if (lk->heldBy)
VG_(deleteBag)( lk->heldBy );
@@ -2232,6 +2233,9 @@
}
tl_assert( !lk->heldBy );
tl_assert( is_sane_LockN(lk) );
+
+ map_locks_delete( lk->guestaddr );
+ del_LockN( lk );
}
if (clo_sanity_flags & SCE_LOCKS)
@@ -2353,6 +2357,16 @@
}
}
+static void map_cond_to_SO_delete ( void* cond ) {
+ UWord keyW, valW;
+ map_cond_to_SO_INIT();
+ if (VG_(delFromFM)( map_cond_to_SO, &keyW, &valW, (UWord)cond )) {
+ SO* so = (SO*)valW;
+ tl_assert(keyW == (UWord)cond);
+ libhb_so_dealloc(so);
+ }
+}
+
static void evh__HG_PTHREAD_COND_SIGNAL_PRE ( ThreadId tid, void* cond )
{
/* 'tid' has signalled on 'cond'. As per the comment above, bind
@@ -2469,7 +2483,21 @@
libhb_so_recv( thr->hbthr, so, True/*strong_recv*/ );
}
+static void evh__HG_PTHREAD_COND_DESTROY_PRE ( ThreadId tid,
+ void* cond )
+{
+ /* Deal with destroy events. The only purpose is to free storage
+ associated with the CV, so as to avoid any possible resource
+ leaks. */
+ if (SHOW_EVENTS >= 1)
+ VG_(printf)("evh__HG_PTHREAD_COND_DESTROY_PRE"
+ "(ctid=%d, cond=%p)\n",
+ (Int)tid, (void*)cond );
+ map_cond_to_SO_delete( cond );
+}
+
+
/* -------------- events to do with rwlocks -------------- */
/* EXPOSITION only */
@@ -2519,6 +2547,9 @@
}
tl_assert( !lk->heldBy );
tl_assert( is_sane_LockN(lk) );
+
+ map_locks_delete( lk->guestaddr );
+ del_LockN( lk );
}
if (clo_sanity_flags & SCE_LOCKS)
@@ -2647,11 +2678,13 @@
}
static void push_SO_for_sem ( void* sem, SO* so ) {
+ UWord keyW;
XArray* xa;
tl_assert(so);
map_sem_to_SO_stack_INIT();
if (VG_(lookupFM)( map_sem_to_SO_stack,
- NULL, (UWord*)&xa, (UWord)sem )) {
+ &keyW, (UWord*)&xa, (UWord)sem )) {
+ tl_assert(keyW == (UWord)sem);
tl_assert(xa);
VG_(addToXA)( xa, &so );
} else {
@@ -2662,13 +2695,16 @@
}
static SO* mb_pop_SO_for_sem ( void* sem ) {
+ UWord keyW;
XArray* xa;
SO* so;
map_sem_to_SO_stack_INIT();
if (VG_(lookupFM)( map_sem_to_SO_stack,
- NULL, (UWord*)&xa, (UWord)sem )) {
+ &keyW, (UWord*)&xa, (UWord)sem )) {
/* xa is the stack for this semaphore. */
- Word sz = VG_(sizeXA)( xa );
+ Word sz;
+ tl_assert(keyW == (UWord)sem);
+ sz = VG_(sizeXA)( xa );
tl_assert(sz >= 0);
if (sz == 0)
return NULL; /* odd, the stack is empty */
@@ -2684,12 +2720,15 @@
static void evh__HG_POSIX_SEM_DESTROY_PRE ( ThreadId tid, void* sem )
{
- SO* so;
+ UWord keyW, valW;
+ SO* so;
if (SHOW_EVENTS >= 1)
VG_(printf)("evh__HG_POSIX_SEM_DESTROY_PRE(ctid=%d, sem=%p)\n",
(Int)tid, (void*)sem );
+ map_sem_to_SO_stack_INIT();
+
/* Empty out the semaphore's SO stack. This way of doing it is
stupid, but at least it's easy. */
while (1) {
@@ -2697,6 +2736,14 @@
if (!so) break;
libhb_so_dealloc(so);
}
+
+ if (VG_(delFromFM)( map_sem_to_SO_stack, &keyW, &valW, (UWord)sem )) {
+ XArray* xa = (XArray*)valW;
+ tl_assert(keyW == (UWord)sem);
+ tl_assert(xa);
+ tl_assert(VG_(sizeXA)(xa) == 0); /* preceding loop just emptied it */
+ VG_(deleteXA)(xa);
+ }
}
static
@@ -3909,6 +3956,11 @@
break;
}
+ /* cond=arg[1] */
+ case _VG_USERREQ__HG_PTHREAD_COND_DESTROY_PRE:
+ evh__HG_PTHREAD_COND_DESTROY_PRE( tid, (void*)args[1] );
+ break;
+
/* Thread successfully completed pthread_cond_wait, cond=arg[1],
mutex=arg[2] */
case _VG_USERREQ__HG_PTHREAD_COND_WAIT_POST:
|