1af44c8236f7a73e71b16b707bba56f33af4d01cesewardj/* 286562bd89ac23ce795d19c71fabcb9d1c8f956d3bart This file is part of drd, a thread error detector. 3af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 4ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes Copyright (C) 2006-2017 Bart Van Assche <bvanassche@acm.org>. 5af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 6af44c8236f7a73e71b16b707bba56f33af4d01cesewardj This program is free software; you can redistribute it and/or 7af44c8236f7a73e71b16b707bba56f33af4d01cesewardj modify it under the terms of the GNU General Public License as 8af44c8236f7a73e71b16b707bba56f33af4d01cesewardj published by the Free Software Foundation; either version 2 of the 9af44c8236f7a73e71b16b707bba56f33af4d01cesewardj License, or (at your option) any later version. 10af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 11af44c8236f7a73e71b16b707bba56f33af4d01cesewardj This program is distributed in the hope that it will be useful, but 12af44c8236f7a73e71b16b707bba56f33af4d01cesewardj WITHOUT ANY WARRANTY; without even the implied warranty of 13af44c8236f7a73e71b16b707bba56f33af4d01cesewardj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14af44c8236f7a73e71b16b707bba56f33af4d01cesewardj General Public License for more details. 15af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 16af44c8236f7a73e71b16b707bba56f33af4d01cesewardj You should have received a copy of the GNU General Public License 17af44c8236f7a73e71b16b707bba56f33af4d01cesewardj along with this program; if not, write to the Free Software 18af44c8236f7a73e71b16b707bba56f33af4d01cesewardj Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 19af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 02111-1307, USA. 20af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 21af44c8236f7a73e71b16b707bba56f33af4d01cesewardj The GNU General Public License is contained in the file COPYING. 22af44c8236f7a73e71b16b707bba56f33af4d01cesewardj*/ 23af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 24af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 2528230a3734e045791173aca660efc7d7aeef78cebart#include "drd_clientobj.h" 26af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "drd_cond.h" 27af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "drd_error.h" 28af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "drd_mutex.h" 2946b5fcebcf676fcc950a359d9dee5ac0d5755afcbart#include "pub_tool_errormgr.h" /* VG_(maybe_record_error)() */ 3046b5fcebcf676fcc950a359d9dee5ac0d5755afcbart#include "pub_tool_libcassert.h" /* tl_assert() */ 31850f1990e89f10e7efb33a140ab14baaebacc864bart#include "pub_tool_libcbase.h" /* VG_(memcmp)() */ 3246b5fcebcf676fcc950a359d9dee5ac0d5755afcbart#include "pub_tool_libcprint.h" /* VG_(printf)() */ 3346b5fcebcf676fcc950a359d9dee5ac0d5755afcbart#include "pub_tool_machine.h" /* VG_(get_IP)() */ 3446b5fcebcf676fcc950a359d9dee5ac0d5755afcbart#include "pub_tool_threadstate.h" /* VG_(get_running_tid)() */ 35af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 36af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 3746b5fcebcf676fcc950a359d9dee5ac0d5755afcbart/* Local functions. */ 3828230a3734e045791173aca660efc7d7aeef78cebart 39dc1ef03a8d13efe24661a89091e66169bf3f1091bartstatic void DRD_(cond_cleanup)(struct cond_info* p); 4028230a3734e045791173aca660efc7d7aeef78cebart 4128230a3734e045791173aca660efc7d7aeef78cebart 4246b5fcebcf676fcc950a359d9dee5ac0d5755afcbart/* Local variables. */ 4328230a3734e045791173aca660efc7d7aeef78cebart 44dc1ef03a8d13efe24661a89091e66169bf3f1091bartstatic Bool DRD_(s_report_signal_unlocked) = True; 45dc1ef03a8d13efe24661a89091e66169bf3f1091bartstatic Bool DRD_(s_trace_cond); 46af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 47af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 4846b5fcebcf676fcc950a359d9dee5ac0d5755afcbart/* Function definitions. */ 4928230a3734e045791173aca660efc7d7aeef78cebart 50dc1ef03a8d13efe24661a89091e66169bf3f1091bartvoid DRD_(cond_set_report_signal_unlocked)(const Bool r) 51764dea2795ab46dadc2198a1123c0943181c6e70bart{ 52bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(s_report_signal_unlocked) = r; 53764dea2795ab46dadc2198a1123c0943181c6e70bart} 54764dea2795ab46dadc2198a1123c0943181c6e70bart 55dc1ef03a8d13efe24661a89091e66169bf3f1091bartvoid DRD_(cond_set_trace)(const Bool trace_cond) 56af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 57bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(s_trace_cond) = trace_cond; 58af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 59af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 60af44c8236f7a73e71b16b707bba56f33af4d01cesewardjstatic 61dc1ef03a8d13efe24661a89091e66169bf3f1091bartvoid DRD_(cond_initialize)(struct cond_info* const p, const Addr cond) 62af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 63bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(cond != 0); 6462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart tl_assert(p->a1 == cond); 6562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart tl_assert(p->type == ClientCondvar); 66bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 67bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->cleanup = (void(*)(DrdClientobj*))(DRD_(cond_cleanup)); 68bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->delete_thread = 0; 69bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->waiter_count = 0; 70bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->mutex = 0; 71af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 72af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 73195e41fe2b9e02e142a0461113bfa55c89d24c5ebart/** 74195e41fe2b9e02e142a0461113bfa55c89d24c5ebart * Free the memory that was allocated by cond_initialize(). Called by 75195e41fe2b9e02e142a0461113bfa55c89d24c5ebart * DRD_(clientobj_remove)(). 7628230a3734e045791173aca660efc7d7aeef78cebart */ 77dc1ef03a8d13efe24661a89091e66169bf3f1091bartstatic void DRD_(cond_cleanup)(struct cond_info* p) 78af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 79bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p); 80bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p->mutex) 81bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 82bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct mutex_info* q; 83bedfd237fbdc80d0c917cfcb85a94b5561c92633bart q = &(DRD_(clientobj_get)(p->mutex, ClientMutex)->mutex); 84bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 8562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart CondDestrErrInfo cde = { 8662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart DRD_(thread_get_running_tid)(), 8762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart p->a1, 8862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart q ? q->a1 : 0, 8962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart q ? q->owner : DRD_INVALID_THREADID 9062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart }; 91bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 92bedfd237fbdc80d0c917cfcb85a94b5561c92633bart CondDestrErr, 93bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 94bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Destroying condition variable that is being" 95bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " waited upon", 96bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &cde); 97bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 98bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 9928230a3734e045791173aca660efc7d7aeef78cebart} 10028230a3734e045791173aca660efc7d7aeef78cebart 10162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart/** 10262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart * Report that the synchronization object at address 'addr' is of the 10362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart * wrong type. 10462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart */ 10562cc23286aa2d2cbeb6643a15ef37fe020a3d159bartstatic void wrong_type(const Addr addr) 10662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart{ 10762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart GenericErrInfo gei = { 10862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart .tid = DRD_(thread_get_running_tid)(), 10962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart .addr = addr, 11062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart }; 11162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart VG_(maybe_record_error)(VG_(get_running_tid)(), 11262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart GenericErr, 11362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart VG_(get_IP)(VG_(get_running_tid)()), 11462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart "wrong type of synchronization object", 11562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart &gei); 11662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart} 11762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 118d45d99553c15a361bb797d21ec6afb9bad22d2d4bartstatic struct cond_info* cond_get_or_allocate(const Addr cond) 11928230a3734e045791173aca660efc7d7aeef78cebart{ 120bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct cond_info *p; 121bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 122bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(offsetof(DrdClientobj, cond) == 0); 123bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = &(DRD_(clientobj_get)(cond, ClientCondvar)->cond); 12462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart if (p) 12562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart return p; 12662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 12762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart if (DRD_(clientobj_present)(cond, cond + 1)) 128bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 12962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart wrong_type(cond); 13062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart return 0; 131bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 13262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 13362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart p = &(DRD_(clientobj_add)(cond, ClientCondvar)->cond); 13462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart DRD_(cond_initialize)(p, cond); 135bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return p; 136af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 137af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 138d45d99553c15a361bb797d21ec6afb9bad22d2d4bartstruct cond_info* DRD_(cond_get)(const Addr cond) 13928230a3734e045791173aca660efc7d7aeef78cebart{ 140bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(offsetof(DrdClientobj, cond) == 0); 141bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return &(DRD_(clientobj_get)(cond, ClientCondvar)->cond); 14228230a3734e045791173aca660efc7d7aeef78cebart} 14328230a3734e045791173aca660efc7d7aeef78cebart 14428230a3734e045791173aca660efc7d7aeef78cebart/** Called before pthread_cond_init(). */ 145dc1ef03a8d13efe24661a89091e66169bf3f1091bartvoid DRD_(cond_pre_init)(const Addr cond) 146af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 147bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct cond_info* p; 148bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 149bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (DRD_(s_trace_cond)) 150ea71ffb08eccc0869c5b9421160fef4052e35c23florian DRD_(trace_msg)("[%u] cond_init cond 0x%lx", 151b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), cond); 152bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 153bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(cond_get)(cond); 154bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 1554005d47b84b5ab8ae64eeb4b4e73102d3bdb4b09bart if (p) { 156d45d99553c15a361bb797d21ec6afb9bad22d2d4bart CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond }; 157bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 158bedfd237fbdc80d0c917cfcb85a94b5561c92633bart CondErr, 159bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 160bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "initialized twice", 161bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &cei); 162bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 163bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 1644005d47b84b5ab8ae64eeb4b4e73102d3bdb4b09bart cond_get_or_allocate(cond); 165af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 166af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 16728230a3734e045791173aca660efc7d7aeef78cebart/** Called after pthread_cond_destroy(). */ 168d36fa80de3fb0350509a3714bb795392aca21849bartvoid DRD_(cond_post_destroy)(const Addr cond, const Bool destroy_succeeded) 169af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 170bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct cond_info* p; 171bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 172bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (DRD_(s_trace_cond)) 173ea71ffb08eccc0869c5b9421160fef4052e35c23florian DRD_(trace_msg)("[%u] cond_destroy cond 0x%lx", 174b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), cond); 175bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 176bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(cond_get)(cond); 177bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0) 178bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 179d45d99553c15a361bb797d21ec6afb9bad22d2d4bart CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond }; 180bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 181bedfd237fbdc80d0c917cfcb85a94b5561c92633bart CondErr, 182bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 183bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "not a condition variable", 184bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &cei); 185bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 186bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 187bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 188bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p->waiter_count != 0) 189bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 190d45d99553c15a361bb797d21ec6afb9bad22d2d4bart CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond }; 191bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 192bedfd237fbdc80d0c917cfcb85a94b5561c92633bart CondErr, 193bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 194bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "destruction of condition variable being waited" 195bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " upon", 196bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &cei); 197bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 198bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 199d36fa80de3fb0350509a3714bb795392aca21849bart if (destroy_succeeded) 200d36fa80de3fb0350509a3714bb795392aca21849bart DRD_(clientobj_remove)(p->a1, ClientCondvar); 201af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 202af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 20362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart/** 20462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart * Called before pthread_cond_wait(). Note: before this function is called, 20562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart * mutex_unlock() has already been called from drd_clientreq.c. 20608e6d6ac35bce1b6a2203a23c4dafd96035fdc29bart */ 20762cc23286aa2d2cbeb6643a15ef37fe020a3d159bartvoid DRD_(cond_pre_wait)(const Addr cond, const Addr mutex) 208af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 209bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct cond_info* p; 210bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct mutex_info* q; 211bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 212bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (DRD_(s_trace_cond)) 213ea71ffb08eccc0869c5b9421160fef4052e35c23florian DRD_(trace_msg)("[%u] cond_pre_wait cond 0x%lx", 214b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), cond); 215bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 216d45d99553c15a361bb797d21ec6afb9bad22d2d4bart p = cond_get_or_allocate(cond); 21762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart if (!p) 21862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart { 21962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond }; 22062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart VG_(maybe_record_error)(VG_(get_running_tid)(), 22162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart CondErr, 22262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart VG_(get_IP)(VG_(get_running_tid)()), 22362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart "not a condition variable", 22462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart &cei); 22562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart return; 22662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart } 227bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 228bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p->waiter_count == 0) 229bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 230bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->mutex = mutex; 231bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 232bedfd237fbdc80d0c917cfcb85a94b5561c92633bart else if (p->mutex != mutex) 233bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 234bedfd237fbdc80d0c917cfcb85a94b5561c92633bart CondWaitErrInfo cwei 235d45d99553c15a361bb797d21ec6afb9bad22d2d4bart = { .tid = DRD_(thread_get_running_tid)(), 236d45d99553c15a361bb797d21ec6afb9bad22d2d4bart .cond = cond, .mutex1 = p->mutex, .mutex2 = mutex }; 237bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 238bedfd237fbdc80d0c917cfcb85a94b5561c92633bart CondWaitErr, 239bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 240bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Inconsistent association of condition variable" 241bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " and mutex", 242bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &cwei); 243bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 244bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p->mutex); 245bedfd237fbdc80d0c917cfcb85a94b5561c92633bart q = DRD_(mutex_get)(p->mutex); 246bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (q 247bedfd237fbdc80d0c917cfcb85a94b5561c92633bart && q->owner == DRD_(thread_get_running_tid)() && q->recursion_count > 0) 248bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 249bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const ThreadId vg_tid = VG_(get_running_tid)(); 250d45d99553c15a361bb797d21ec6afb9bad22d2d4bart MutexErrInfo MEI = { DRD_(thread_get_running_tid)(), 251d45d99553c15a361bb797d21ec6afb9bad22d2d4bart q->a1, q->recursion_count, q->owner }; 252bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(vg_tid, 253bedfd237fbdc80d0c917cfcb85a94b5561c92633bart MutexErr, 254bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(vg_tid), 255bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Mutex locked recursively", 256bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &MEI); 257bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 258bedfd237fbdc80d0c917cfcb85a94b5561c92633bart else if (q == 0) 259bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 260bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(not_a_mutex)(p->mutex); 261bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 262bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 26362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart ++p->waiter_count; 264af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 265af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 26662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart/** 26762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart * Called after pthread_cond_wait(). 26862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart */ 26962cc23286aa2d2cbeb6643a15ef37fe020a3d159bartvoid DRD_(cond_post_wait)(const Addr cond) 270af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 271bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct cond_info* p; 272bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 273bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (DRD_(s_trace_cond)) 274ea71ffb08eccc0869c5b9421160fef4052e35c23florian DRD_(trace_msg)("[%u] cond_post_wait cond 0x%lx", 275b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), cond); 276bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 277bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(cond_get)(cond); 27862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart if (!p) 279bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 2807a2cc3c5be225eb49813c1460d861481ee490d6ebart CondDestrErrInfo cde = { 2817a2cc3c5be225eb49813c1460d861481ee490d6ebart DRD_(thread_get_running_tid)(), cond, 0, DRD_INVALID_THREADID 2827a2cc3c5be225eb49813c1460d861481ee490d6ebart }; 2837a2cc3c5be225eb49813c1460d861481ee490d6ebart VG_(maybe_record_error)(VG_(get_running_tid)(), 2847a2cc3c5be225eb49813c1460d861481ee490d6ebart CondDestrErr, 2857a2cc3c5be225eb49813c1460d861481ee490d6ebart VG_(get_IP)(VG_(get_running_tid)()), 2867a2cc3c5be225eb49813c1460d861481ee490d6ebart "condition variable has been destroyed while" 2877a2cc3c5be225eb49813c1460d861481ee490d6ebart " being waited upon", 2887a2cc3c5be225eb49813c1460d861481ee490d6ebart &cde); 28962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart return; 29062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart } 29162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 29262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart if (p->waiter_count > 0) 29362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart { 29462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart --p->waiter_count; 29562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart if (p->waiter_count == 0) 29662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart { 29762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart p->mutex = 0; 298a9c5508b2963e498de4fa95777ff3efd59d65a3abart } 299bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 300af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 301af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 30262cc23286aa2d2cbeb6643a15ef37fe020a3d159bartstatic void cond_signal(const DrdThreadId tid, struct cond_info* const cond_p) 303af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 304bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const ThreadId vg_tid = VG_(get_running_tid)(); 305bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const DrdThreadId drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid); 306bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 30762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart tl_assert(cond_p); 30862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 30962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart if (cond_p->waiter_count > 0) 310bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 311bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (DRD_(s_report_signal_unlocked) 31262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart && ! DRD_(mutex_is_locked_by)(cond_p->mutex, drd_tid)) 313bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 31462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart /* 31562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart * A signal is sent while the associated mutex has not been locked. 31662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart * This can indicate but is not necessarily a race condition. 31762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart */ 31862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart CondRaceErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), 31962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart .cond = cond_p->a1, 32062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart .mutex = cond_p->mutex, 32162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart }; 32262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart VG_(maybe_record_error)(vg_tid, 32362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart CondRaceErr, 32462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart VG_(get_IP)(vg_tid), 32562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart "CondErr", 32662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart &cei); 327bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 328bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 329bedfd237fbdc80d0c917cfcb85a94b5561c92633bart else 330bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 33162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart /* 33262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart * No other thread is waiting for the signal, hence the signal will 33362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart * be lost. This is normal in a POSIX threads application. 33462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart */ 335bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 336af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 337af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 33862cc23286aa2d2cbeb6643a15ef37fe020a3d159bartstatic void not_initialized(Addr const cond) 33962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart{ 34062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond }; 34162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart VG_(maybe_record_error)(VG_(get_running_tid)(), 34262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart CondErr, 34362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart VG_(get_IP)(VG_(get_running_tid)()), 34462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart "condition variable has not been initialized", 34562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart &cei); 34662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart} 34762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 3483b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart/** Called before pthread_cond_signal(). */ 349dc1ef03a8d13efe24661a89091e66169bf3f1091bartvoid DRD_(cond_pre_signal)(Addr const cond) 3503b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart{ 35162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart struct cond_info* p; 35262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 35362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart p = DRD_(cond_get)(cond); 354bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (DRD_(s_trace_cond)) 355ea71ffb08eccc0869c5b9421160fef4052e35c23florian DRD_(trace_msg)("[%u] cond_signal cond 0x%lx", 356b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), cond); 357bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 358850f1990e89f10e7efb33a140ab14baaebacc864bart tl_assert(DRD_(pthread_cond_initializer)); 359850f1990e89f10e7efb33a140ab14baaebacc864bart if (!p && VG_(memcmp)((void*)cond, (void*)DRD_(pthread_cond_initializer), 360850f1990e89f10e7efb33a140ab14baaebacc864bart DRD_(pthread_cond_initializer_size)) != 0) 36162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart { 36262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart not_initialized(cond); 36362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart return; 36462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart } 36562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 366850f1990e89f10e7efb33a140ab14baaebacc864bart if (!p) 367850f1990e89f10e7efb33a140ab14baaebacc864bart p = cond_get_or_allocate(cond); 368850f1990e89f10e7efb33a140ab14baaebacc864bart 36962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart cond_signal(DRD_(thread_get_running_tid)(), p); 3703b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart} 3713b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart 37228230a3734e045791173aca660efc7d7aeef78cebart/** Called before pthread_cond_broadcast(). */ 373dc1ef03a8d13efe24661a89091e66169bf3f1091bartvoid DRD_(cond_pre_broadcast)(Addr const cond) 374af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 37562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart struct cond_info* p; 37662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 377bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (DRD_(s_trace_cond)) 378ea71ffb08eccc0869c5b9421160fef4052e35c23florian DRD_(trace_msg)("[%u] cond_broadcast cond 0x%lx", 379b92ff0fd192dd05700f7d20db00795965e20b5c5bart DRD_(thread_get_running_tid)(), cond); 380bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 38162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart p = DRD_(cond_get)(cond); 382850f1990e89f10e7efb33a140ab14baaebacc864bart tl_assert(DRD_(pthread_cond_initializer)); 383850f1990e89f10e7efb33a140ab14baaebacc864bart if (!p && VG_(memcmp)((void*)cond, (void*)DRD_(pthread_cond_initializer), 384850f1990e89f10e7efb33a140ab14baaebacc864bart DRD_(pthread_cond_initializer_size)) != 0) 38562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart { 38662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart not_initialized(cond); 38762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart return; 38862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart } 38962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 390850f1990e89f10e7efb33a140ab14baaebacc864bart if (!p) 391850f1990e89f10e7efb33a140ab14baaebacc864bart p = cond_get_or_allocate(cond); 392850f1990e89f10e7efb33a140ab14baaebacc864bart 39362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart cond_signal(DRD_(thread_get_running_tid)(), p); 394af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 395