From: Bart Van Assche Date: Wed, 12 Mar 2008 17:23:07 +0000 (+0000) Subject: Bug fix: sometimes an assert was triggered if pthread_barrier_destroy() was called... X-Git-Tag: svn/VALGRIND_3_4_0~895 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0c4e5b8ce4c97e461a74725252c225c7075412eb;p=thirdparty%2Fvalgrind.git Bug fix: sometimes an assert was triggered if pthread_barrier_destroy() was called after the last pthread_barrier_wait() finished and before the post-pthread_barrier_wait() client request finished. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7654 --- diff --git a/exp-drd/drd_barrier.c b/exp-drd/drd_barrier.c index 05f4fc4265..dc7b46ddef 100644 --- a/exp-drd/drd_barrier.c +++ b/exp-drd/drd_barrier.c @@ -52,7 +52,9 @@ struct barrier_thread_info // Local functions. -void barrier_cleanup(struct barrier_info* p); +static void barrier_cleanup(struct barrier_info* p); +static const char* barrier_get_typename(struct barrier_info* const p); +static const char* barrier_type_name(const BarrierT bt); // Local variables. @@ -100,6 +102,7 @@ void barrier_initialize(struct barrier_info* const p, tl_assert(p->a1 == barrier); p->cleanup = (void(*)(DrdClientobj*))barrier_cleanup; + p->barrier_type = barrier_type; p->count = count; p->pre_iteration = 0; p->post_iteration = 0; @@ -121,7 +124,7 @@ void barrier_cleanup(struct barrier_info* p) tl_assert(p); - if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count) + if (p->pre_waiters_left != p->count) { BarrierErrInfo bei = { p->a1 }; VG_(maybe_record_error)(VG_(get_running_tid)(), @@ -178,17 +181,44 @@ void barrier_init(const Addr barrier, const BarrierT barrier_type, const Word count, const Bool reinitialization) { + struct barrier_info* p; + + tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); + + p = barrier_get_or_allocate(barrier, barrier_type, count); + if (s_trace_barrier) { - VG_(message)(Vg_UserMsg, - "[%d/%d] barrier_init 0x%lx", - VG_(get_running_tid)(), - thread_get_running_tid(), - barrier); + if (reinitialization) + { + VG_(message)(Vg_UserMsg, + "[%d/%d] barrier_reinit %s 0x%lx count %d -> %d", + VG_(get_running_tid)(), + thread_get_running_tid(), + barrier_get_typename(p), + barrier, + p->count, + count); + } + else + { + VG_(message)(Vg_UserMsg, + "[%d/%d] barrier_init %s 0x%lx", + VG_(get_running_tid)(), + thread_get_running_tid(), + barrier_get_typename(p), + barrier); + } + } + + if (reinitialization && p->count != count) + { + if (p->pre_waiters_left != p->count || p->post_waiters_left != p->count) + { + VG_(message)(Vg_UserMsg, "Error: reinitialization with active waiters"); + } + p->count = count; } - tl_assert(barrier_get(barrier) == 0); - tl_assert(barrier_type == pthread_barrier || barrier_type == gomp_barrier); - barrier_get_or_allocate(barrier, barrier_type, count); } /** Called after pthread_barrier_destroy(). */ @@ -196,16 +226,18 @@ void barrier_destroy(const Addr barrier, const BarrierT barrier_type) { struct barrier_info* p; + p = barrier_get(barrier); + if (s_trace_barrier) { VG_(message)(Vg_UserMsg, - "[%d/%d] barrier_destroy 0x%lx", + "[%d/%d] barrier_destroy %s 0x%lx", VG_(get_running_tid)(), thread_get_running_tid(), + barrier_get_typename(p), barrier); } - p = barrier_get(barrier); if (p == 0) { GenericErrInfo GEI; @@ -234,9 +266,10 @@ void barrier_pre_wait(const DrdThreadId tid, const Addr barrier, if (s_trace_barrier) { VG_(message)(Vg_UserMsg, - "[%d/%d] barrier_pre_wait 0x%lx iteration %d", + "[%d/%d] barrier_pre_wait %s 0x%lx iteration %d", VG_(get_running_tid)(), thread_get_running_tid(), + barrier_get_typename(p), barrier, p->pre_iteration); } @@ -266,18 +299,24 @@ void barrier_post_wait(const DrdThreadId tid, const Addr barrier, struct barrier_info* p; p = barrier_get(barrier); - tl_assert(p); if (s_trace_barrier) { VG_(message)(Vg_UserMsg, - "[%d/%d] barrier_post_wait 0x%lx iteration %d", + "[%d/%d] barrier_post_wait %s 0x%lx iteration %d", VG_(get_running_tid)(), tid, + p ? barrier_get_typename(p) : "(?)", barrier, - p->post_iteration); + p ? p->post_iteration : -1); } + /* If p == 0, this means that the barrier has been destroyed after */ + /* *_barrier_wait() returned and before this function was called. Just */ + /* return in that case. */ + if (p == 0) + return; + if (waited) { const UWord word_tid = tid; @@ -322,3 +361,22 @@ void barrier_thread_delete(const DrdThreadId tid) VG_(OSetGen_FreeNode)(p->oset, q); } } + +static const char* barrier_get_typename(struct barrier_info* const p) +{ + tl_assert(p); + + return barrier_type_name(p->barrier_type); +} + +static const char* barrier_type_name(const BarrierT bt) +{ + switch (bt) + { + case pthread_barrier: + return "pthread barrier"; + case gomp_barrier: + return "gomp barrier"; + } + return "?"; +} diff --git a/exp-drd/drd_clientobj.h b/exp-drd/drd_clientobj.h index 3a91ac7a3f..9302b2ab05 100644 --- a/exp-drd/drd_clientobj.h +++ b/exp-drd/drd_clientobj.h @@ -92,6 +92,7 @@ struct barrier_info Addr a1; ObjType type; void (*cleanup)(union drd_clientobj*); + BarrierT barrier_type; // pthread_barrier or gomp_barrier. 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.