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 Valgrind-developers@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/valgrind-developers