drd_cond.c revision 62cc23286aa2d2cbeb6643a15ef37fe020a3d159
1bedfd237fbdc80d0c917cfcb85a94b5561c92633bart/* -*- mode: C; c-basic-offset: 3; -*- */ 2af44c8236f7a73e71b16b707bba56f33af4d01cesewardj/* 386562bd89ac23ce795d19c71fabcb9d1c8f956d3bart This file is part of drd, a thread error detector. 4af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 586562bd89ac23ce795d19c71fabcb9d1c8f956d3bart Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>. 6af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 7af44c8236f7a73e71b16b707bba56f33af4d01cesewardj This program is free software; you can redistribute it and/or 8af44c8236f7a73e71b16b707bba56f33af4d01cesewardj modify it under the terms of the GNU General Public License as 9af44c8236f7a73e71b16b707bba56f33af4d01cesewardj published by the Free Software Foundation; either version 2 of the 10af44c8236f7a73e71b16b707bba56f33af4d01cesewardj License, or (at your option) any later version. 11af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 12af44c8236f7a73e71b16b707bba56f33af4d01cesewardj This program is distributed in the hope that it will be useful, but 13af44c8236f7a73e71b16b707bba56f33af4d01cesewardj WITHOUT ANY WARRANTY; without even the implied warranty of 14af44c8236f7a73e71b16b707bba56f33af4d01cesewardj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15af44c8236f7a73e71b16b707bba56f33af4d01cesewardj General Public License for more details. 16af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 17af44c8236f7a73e71b16b707bba56f33af4d01cesewardj You should have received a copy of the GNU General Public License 18af44c8236f7a73e71b16b707bba56f33af4d01cesewardj along with this program; if not, write to the Free Software 19af44c8236f7a73e71b16b707bba56f33af4d01cesewardj Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 20af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 02111-1307, USA. 21af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 22af44c8236f7a73e71b16b707bba56f33af4d01cesewardj The GNU General Public License is contained in the file COPYING. 23af44c8236f7a73e71b16b707bba56f33af4d01cesewardj*/ 24af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 25af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 2628230a3734e045791173aca660efc7d7aeef78cebart#include "drd_clientobj.h" 27af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "drd_cond.h" 28af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "drd_error.h" 29af44c8236f7a73e71b16b707bba56f33af4d01cesewardj#include "drd_mutex.h" 3046b5fcebcf676fcc950a359d9dee5ac0d5755afcbart#include "pub_tool_errormgr.h" /* VG_(maybe_record_error)() */ 3146b5fcebcf676fcc950a359d9dee5ac0d5755afcbart#include "pub_tool_libcassert.h" /* tl_assert() */ 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)) 150bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 151bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 15263c92ea799549976957f5b4d54ede744f762c56fbart "[%d] cond_init cond 0x%lx\n", 153bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_get_running_tid)(), 154bedfd237fbdc80d0c917cfcb85a94b5561c92633bart cond); 155bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 156bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 157bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(cond_get)(cond); 158bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 159bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p) 160bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 161d45d99553c15a361bb797d21ec6afb9bad22d2d4bart CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond }; 162bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 163bedfd237fbdc80d0c917cfcb85a94b5561c92633bart CondErr, 164bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 165bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "initialized twice", 166bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &cei); 167bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 168bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 169d45d99553c15a361bb797d21ec6afb9bad22d2d4bart p = cond_get_or_allocate(cond); 170af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 171af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 17228230a3734e045791173aca660efc7d7aeef78cebart/** Called after pthread_cond_destroy(). */ 173dc1ef03a8d13efe24661a89091e66169bf3f1091bartvoid DRD_(cond_post_destroy)(const Addr cond) 174af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 175bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct cond_info* p; 176bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 177bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (DRD_(s_trace_cond)) 178bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 179bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 18063c92ea799549976957f5b4d54ede744f762c56fbart "[%d] cond_destroy cond 0x%lx\n", 181bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_get_running_tid)(), 182bedfd237fbdc80d0c917cfcb85a94b5561c92633bart cond); 183bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 184bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 185bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(cond_get)(cond); 186bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p == 0) 187bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 188d45d99553c15a361bb797d21ec6afb9bad22d2d4bart CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond }; 189bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 190bedfd237fbdc80d0c917cfcb85a94b5561c92633bart CondErr, 191bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 192bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "not a condition variable", 193bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &cei); 194bedfd237fbdc80d0c917cfcb85a94b5561c92633bart return; 195bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 196bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 197bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p->waiter_count != 0) 198bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 199d45d99553c15a361bb797d21ec6afb9bad22d2d4bart CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond }; 200bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 201bedfd237fbdc80d0c917cfcb85a94b5561c92633bart CondErr, 202bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 203bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "destruction of condition variable being waited" 204bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " upon", 205bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &cei); 206bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 207bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 208bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(clientobj_remove)(p->a1, ClientCondvar); 209af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 210af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 21162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart/** 21262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart * Called before pthread_cond_wait(). Note: before this function is called, 21362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart * mutex_unlock() has already been called from drd_clientreq.c. 21408e6d6ac35bce1b6a2203a23c4dafd96035fdc29bart */ 21562cc23286aa2d2cbeb6643a15ef37fe020a3d159bartvoid DRD_(cond_pre_wait)(const Addr cond, const Addr mutex) 216af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 217bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct cond_info* p; 218bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct mutex_info* q; 219bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 220bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (DRD_(s_trace_cond)) 221bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 222bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 22363c92ea799549976957f5b4d54ede744f762c56fbart "[%d] cond_pre_wait cond 0x%lx\n", 224bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_get_running_tid)(), 225bedfd237fbdc80d0c917cfcb85a94b5561c92633bart cond); 226bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 227bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 228d45d99553c15a361bb797d21ec6afb9bad22d2d4bart p = cond_get_or_allocate(cond); 22962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart if (!p) 23062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart { 23162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond }; 23262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart VG_(maybe_record_error)(VG_(get_running_tid)(), 23362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart CondErr, 23462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart VG_(get_IP)(VG_(get_running_tid)()), 23562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart "not a condition variable", 23662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart &cei); 23762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart return; 23862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart } 239bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 240bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (p->waiter_count == 0) 241bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 242bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p->mutex = mutex; 243bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 244bedfd237fbdc80d0c917cfcb85a94b5561c92633bart else if (p->mutex != mutex) 245bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 246bedfd237fbdc80d0c917cfcb85a94b5561c92633bart CondWaitErrInfo cwei 247d45d99553c15a361bb797d21ec6afb9bad22d2d4bart = { .tid = DRD_(thread_get_running_tid)(), 248d45d99553c15a361bb797d21ec6afb9bad22d2d4bart .cond = cond, .mutex1 = p->mutex, .mutex2 = mutex }; 249bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(VG_(get_running_tid)(), 250bedfd237fbdc80d0c917cfcb85a94b5561c92633bart CondWaitErr, 251bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(VG_(get_running_tid)()), 252bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Inconsistent association of condition variable" 253bedfd237fbdc80d0c917cfcb85a94b5561c92633bart " and mutex", 254bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &cwei); 255bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 256bedfd237fbdc80d0c917cfcb85a94b5561c92633bart tl_assert(p->mutex); 257bedfd237fbdc80d0c917cfcb85a94b5561c92633bart q = DRD_(mutex_get)(p->mutex); 258bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (q 259bedfd237fbdc80d0c917cfcb85a94b5561c92633bart && q->owner == DRD_(thread_get_running_tid)() && q->recursion_count > 0) 260bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 261bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const ThreadId vg_tid = VG_(get_running_tid)(); 262d45d99553c15a361bb797d21ec6afb9bad22d2d4bart MutexErrInfo MEI = { DRD_(thread_get_running_tid)(), 263d45d99553c15a361bb797d21ec6afb9bad22d2d4bart q->a1, q->recursion_count, q->owner }; 264bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(maybe_record_error)(vg_tid, 265bedfd237fbdc80d0c917cfcb85a94b5561c92633bart MutexErr, 266bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(get_IP)(vg_tid), 267bedfd237fbdc80d0c917cfcb85a94b5561c92633bart "Mutex locked recursively", 268bedfd237fbdc80d0c917cfcb85a94b5561c92633bart &MEI); 269bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 270bedfd237fbdc80d0c917cfcb85a94b5561c92633bart else if (q == 0) 271bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 272bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(not_a_mutex)(p->mutex); 273bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 274bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 27562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart ++p->waiter_count; 276af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 277af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 27862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart/** 27962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart * Called after pthread_cond_wait(). 28062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart */ 28162cc23286aa2d2cbeb6643a15ef37fe020a3d159bartvoid DRD_(cond_post_wait)(const Addr cond) 282af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 283bedfd237fbdc80d0c917cfcb85a94b5561c92633bart struct cond_info* p; 284bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 285bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (DRD_(s_trace_cond)) 286bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 287bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 28863c92ea799549976957f5b4d54ede744f762c56fbart "[%d] cond_post_wait cond 0x%lx\n", 289bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_get_running_tid)(), 290bedfd237fbdc80d0c917cfcb85a94b5561c92633bart cond); 291bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 292bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 293bedfd237fbdc80d0c917cfcb85a94b5561c92633bart p = DRD_(cond_get)(cond); 29462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart if (!p) 295bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 29662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart struct mutex_info* q; 29762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart q = &(DRD_(clientobj_get)(p->mutex, ClientMutex)->mutex); 298a9c5508b2963e498de4fa95777ff3efd59d65a3abart { 29962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart CondDestrErrInfo cde = { 30062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart DRD_(thread_get_running_tid)(), 30162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart p->a1, 30262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart q ? q->a1 : 0, 30362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart q ? q->owner : DRD_INVALID_THREADID 30462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart }; 30562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart VG_(maybe_record_error)(VG_(get_running_tid)(), 30662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart CondDestrErr, 30762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart VG_(get_IP)(VG_(get_running_tid)()), 30862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart "condition variable has been destroyed while" 30962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart " being waited upon", 31062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart &cde); 31162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart } 31262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart return; 31362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart } 31462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 31562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart if (p->waiter_count > 0) 31662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart { 31762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart --p->waiter_count; 31862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart if (p->waiter_count == 0) 31962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart { 32062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart p->mutex = 0; 321a9c5508b2963e498de4fa95777ff3efd59d65a3abart } 322bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 323af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 324af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 32562cc23286aa2d2cbeb6643a15ef37fe020a3d159bartstatic void cond_signal(const DrdThreadId tid, struct cond_info* const cond_p) 326af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 327bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const ThreadId vg_tid = VG_(get_running_tid)(); 328bedfd237fbdc80d0c917cfcb85a94b5561c92633bart const DrdThreadId drd_tid = DRD_(VgThreadIdToDrdThreadId)(vg_tid); 329bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 33062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart tl_assert(cond_p); 33162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 33262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart if (cond_p->waiter_count > 0) 333bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 334bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (DRD_(s_report_signal_unlocked) 33562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart && ! DRD_(mutex_is_locked_by)(cond_p->mutex, drd_tid)) 336bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 33762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart /* 33862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart * A signal is sent while the associated mutex has not been locked. 33962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart * This can indicate but is not necessarily a race condition. 34062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart */ 34162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart CondRaceErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), 34262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart .cond = cond_p->a1, 34362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart .mutex = cond_p->mutex, 34462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart }; 34562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart VG_(maybe_record_error)(vg_tid, 34662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart CondRaceErr, 34762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart VG_(get_IP)(vg_tid), 34862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart "CondErr", 34962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart &cei); 350bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 351bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 352bedfd237fbdc80d0c917cfcb85a94b5561c92633bart else 353bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 35462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart /* 35562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart * No other thread is waiting for the signal, hence the signal will 35662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart * be lost. This is normal in a POSIX threads application. 35762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart */ 358bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 359af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 360af44c8236f7a73e71b16b707bba56f33af4d01cesewardj 36162cc23286aa2d2cbeb6643a15ef37fe020a3d159bartstatic void not_initialized(Addr const cond) 36262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart{ 36362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart CondErrInfo cei = { .tid = DRD_(thread_get_running_tid)(), .cond = cond }; 36462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart VG_(maybe_record_error)(VG_(get_running_tid)(), 36562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart CondErr, 36662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart VG_(get_IP)(VG_(get_running_tid)()), 36762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart "condition variable has not been initialized", 36862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart &cei); 36962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart} 37062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 3713b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart/** Called before pthread_cond_signal(). */ 372dc1ef03a8d13efe24661a89091e66169bf3f1091bartvoid DRD_(cond_pre_signal)(Addr const cond) 3733b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart{ 37462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart struct cond_info* p; 37562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 37662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart p = DRD_(cond_get)(cond); 377bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (DRD_(s_trace_cond)) 378bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 379bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 38063c92ea799549976957f5b4d54ede744f762c56fbart "[%d] cond_signal cond 0x%lx\n", 381bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_get_running_tid)(), 382bedfd237fbdc80d0c917cfcb85a94b5561c92633bart cond); 383bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 384bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 38562cc23286aa2d2cbeb6643a15ef37fe020a3d159bart if (!p) 38662cc23286aa2d2cbeb6643a15ef37fe020a3d159bart { 38762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart not_initialized(cond); 38862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart return; 38962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart } 39062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 39162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart cond_signal(DRD_(thread_get_running_tid)(), p); 3923b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart} 3933b1ee459c4a59f6479a7b2803f7ccd952aab44bbbart 39428230a3734e045791173aca660efc7d7aeef78cebart/** Called before pthread_cond_broadcast(). */ 395dc1ef03a8d13efe24661a89091e66169bf3f1091bartvoid DRD_(cond_pre_broadcast)(Addr const cond) 396af44c8236f7a73e71b16b707bba56f33af4d01cesewardj{ 39762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart struct cond_info* p; 39862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 399bedfd237fbdc80d0c917cfcb85a94b5561c92633bart if (DRD_(s_trace_cond)) 400bedfd237fbdc80d0c917cfcb85a94b5561c92633bart { 401bedfd237fbdc80d0c917cfcb85a94b5561c92633bart VG_(message)(Vg_UserMsg, 40263c92ea799549976957f5b4d54ede744f762c56fbart "[%d] cond_broadcast cond 0x%lx\n", 403bedfd237fbdc80d0c917cfcb85a94b5561c92633bart DRD_(thread_get_running_tid)(), 404bedfd237fbdc80d0c917cfcb85a94b5561c92633bart cond); 405bedfd237fbdc80d0c917cfcb85a94b5561c92633bart } 406bedfd237fbdc80d0c917cfcb85a94b5561c92633bart 40762cc23286aa2d2cbeb6643a15ef37fe020a3d159bart p = DRD_(cond_get)(cond); 40862cc23286aa2d2cbeb6643a15ef37fe020a3d159bart if (!p) 40962cc23286aa2d2cbeb6643a15ef37fe020a3d159bart { 41062cc23286aa2d2cbeb6643a15ef37fe020a3d159bart not_initialized(cond); 41162cc23286aa2d2cbeb6643a15ef37fe020a3d159bart return; 41262cc23286aa2d2cbeb6643a15ef37fe020a3d159bart } 41362cc23286aa2d2cbeb6643a15ef37fe020a3d159bart 41462cc23286aa2d2cbeb6643a15ef37fe020a3d159bart cond_signal(DRD_(thread_get_running_tid)(), p); 415af44c8236f7a73e71b16b707bba56f33af4d01cesewardj} 416