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