Author: bart
Date: 2008-02-29 17:27:03 +0000 (Fri, 29 Feb 2008)
New Revision: 7508
Log:
Eliminated upper bounds on the number of condition variables, semaphores and
barriers. Added command-line option --trace-semaphore.
Modified:
trunk/exp-drd/TODO.txt
trunk/exp-drd/drd_barrier.c
trunk/exp-drd/drd_barrier.h
trunk/exp-drd/drd_clientobj.c
trunk/exp-drd/drd_clientobj.h
trunk/exp-drd/drd_clientreq.c
trunk/exp-drd/drd_clientreq.h
trunk/exp-drd/drd_cond.c
trunk/exp-drd/drd_cond.h
trunk/exp-drd/drd_intercepts.c
trunk/exp-drd/drd_main.c
trunk/exp-drd/drd_mutex.c
trunk/exp-drd/drd_semaphore.c
trunk/exp-drd/drd_semaphore.h
trunk/exp-drd/drd_track.h
Modified: trunk/exp-drd/TODO.txt
===================================================================
--- trunk/exp-drd/TODO.txt 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/TODO.txt 2008-02-29 17:27:03 UTC (rev 7508)
@@ -8,8 +8,6 @@
- Print an error message when memory is freed that contains a locked
reader-writer synchronization object.
- Print an error message when a semaphore is freed that is being waited upon.
-- Eliminate the upper bounds on the number of condition variables,
- semaphores, barriers and threads by converting arrays into OSet's.
- Implement segment merging, such that the number of segments per thread
remains limited even when there is no synchronization between threads.
- Add locking order checking.
@@ -33,6 +31,9 @@
a crash on AMD64. Is this an exp-drd or a VEX bug ?
- On x86 and amd64 platforms, add support for implicit locking arising from
the use of the LOCK instruction prefix.
+- Add test programs for freeing memory that contains a condition variable /
+ destroying a condition variable being waited upon.
+- Convert the array in drd_thread.c with thread information into an OSet.
Testing
Modified: trunk/exp-drd/drd_barrier.c
===================================================================
--- trunk/exp-drd/drd_barrier.c 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_barrier.c 2008-02-29 17:27:03 UTC (rev 7508)
@@ -24,6 +24,7 @@
#include "drd_barrier.h"
+#include "drd_clientobj.h"
#include "drd_error.h"
#include "drd_suppression.h"
#include "priv_drd_clientreq.h"
@@ -38,19 +39,6 @@
// Type definitions.
-/* Information associated with a client-side pthread_barrier_t object. */
-struct barrier_info
-{
- Addr barrier; // Client address of barrier.
- SizeT size; // Size in bytes of client-side object.
- Word count; // Participant count in a barrier wait.
- Word pre_iteration; // pthread_barrier_wait() call count modulo two.
- Word post_iteration; // pthread_barrier_wait() call count modulo two.
- Word pre_waiters_left; // number of waiters left for a complete barrier.
- Word post_waiters_left; // number of waiters left for a complete barrier.
- OSet* oset; // Thread-specific barrier information.
-};
-
/* Information associated with one thread participating in a barrier. */
struct barrier_thread_info
{
@@ -62,11 +50,14 @@
};
+// Local functions.
+
+void barrier_cleanup(struct barrier_info* p);
+
+
// Local variables.
static Bool s_trace_barrier = False;
-/* To do: eliminate the upper limit on the number of barriers (4). */
-struct barrier_info s_barrier[4];
// Function definitions.
@@ -106,9 +97,10 @@
tl_assert(barrier != 0);
tl_assert(size > 0);
tl_assert(count > 0);
+ tl_assert(p->a1 == barrier);
+ tl_assert(p->a2 - p->a1 == size);
- p->barrier = barrier;
- p->size = size;
+ p->cleanup = (void(*)(DrdClientobj*))barrier_cleanup;
p->count = count;
p->pre_iteration = 0;
p->post_iteration = 0;
@@ -120,14 +112,20 @@
p->oset = VG_(OSetGen_Create)(0, 0, VG_(malloc), VG_(free));
}
-/** Deallocate the memory allocated by barrier_initialize() and in p->oset. */
-void barrier_destroy(struct barrier_info* const p)
+/** Deallocate the memory allocated by barrier_initialize() and in p->oset.
+ * Called by drd_clientobj_destroy().
+ */
+void barrier_cleanup(struct barrier_info* p)
{
struct barrier_thread_info* q;
tl_assert(p);
- drd_finish_suppression(p->barrier, p->barrier + p->size);
+ if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count)
+ {
+ VG_(message)(Vg_UserMsg, "Destruction of barrier 0x%lx being waited upon",
+ p->a1);
+ }
VG_(OSetGen_ResetIter)(p->oset);
for ( ; (q = VG_(OSetGen_Next)(p->oset)) != 0; )
@@ -135,13 +133,6 @@
barrier_thread_destroy(q);
}
VG_(OSetGen_Destroy)(p->oset);
- p->barrier = 0;
- p->size = 0;
- p->count = 0;
- p->pre_iteration = 0;
- p->post_iteration = 0;
- p->pre_waiters_left = 0;
- p->post_waiters_left = 0;
}
/** Look up the client-side barrier address barrier in s_barrier[]. If not
@@ -150,31 +141,30 @@
struct barrier_info*
barrier_get_or_allocate(const Addr barrier, const SizeT size, const Word count)
{
- int i;
+ struct barrier_info *p;
- for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++)
+ tl_assert(offsetof(DrdClientobj, barrier) == 0);
+ p = &drd_clientobj_get(barrier, ClientBarrier)->barrier;
+ if (p == 0)
{
- if (s_barrier[i].barrier == barrier)
- {
- tl_assert(s_barrier[i].size == size);
- return &s_barrier[i];
- }
+ p = &drd_clientobj_add(barrier, barrier + size, ClientBarrier)->barrier;
+ barrier_initialize(p, barrier, size, count);
}
- for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++)
- {
- if (s_barrier[i].barrier == 0)
- {
- barrier_initialize(&s_barrier[i], barrier, size, count);
- drd_start_suppression(barrier, barrier + size, "barrier");
- return &s_barrier[i];
- }
- }
- tl_assert(0);
- return 0;
+ return p;
}
+/** Look up the address of the information associated with the client-side
+ * barrier object. */
+struct barrier_info* barrier_get(const Addr barrier)
+{
+ tl_assert(offsetof(DrdClientobj, barrier) == 0);
+ return &drd_clientobj_get(barrier, ClientBarrier)->barrier;
+}
+
/** Initialize a barrier with client address barrier, client size size, and
- * where count threads participate in each barrier. */
+ * where count threads participate in each barrier.
+ * Called before pthread_barrier_init().
+ */
struct barrier_info*
barrier_init(const Addr barrier, const SizeT size, const Word count)
{
@@ -182,17 +172,14 @@
return barrier_get_or_allocate(barrier, size, count);
}
-/** Look up the address of the information associated with the client-side
- * barrier object. */
-struct barrier_info* barrier_get(const Addr barrier)
+/** Called after pthread_barrier_destroy(). */
+void barrier_destroy(struct barrier_info* const p)
{
- int i;
- for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++)
- if (s_barrier[i].barrier == barrier)
- return &s_barrier[i];
- return 0;
+ tl_assert(p);
+ drd_clientobj_remove(p->a1, ClientBarrier);
}
+/** Called before pthread_barrier_wait(). */
void barrier_pre_wait(const DrdThreadId tid, const Addr barrier)
{
struct barrier_info* p;
@@ -227,6 +214,7 @@
}
}
+/** Called after pthread_barrier_wait(). */
void barrier_post_wait(const DrdThreadId tid, const Addr barrier,
const Bool waited)
{
@@ -286,31 +274,15 @@
/** Call this function when thread tid stops to exist. */
void barrier_thread_delete(const DrdThreadId tid)
{
- int i;
+ struct barrier_info* p;
- for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++)
+ drd_clientobj_resetiter();
+ for ( ; (p = &drd_clientobj_next(ClientBarrier)->barrier) != 0; )
{
- struct barrier_info* const p = &s_barrier[i];
- if (p->barrier)
- {
- struct barrier_thread_info* q;
- const UWord word_tid = tid;
- q = VG_(OSetGen_Remove)(p->oset, &word_tid);
- barrier_thread_destroy(q);
- VG_(OSetGen_FreeNode)(p->oset, q);
- }
+ struct barrier_thread_info* q;
+ const UWord word_tid = tid;
+ q = VG_(OSetGen_Remove)(p->oset, &word_tid);
+ barrier_thread_destroy(q);
+ VG_(OSetGen_FreeNode)(p->oset, q);
}
}
-
-void barrier_stop_using_mem(const Addr a1, const Addr a2)
-{
- unsigned i;
- for (i = 0; i < sizeof(s_barrier)/sizeof(s_barrier[0]); i++)
- {
- if (a1 <= s_barrier[i].barrier && s_barrier[i].barrier < a2)
- {
- tl_assert(s_barrier[i].barrier + s_barrier[i].size <= a2);
- barrier_destroy(&s_barrier[i]);
- }
- }
-}
Modified: trunk/exp-drd/drd_barrier.h
===================================================================
--- trunk/exp-drd/drd_barrier.h 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_barrier.h 2008-02-29 17:27:03 UTC (rev 7508)
@@ -26,8 +26,8 @@
// Barrier state information.
-#ifndef __BARRIER_H
-#define __BARRIER_H
+#ifndef __DRD_BARRIER_H
+#define __DRD_BARRIER_H
#include "drd_thread.h" // DrdThreadId
@@ -50,4 +50,4 @@
void barrier_stop_using_mem(const Addr a1, const Addr a2);
-#endif /* __BARRIER_H */
+#endif /* __DRD_BARRIER_H */
Modified: trunk/exp-drd/drd_clientobj.c
===================================================================
--- trunk/exp-drd/drd_clientobj.c 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_clientobj.c 2008-02-29 17:27:03 UTC (rev 7508)
@@ -120,10 +120,12 @@
return p;
}
-Bool drd_clientobj_remove(const Addr addr)
+Bool drd_clientobj_remove(const Addr addr, const ObjType t)
{
DrdClientobj* p;
+ p = VG_(OSetGen_Lookup)(s_clientobj, &addr);
+ tl_assert(p->any.type == t);
p = VG_(OSetGen_Remove)(s_clientobj, &addr);
if (p)
{
@@ -163,7 +165,7 @@
a1, a2);
#endif
removed_at = p->any.a1;
- drd_clientobj_remove(p->any.a1);
+ drd_clientobj_remove(p->any.a1, p->any.type);
/* The above call removes an element from the oset and hence invalidates
*/
/* the iterator. Set the iterator back.
*/
VG_(OSetGen_ResetIter)(s_clientobj);
Modified: trunk/exp-drd/drd_clientobj.h
===================================================================
--- trunk/exp-drd/drd_clientobj.h 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_clientobj.h 2008-02-29 17:27:03 UTC (rev 7508)
@@ -30,6 +30,7 @@
#include "drd_clientreq.h" /* MutexT */
#include "drd_thread.h" /* DrdThreadId */
#include "pub_tool_basics.h"
+#include "pub_tool_oset.h"
// Forward declarations.
@@ -39,7 +40,12 @@
// Type definitions.
-typedef enum { ClientMutex = 1, } ObjType;
+typedef enum {
+ ClientMutex = 1,
+ ClientCondvar = 2,
+ ClientSemaphore = 3,
+ ClientBarrier = 4,
+} ObjType;
struct any
{
@@ -61,10 +67,50 @@
VectorClock vc; // vector clock associated with last unlock.
};
+struct cond_info
+{
+ Addr a1;
+ Addr a2;
+ ObjType type;
+ void (*cleanup)(union drd_clientobj*);
+ int waiter_count;
+ Addr mutex; // Client mutex specified in pthread_cond_wait() call, and
null
+ // if no client threads are currently waiting on this
cond.var.
+};
+
+struct semaphore_info
+{
+ Addr a1;
+ Addr a2;
+ ObjType type;
+ void (*cleanup)(union drd_clientobj*);
+ UWord value; // Semaphore value.
+ UWord waiters; // Number of threads inside sem_wait().
+ DrdThreadId last_sem_post_tid; // Thread ID associated with last sem_post().
+ VectorClock vc; // Vector clock of last sem_post() call.
+};
+
+struct barrier_info
+{
+ Addr a1;
+ Addr a2;
+ ObjType type;
+ void (*cleanup)(union drd_clientobj*);
+ Word count; // Participant count in a barrier wait.
+ Word pre_iteration; // pthread_barrier_wait() call count modulo
two.
+ Word post_iteration; // pthread_barrier_wait() call count modulo
two.
+ Word pre_waiters_left; // number of waiters left for a complete
barrier.
+ Word post_waiters_left; // number of waiters left for a complete
barrier.
+ OSet* oset; // Thread-specific barrier information.
+};
+
typedef union drd_clientobj
{
- struct any any;
- struct mutex_info mutex;
+ struct any any;
+ struct mutex_info mutex;
+ struct cond_info cond;
+ struct semaphore_info semaphore;
+ struct barrier_info barrier;
} DrdClientobj;
@@ -75,7 +121,7 @@
DrdClientobj* drd_clientobj_get(const Addr addr, const ObjType t);
Bool drd_clientobj_present(const Addr a1, const Addr a2);
DrdClientobj* drd_clientobj_add(const Addr a1, const Addr a2, const ObjType t);
-Bool drd_clientobj_remove(const Addr addr);
+Bool drd_clientobj_remove(const Addr addr, const ObjType t);
void drd_clientobj_stop_using_mem(const Addr a1, const Addr a2);
void drd_clientobj_resetiter(void);
DrdClientobj* drd_clientobj_next(const ObjType t);
Modified: trunk/exp-drd/drd_clientreq.c
===================================================================
--- trunk/exp-drd/drd_clientreq.c 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_clientreq.c 2008-02-29 17:27:03 UTC (rev 7508)
@@ -189,6 +189,10 @@
drd_semaphore_destroy(arg[1]);
break;
+ case VG_USERREQ__PRE_SEM_WAIT:
+ drd_semaphore_pre_wait(thread_get_running_tid(), arg[1], arg[2]);
+ break;
+
case VG_USERREQ__POST_SEM_WAIT:
drd_semaphore_post_wait(thread_get_running_tid(), arg[1], arg[2]);
break;
Modified: trunk/exp-drd/drd_clientreq.h
===================================================================
--- trunk/exp-drd/drd_clientreq.h 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_clientreq.h 2008-02-29 17:27:03 UTC (rev 7508)
@@ -93,8 +93,11 @@
VG_USERREQ__SEM_DESTROY,
/* args: Addr sem */
/* To notify the drd tool of a sem_wait call. */
+ VG_USERREQ__PRE_SEM_WAIT,
+ /* args: Addr sem, SizeT sem_size */
+ /* To notify the drd tool of a sem_wait call. */
VG_USERREQ__POST_SEM_WAIT,
- /* args: Addr sem, SizeT sem_size */
+ /* args: Addr sem, Bool waited */
/* To notify the drd tool before a sem_post call. */
VG_USERREQ__PRE_SEM_POST,
/* args: Addr sem, SizeT sem_size */
Modified: trunk/exp-drd/drd_cond.c
===================================================================
--- trunk/exp-drd/drd_cond.c 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_cond.c 2008-02-29 17:27:03 UTC (rev 7508)
@@ -23,6 +23,7 @@
*/
+#include "drd_clientobj.h"
#include "drd_cond.h"
#include "drd_error.h"
#include "drd_mutex.h"
@@ -35,10 +36,18 @@
#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
-static struct cond_info s_cond[256];
+// Local functions.
+
+static void cond_cleanup(struct cond_info* p);
+
+
+// Local variables.
+
static Bool s_trace_cond;
+// Function definitions.
+
void cond_set_trace(const Bool trace_cond)
{
s_trace_cond = trace_cond;
@@ -49,81 +58,82 @@
const SizeT size)
{
tl_assert(cond != 0);
+ tl_assert(p->a1 == cond);
+ tl_assert(p->a2 - p->a1 == size);
+ tl_assert(p->type == ClientCondvar);
- p->cond = cond;
- p->size = size;
+ p->cleanup = (void(*)(DrdClientobj*))cond_cleanup;
p->waiter_count = 0;
p->mutex = 0;
}
+/** Free the memory that was allocated by cond_initialize(). Called by
+ * drd_clientobj_remove().
+ */
+static void cond_cleanup(struct cond_info* p)
+{
+ tl_assert(p);
+ if (p->mutex)
+ {
+ struct mutex_info* q;
+ q = &drd_clientobj_get(p->mutex, ClientMutex)->mutex;
+ VG_(message)(Vg_UserMsg,
+ "Error: destroying condition variable 0x%lx while thread %d"
+ " is waiting on it.\n",
+ p->a1, q ? q->owner : -1);
+ }
+}
+
static struct cond_info*
cond_get_or_allocate(const Addr cond, const SizeT size)
{
- int i;
- for (i = 0; i < sizeof(s_cond)/sizeof(s_cond[0]); i++)
+ struct cond_info *p;
+
+ tl_assert(offsetof(DrdClientobj, cond) == 0);
+ p = &drd_clientobj_get(cond, ClientCondvar)->cond;
+ if (p == 0)
{
- if (s_cond[i].cond == cond)
- {
- tl_assert(s_cond[i].size == size);
- return &s_cond[i];
- }
+ p = &drd_clientobj_add(cond, cond + size, ClientCondvar)->cond;
+ cond_initialize(p, cond, size);
}
- for (i = 0; i < sizeof(s_cond)/sizeof(s_cond[0]); i++)
- {
- if (s_cond[i].cond == 0)
- {
- cond_initialize(&s_cond[i], cond, size);
- /* TO DO: replace the constant below by a symbolic constant referring */
- /* to sizeof(pthread_cond_t). */
- drd_start_suppression(cond, cond + size, "cond");
- return &s_cond[i];
- }
- }
- tl_assert(0);
- return 0;
+ return p;
}
+struct cond_info* cond_get(const Addr cond)
+{
+ tl_assert(offsetof(DrdClientobj, cond) == 0);
+ return &drd_clientobj_get(cond, ClientCondvar)->cond;
+}
+
+/** Called before pthread_cond_init(). */
void cond_init(const Addr cond, const SizeT size)
{
if (s_trace_cond)
{
VG_(message)(Vg_UserMsg, "Initializing condition variable 0x%lx", cond);
- VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
- VG_(clo_backtrace_size));
+ VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
VG_(clo_backtrace_size));
}
tl_assert(cond_get(cond) == 0);
tl_assert(size > 0);
cond_get_or_allocate(cond, size);
}
+/** Called after pthread_cond_destroy(). */
void cond_destroy(struct cond_info* const p)
{
if (s_trace_cond)
{
- VG_(message)(Vg_UserMsg, "Destroying condition variable 0x%lx", p->cond);
- VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
- VG_(clo_backtrace_size));
+ VG_(message)(Vg_UserMsg, "Destroying condition variable 0x%lx", p->a1);
+ VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
VG_(clo_backtrace_size));
}
// TO DO: print a proper error message if waiter_count != 0.
tl_assert(p->waiter_count == 0);
- drd_finish_suppression(p->cond, p->cond + p->size);
-
- p->cond = 0;
- p->waiter_count = 0;
- p->mutex = 0;
+ drd_clientobj_remove(p->a1, ClientCondvar);
}
-struct cond_info* cond_get(const Addr cond)
-{
- int i;
- for (i = 0; i < sizeof(s_cond)/sizeof(s_cond[0]); i++)
- if (s_cond[i].cond == cond)
- return &s_cond[i];
- return 0;
-}
-
+/** Called before pthread_cond_wait(). */
int cond_pre_wait(const Addr cond, const SizeT cond_size, const Addr mutex)
{
struct cond_info* p;
@@ -143,6 +153,7 @@
return ++p->waiter_count;
}
+/** Called after pthread_cond_wait(). */
int cond_post_wait(const Addr cond)
{
struct cond_info* p;
@@ -158,17 +169,12 @@
return p->waiter_count;
}
+/** Called before pthread_cond_signal(). */
void cond_pre_signal(Addr const cond)
{
const ThreadId vg_tid = VG_(get_running_tid)();
const DrdThreadId drd_tid = VgThreadIdToDrdThreadId(vg_tid);
struct cond_info* const cond_p = cond_get(cond);
-#if 0
- VG_(message)(Vg_DebugMsg, "cond_pre_signal cond %d, w.c. %d, mutex %d",
- cond,
- cond_p ? cond_p->waiter_count : 0,
- cond_p ? cond_p->mutex : 0);
-#endif
if (cond_p && cond_p->waiter_count > 0)
{
if (! mutex_is_locked_by(cond_p->mutex, drd_tid))
@@ -190,23 +196,12 @@
}
}
+/** Called before pthread_cond_broadcast(). */
void cond_pre_broadcast(Addr const cond)
{
cond_pre_signal(cond);
}
+/** Called after pthread_cond_destroy(). */
void cond_thread_delete(const DrdThreadId tid)
{ }
-
-void cond_stop_using_mem(const Addr a1, const Addr a2)
-{
- unsigned i;
- for (i = 0; i < sizeof(s_cond)/sizeof(s_cond[0]); i++)
- {
- if (a1 <= s_cond[i].cond && s_cond[i].cond < a2)
- {
- tl_assert(s_cond[i].cond + s_cond[i].size <= a2);
- cond_destroy(&s_cond[i]);
- }
- }
-}
Modified: trunk/exp-drd/drd_cond.h
===================================================================
--- trunk/exp-drd/drd_cond.h 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_cond.h 2008-02-29 17:27:03 UTC (rev 7508)
@@ -27,24 +27,17 @@
// call.
-#ifndef __COND_H
-#define __COND_H
+#ifndef __DRD_COND_H
+#define __DRD_COND_H
-#include "pub_tool_basics.h" // Addr, SizeT
-#include "drd_vc.h"
-#include "drd_thread.h" // DrdThreadId
+#include "drd_thread.h" // DrdThreadid
+#include "pub_tool_basics.h" // Addr, SizeT
-struct cond_info
-{
- Addr cond; // Pointer to client condition variable.
- SizeT size; // sizeof(pthread_cond_t)
- int waiter_count;
- Addr mutex; // Client mutex specified in pthread_cond_wait() call, and null
- // if no client threads are currently waiting on this cond.var.
-};
+struct cond_info;
+
void cond_set_trace(const Bool trace_cond);
void cond_init(const Addr cond, const SizeT size);
void cond_destroy(struct cond_info* const p);
@@ -54,7 +47,6 @@
void cond_pre_signal(const Addr cond);
void cond_pre_broadcast(const Addr cond);
void cond_thread_delete(const DrdThreadId tid);
-void cond_stop_using_mem(const Addr a1, const Addr a2);
-#endif /* __COND_H */
+#endif /* __DRD_COND_H */
Modified: trunk/exp-drd/drd_intercepts.c
===================================================================
--- trunk/exp-drd/drd_intercepts.c 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_intercepts.c 2008-02-29 17:27:03 UTC (rev 7508)
@@ -706,15 +706,15 @@
int res;
OrigFn fn;
VALGRIND_GET_ORIG_FN(fn);
+ VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
+ sem, 0, 0, 0, 0);
CALL_FN_W_W(ret, fn, sem);
- if (ret == 0)
- {
- VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
- sem, sizeof(*sem), 0, 0, 0);
- }
+ VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
+ sem, ret == 0, 0, 0, 0);
return ret;
}
+// sem_wait
PTH_FUNC(int, sem_waitZa, // sem_wait*
sem_t *sem)
{
@@ -722,12 +722,11 @@
int res;
OrigFn fn;
VALGRIND_GET_ORIG_FN(fn);
+ VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
+ sem, 0, 0, 0, 0);
CALL_FN_W_W(ret, fn, sem);
- if (ret == 0)
- {
- VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
- sem, sizeof(*sem), 0, 0, 0);
- }
+ VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
+ sem, ret == 0, 0, 0, 0);
return ret;
}
@@ -739,12 +738,11 @@
int res;
OrigFn fn;
VALGRIND_GET_ORIG_FN(fn);
+ VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
+ sem, 0, 0, 0, 0);
CALL_FN_W_W(ret, fn, sem);
- if (ret == 0)
- {
- VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
- sem, sizeof(*sem), 0, 0, 0);
- }
+ VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
+ sem, ret == 0, 0, 0, 0);
return ret;
}
@@ -755,12 +753,11 @@
int res;
OrigFn fn;
VALGRIND_GET_ORIG_FN(fn);
+ VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
+ sem, 0, 0, 0, 0);
CALL_FN_W_W(ret, fn, sem);
- if (ret == 0)
- {
- VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
- sem, sizeof(*sem), 0, 0, 0);
- }
+ VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
+ sem, ret == 0, 0, 0, 0);
return ret;
}
@@ -772,12 +769,11 @@
int res;
OrigFn fn;
VALGRIND_GET_ORIG_FN(fn);
+ VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
+ sem, 0, 0, 0, 0);
CALL_FN_W_WW(ret, fn, sem, abs_timeout);
- if (ret == 0)
- {
- VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
- sem, sizeof(*sem), 0, 0, 0);
- }
+ VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
+ sem, ret == 0, 0, 0, 0);
return ret;
}
Modified: trunk/exp-drd/drd_main.c
===================================================================
--- trunk/exp-drd/drd_main.c 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_main.c 2008-02-29 17:27:03 UTC (rev 7508)
@@ -82,6 +82,7 @@
Bool trace_danger_set = False;
Bool trace_mutex = False;
Bool trace_segment = False;
+ Bool trace_semaphore = False;
Bool trace_suppression = False;
Char* trace_address = 0;
@@ -94,6 +95,7 @@
else VG_BOOL_CLO(arg, "--trace-mem", drd_trace_mem)
else VG_BOOL_CLO(arg, "--trace-mutex", trace_mutex)
else VG_BOOL_CLO(arg, "--trace-segment", trace_segment)
+ else VG_BOOL_CLO(arg, "--trace-semaphore", trace_semaphore)
else VG_BOOL_CLO(arg, "--trace-suppression", trace_suppression)
else VG_STR_CLO (arg, "--trace-address", trace_address)
else
@@ -115,6 +117,8 @@
mutex_set_trace(trace_mutex);
if (trace_segment)
sg_set_trace(trace_segment);
+ if (trace_semaphore)
+ semaphore_set_trace(trace_semaphore);
if (trace_suppression)
suppression_set_trace(trace_suppression);
@@ -277,9 +281,6 @@
}
thread_stop_using_mem(a1, a2);
drd_clientobj_stop_using_mem(a1, a2);
- cond_stop_using_mem(a1, a2);
- semaphore_stop_using_mem(a1, a2);
- barrier_stop_using_mem(a1, a2);
drd_suppression_stop_using_mem(a1, a2);
}
@@ -491,10 +492,16 @@
}
}
+void drd_semaphore_pre_wait(const DrdThreadId tid, const Addr semaphore,
+ const SizeT size)
+{
+ semaphore_pre_wait(semaphore, size);
+}
+
void drd_semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
- const SizeT size)
+ const Bool waited)
{
- semaphore_post_wait(tid, semaphore, size);
+ semaphore_post_wait(tid, semaphore, waited);
}
void drd_semaphore_pre_post(const DrdThreadId tid, const Addr semaphore,
Modified: trunk/exp-drd/drd_mutex.c
===================================================================
--- trunk/exp-drd/drd_mutex.c 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_mutex.c 2008-02-29 17:27:03 UTC (rev 7508)
@@ -169,7 +169,7 @@
static void mutex_destroy(struct mutex_info* const p)
{
- drd_clientobj_remove(p->a1);
+ drd_clientobj_remove(p->a1, ClientMutex);
}
/** Called after pthread_mutex_destroy(). */
Modified: trunk/exp-drd/drd_semaphore.c
===================================================================
--- trunk/exp-drd/drd_semaphore.c 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_semaphore.c 2008-02-29 17:27:03 UTC (rev 7508)
@@ -23,6 +23,7 @@
*/
+#include "drd_clientobj.h"
#include "drd_error.h"
#include "drd_semaphore.h"
#include "drd_suppression.h"
@@ -34,22 +35,14 @@
#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
-// Type definitions.
+// Local functions.
-struct semaphore_info
-{
- Addr semaphore; // Pointer to client semaphore.
- SizeT size; // Size in bytes of client-side object.
- UWord value; // Semaphore value.
- DrdThreadId last_sem_post_tid; // Thread ID associated with last sem_post().
- VectorClock vc; // Vector clock of last sem_post() call.
-};
+static void semaphore_cleanup(struct semaphore_info* p);
// Local variables.
static Bool s_trace_semaphore;
-struct semaphore_info s_semaphore[256];
// Function definitions.
@@ -67,41 +60,55 @@
{
tl_assert(semaphore != 0);
tl_assert(size > 0);
+ tl_assert(p->a1 == semaphore);
+ tl_assert(p->a2 - p->a1 == size);
+ tl_assert(p->type == ClientSemaphore);
- p->semaphore = semaphore;
- p->size = size;
+ p->cleanup = (void(*)(DrdClientobj*))semaphore_cleanup;
p->value = value;
+ p->waiters = 0;
p->last_sem_post_tid = DRD_INVALID_THREADID;
vc_init(&p->vc, 0, 0);
}
+/** Free the memory that was allocated by semaphore_initialize(). Called by
+ * drd_clientobj_remove().
+ */
+static void semaphore_cleanup(struct semaphore_info* p)
+{
+ if (p->waiters > 0)
+ {
+ VG_(message)(Vg_UserMsg, "Error: destroying semaphore while %d threads are"
+ "still waiting on the semaphore.\n", p->waiters);
+ }
+ vc_cleanup(&p->vc);
+}
+
static
struct semaphore_info*
semaphore_get_or_allocate(const Addr semaphore, const SizeT size)
{
- int i;
+ struct semaphore_info *p;
- for (i = 0; i < sizeof(s_semaphore)/sizeof(s_semaphore[0]); i++)
+ tl_assert(offsetof(DrdClientobj, semaphore) == 0);
+ p = &drd_clientobj_get(semaphore, ClientSemaphore)->semaphore;
+ if (p == 0)
{
- if (s_semaphore[i].semaphore == semaphore)
- {
- tl_assert(s_semaphore[i].size == size);
- return &s_semaphore[i];
- }
+ tl_assert(offsetof(DrdClientobj, semaphore) == 0);
+ p = &drd_clientobj_add(semaphore, semaphore + size,
+ ClientSemaphore)->semaphore;
+ semaphore_initialize(p, semaphore, size, 0);
}
- for (i = 0; i < sizeof(s_semaphore)/sizeof(s_semaphore[0]); i++)
- {
- if (s_semaphore[i].semaphore == 0)
- {
- semaphore_initialize(&s_semaphore[i], semaphore, size, 0);
- drd_start_suppression(semaphore, semaphore + size, "semaphore");
- return &s_semaphore[i];
- }
- }
- tl_assert(0);
- return 0;
+ return p;
}
+struct semaphore_info* semaphore_get(const Addr semaphore)
+{
+ tl_assert(offsetof(DrdClientobj, semaphore) == 0);
+ return &drd_clientobj_get(semaphore, ClientSemaphore)->semaphore;
+}
+
+/** Called before sem_init(). */
struct semaphore_info* semaphore_init(const Addr semaphore, const SizeT size,
const Word pshared, const UWord value)
{
@@ -113,31 +120,51 @@
return p;
}
+/** Called after sem_destroy(). */
void semaphore_destroy(struct semaphore_info* const p)
{
- drd_finish_suppression(p->semaphore, p->semaphore + p->size);
-
- vc_cleanup(&p->vc);
- p->semaphore = 0;
+ drd_clientobj_remove(p->a1, ClientSemaphore);
}
-struct semaphore_info* semaphore_get(const Addr semaphore)
+/** Called before sem_wait(). */
+void semaphore_pre_wait(const Addr semaphore, const SizeT size)
{
- int i;
- for (i = 0; i < sizeof(s_semaphore)/sizeof(s_semaphore[0]); i++)
- if (s_semaphore[i].semaphore == semaphore)
- return &s_semaphore[i];
- return 0;
+ struct semaphore_info* p;
+
+ p = semaphore_get_or_allocate(semaphore, size);
+ if (s_trace_semaphore)
+ {
+ VG_(message)(Vg_UserMsg, "semaphore_pre_wait(0x%lx, %d)", semaphore, size);
+ }
+ tl_assert(p);
+ tl_assert(p->waiters >= 0);
+ p->waiters++;
+ tl_assert(p->waiters > 0);
}
-/** Called after sem_wait() finished successfully. */
+/** Called after sem_wait() finished.
+ * @note Do not rely on the value of 'waited' -- some glibc versions do
+ * not set it correctly.
+ */
void semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
- const SizeT size)
+ const Bool waited)
{
struct semaphore_info* p;
- p = semaphore_get_or_allocate(semaphore, size);
+ p = semaphore_get(semaphore);
+ if (s_trace_semaphore)
+ {
+ VG_(message)(Vg_UserMsg, "semaphore_post_wait(0x%lx, %d)", semaphore);
+ }
+ tl_assert(p->waiters > 0);
+ p->waiters--;
+ tl_assert(p->waiters >= 0);
tl_assert(p->value >= 0);
+ if (p->value == 0)
+ {
+ VG_(message)(Vg_UserMsg, "Invalid semaphore 0x%lx", semaphore);
+ return;
+ }
p->value--;
tl_assert(p->value >= 0);
if (p->last_sem_post_tid != tid)
@@ -178,16 +205,3 @@
void semaphore_thread_delete(const DrdThreadId threadid)
{ }
-
-void semaphore_stop_using_mem(const Addr a1, const Addr a2)
-{
- unsigned i;
- for (i = 0; i < sizeof(s_semaphore)/sizeof(s_semaphore[0]); i++)
- {
- if (a1 <= s_semaphore[i].semaphore && s_semaphore[i].semaphore < a2)
- {
- tl_assert(s_semaphore[i].semaphore + s_semaphore[i].size <= a2);
- semaphore_destroy(&s_semaphore[i]);
- }
- }
-}
Modified: trunk/exp-drd/drd_semaphore.h
===================================================================
--- trunk/exp-drd/drd_semaphore.h 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_semaphore.h 2008-02-29 17:27:03 UTC (rev 7508)
@@ -26,8 +26,8 @@
// Semaphore state information: owner thread and recursion count.
-#ifndef __SEMAPHORE_H
-#define __SEMAPHORE_H
+#ifndef __DRD_SEMAPHORE_H
+#define __DRD_SEMAPHORE_H
#include "drd_thread.h" // DrdThreadId
@@ -43,14 +43,14 @@
const Word pshared, const UWord value);
void semaphore_destroy(struct semaphore_info* const p);
struct semaphore_info* semaphore_get(const Addr semaphore);
+void semaphore_pre_wait(const Addr semaphore, const SizeT size);
void semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
- const SizeT size);
+ const Bool waited);
void semaphore_pre_post(const DrdThreadId tid, const Addr semaphore,
const SizeT size);
void semaphore_post_post(const DrdThreadId tid, const Addr semaphore,
const SizeT size, const Bool waited);
void semaphore_thread_delete(const DrdThreadId tid);
-void semaphore_stop_using_mem(const Addr a1, const Addr a2);
-#endif /* __SEMAPHORE_H */
+#endif /* __DRD_SEMAPHORE_H */
Modified: trunk/exp-drd/drd_track.h
===================================================================
--- trunk/exp-drd/drd_track.h 2008-02-29 13:15:57 UTC (rev 7507)
+++ trunk/exp-drd/drd_track.h 2008-02-29 17:27:03 UTC (rev 7508)
@@ -40,8 +40,10 @@
void drd_semaphore_init(const Addr semaphore, const SizeT size,
const Word pshared, const Word value);
void drd_semaphore_destroy(const Addr semaphore);
+void drd_semaphore_pre_wait(const DrdThreadId tid, const Addr semaphore,
+ const SizeT size);
void drd_semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
- const SizeT size);
+ const Bool waited);
void drd_semaphore_pre_post(const DrdThreadId tid, const Addr semaphore,
const SizeT size);
void drd_semaphore_post_post(const DrdThreadId tid, const Addr semaphore,
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Valgrind-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/valgrind-developers