blob: 823da1cd5bd3355fac3427922a02afbe001142e8 [file] [log] [blame]
sewardjaf44c822007-11-25 14:01:38 +00001/*
2 This file is part of drd, a data race detector.
3
sewardj85642922008-01-14 11:54:56 +00004 Copyright (C) 2006-2008 Bart Van Assche
sewardjaf44c822007-11-25 14:01:38 +00005 bart.vanassche@gmail.com
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307, USA.
21
22 The GNU General Public License is contained in the file COPYING.
23*/
24
25
bart4bb53d82008-02-28 19:06:34 +000026#include "drd_clientobj.h"
sewardjaf44c822007-11-25 14:01:38 +000027#include "drd_error.h"
28#include "drd_mutex.h"
sewardj721ad7b2007-11-30 08:30:29 +000029#include "priv_drd_clientreq.h"
bart9d5b7962008-05-14 12:25:00 +000030#include "pub_tool_vki.h"
sewardjaf44c822007-11-25 14:01:38 +000031#include "pub_tool_errormgr.h" // VG_(maybe_record_error)()
32#include "pub_tool_libcassert.h" // tl_assert()
bart5bd9f2d2008-03-03 20:31:58 +000033#include "pub_tool_libcbase.h" // VG_(strlen)
bart4bb53d82008-02-28 19:06:34 +000034#include "pub_tool_libcprint.h" // VG_(message)()
bart9d5b7962008-05-14 12:25:00 +000035#include "pub_tool_libcproc.h" // VG_(read_millisecond_timer)()
sewardjaf44c822007-11-25 14:01:38 +000036#include "pub_tool_machine.h" // VG_(get_IP)()
37#include "pub_tool_threadstate.h" // VG_(get_running_tid)()
38
39
sewardj347eeba2008-01-21 14:19:07 +000040// Local functions.
41
bart46d5f172008-02-28 19:49:37 +000042static void mutex_cleanup(struct mutex_info* p);
bart5357fcb2008-02-27 15:46:00 +000043static Bool mutex_is_locked(struct mutex_info* const p);
sewardj347eeba2008-01-21 14:19:07 +000044
45
sewardjaf44c822007-11-25 14:01:38 +000046// Local variables.
47
48static Bool s_trace_mutex;
49static ULong s_mutex_lock_count;
bart6bbefaf2008-04-19 15:16:45 +000050static ULong s_mutex_segment_creation_count;
bart9d5b7962008-05-14 12:25:00 +000051static UInt s_mutex_lock_threshold_ms = 1000 * 1000;
sewardjaf44c822007-11-25 14:01:38 +000052
53
54// Function definitions.
55
56void mutex_set_trace(const Bool trace_mutex)
57{
58 tl_assert(!! trace_mutex == trace_mutex);
59 s_trace_mutex = trace_mutex;
60}
61
bart9d5b7962008-05-14 12:25:00 +000062void mutex_set_lock_threshold(const UInt lock_threshold_ms)
63{
64 s_mutex_lock_threshold_ms = lock_threshold_ms;
65}
66
sewardjaf44c822007-11-25 14:01:38 +000067static
68void mutex_initialize(struct mutex_info* const p,
bart0268dfa2008-03-11 20:10:21 +000069 const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +000070{
71 tl_assert(mutex != 0);
sewardjaf44c822007-11-25 14:01:38 +000072
bart4bb53d82008-02-28 19:06:34 +000073 tl_assert(p->a1 == mutex);
barta2b6e1b2008-03-17 18:32:39 +000074 p->cleanup = (void(*)(DrdClientobj*))&mutex_cleanup;
75 p->mutex_type = mutex_type;
76 p->recursion_count = 0;
77 p->owner = DRD_INVALID_THREADID;
78 p->last_locked_segment = 0;
bart9d5b7962008-05-14 12:25:00 +000079 p->acquiry_time_ms = 0;
bart886b87c2008-06-28 13:40:41 +000080 p->first_observed_at = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);
bart9d5b7962008-05-14 12:25:00 +000081 p->acquired_at = 0;
sewardjaf44c822007-11-25 14:01:38 +000082}
83
bart46d5f172008-02-28 19:49:37 +000084/** Deallocate the memory that was allocated by mutex_initialize(). */
85static void mutex_cleanup(struct mutex_info* p)
86{
bart6b717612008-03-24 09:29:38 +000087 tl_assert(p);
88
bartb78312c2008-02-29 11:00:17 +000089 if (s_trace_mutex)
90 {
bart3b1ee452008-02-29 19:28:15 +000091 VG_(message)(Vg_UserMsg,
92 "[%d/%d] mutex_destroy %s 0x%lx",
93 VG_(get_running_tid)(),
94 thread_get_running_tid(),
bartb78312c2008-02-29 11:00:17 +000095 mutex_get_typename(p),
96 p->a1);
97 }
98
bart46d5f172008-02-28 19:49:37 +000099 if (mutex_is_locked(p))
100 {
101 MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner };
102 VG_(maybe_record_error)(VG_(get_running_tid)(),
103 MutexErr,
104 VG_(get_IP)(VG_(get_running_tid)()),
105 "Destroying locked mutex",
106 &MEI);
107 }
108
barta2b6e1b2008-03-17 18:32:39 +0000109 sg_put(p->last_locked_segment);
110 p->last_locked_segment = 0;
bart46d5f172008-02-28 19:49:37 +0000111}
112
bart886b87c2008-06-28 13:40:41 +0000113/** Let Valgrind report that there is no mutex object at address 'mutex'. */
bart6b717612008-03-24 09:29:38 +0000114static void not_a_mutex(const Addr mutex)
115{
116 MutexErrInfo MEI = { mutex, -1, DRD_INVALID_THREADID };
117 VG_(maybe_record_error)(VG_(get_running_tid)(),
118 MutexErr,
119 VG_(get_IP)(VG_(get_running_tid)()),
120 "Not a mutex",
121 &MEI);
122}
123
sewardjaf44c822007-11-25 14:01:38 +0000124static
sewardj721ad7b2007-11-30 08:30:29 +0000125struct mutex_info*
bart0268dfa2008-03-11 20:10:21 +0000126mutex_get_or_allocate(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000127{
bart4bb53d82008-02-28 19:06:34 +0000128 struct mutex_info* p;
sewardj721ad7b2007-11-30 08:30:29 +0000129
bart4bb53d82008-02-28 19:06:34 +0000130 tl_assert(offsetof(DrdClientobj, mutex) == 0);
bart72b751c2008-03-01 13:44:24 +0000131 p = &clientobj_get(mutex, ClientMutex)->mutex;
bart4bb53d82008-02-28 19:06:34 +0000132 if (p)
133 {
bart4bb53d82008-02-28 19:06:34 +0000134 return p;
135 }
sewardj721ad7b2007-11-30 08:30:29 +0000136
bart0268dfa2008-03-11 20:10:21 +0000137 if (clientobj_present(mutex, mutex + 1))
sewardj721ad7b2007-11-30 08:30:29 +0000138 {
bart6b717612008-03-24 09:29:38 +0000139 not_a_mutex(mutex);
bart5bd9f2d2008-03-03 20:31:58 +0000140 return 0;
sewardj721ad7b2007-11-30 08:30:29 +0000141 }
bart4bb53d82008-02-28 19:06:34 +0000142
bart0268dfa2008-03-11 20:10:21 +0000143 p = &clientobj_add(mutex, ClientMutex)->mutex;
144 mutex_initialize(p, mutex, mutex_type);
bart4bb53d82008-02-28 19:06:34 +0000145 return p;
sewardjaf44c822007-11-25 14:01:38 +0000146}
147
bart3b1ee452008-02-29 19:28:15 +0000148struct mutex_info* mutex_get(const Addr mutex)
149{
150 tl_assert(offsetof(DrdClientobj, mutex) == 0);
bart72b751c2008-03-01 13:44:24 +0000151 return &clientobj_get(mutex, ClientMutex)->mutex;
bart3b1ee452008-02-29 19:28:15 +0000152}
153
bart00344642008-03-01 15:27:41 +0000154/** Called before pthread_mutex_init(). */
sewardj721ad7b2007-11-30 08:30:29 +0000155struct mutex_info*
bart0268dfa2008-03-11 20:10:21 +0000156mutex_init(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000157{
bart00344642008-03-01 15:27:41 +0000158 struct mutex_info* p;
sewardjaf44c822007-11-25 14:01:38 +0000159
sewardjaf44c822007-11-25 14:01:38 +0000160 if (s_trace_mutex)
161 {
bart3b1ee452008-02-29 19:28:15 +0000162 VG_(message)(Vg_UserMsg,
163 "[%d/%d] mutex_init %s 0x%lx",
164 VG_(get_running_tid)(),
165 thread_get_running_tid(),
sewardj347eeba2008-01-21 14:19:07 +0000166 mutex_type_name(mutex_type),
sewardjaf44c822007-11-25 14:01:38 +0000167 mutex);
168 }
169
bart00344642008-03-01 15:27:41 +0000170 if (mutex_type == mutex_type_invalid_mutex)
171 {
bart6b717612008-03-24 09:29:38 +0000172 not_a_mutex(mutex);
bart00344642008-03-01 15:27:41 +0000173 return 0;
174 }
175
176 p = mutex_get(mutex);
177 if (p)
sewardj347eeba2008-01-21 14:19:07 +0000178 {
179 const ThreadId vg_tid = VG_(get_running_tid)();
180 MutexErrInfo MEI
bart00344642008-03-01 15:27:41 +0000181 = { p->a1, p->recursion_count, p->owner };
sewardj347eeba2008-01-21 14:19:07 +0000182 VG_(maybe_record_error)(vg_tid,
183 MutexErr,
184 VG_(get_IP)(vg_tid),
185 "Mutex reinitialization",
186 &MEI);
bart00344642008-03-01 15:27:41 +0000187 return p;
sewardj347eeba2008-01-21 14:19:07 +0000188 }
bart0268dfa2008-03-11 20:10:21 +0000189 p = mutex_get_or_allocate(mutex, mutex_type);
sewardj347eeba2008-01-21 14:19:07 +0000190
bart00344642008-03-01 15:27:41 +0000191 return p;
sewardjaf44c822007-11-25 14:01:38 +0000192}
193
bart46d5f172008-02-28 19:49:37 +0000194/** Called after pthread_mutex_destroy(). */
sewardj347eeba2008-01-21 14:19:07 +0000195void mutex_post_destroy(const Addr mutex)
196{
bart72b751c2008-03-01 13:44:24 +0000197 struct mutex_info* p;
sewardj347eeba2008-01-21 14:19:07 +0000198
bart72b751c2008-03-01 13:44:24 +0000199 p = mutex_get(mutex);
200 if (p == 0)
201 {
bart6b717612008-03-24 09:29:38 +0000202 not_a_mutex(mutex);
bart72b751c2008-03-01 13:44:24 +0000203 return;
204 }
205
206 clientobj_remove(mutex, ClientMutex);
sewardj347eeba2008-01-21 14:19:07 +0000207}
208
bart8bba1f72008-02-27 16:13:05 +0000209/** Called before pthread_mutex_lock() is invoked. If a data structure for
210 * the client-side object was not yet created, do this now. Also check whether
211 * an attempt is made to lock recursively a synchronization object that must
212 * not be locked recursively.
213 */
bart2e3a3c12008-03-24 08:33:47 +0000214void mutex_pre_lock(const Addr mutex, const MutexT mutex_type,
215 const Bool trylock)
bart8bba1f72008-02-27 16:13:05 +0000216{
bart635cb162008-02-28 08:30:43 +0000217 struct mutex_info* p;
218
bart0268dfa2008-03-11 20:10:21 +0000219 p = mutex_get_or_allocate(mutex, mutex_type);
bart00344642008-03-01 15:27:41 +0000220 if (s_trace_mutex)
221 {
222 VG_(message)(Vg_UserMsg,
223 "[%d/%d] pre_mutex_lock %s 0x%lx rc %d owner %d",
224 VG_(get_running_tid)(),
225 thread_get_running_tid(),
bart6b717612008-03-24 09:29:38 +0000226 p ? mutex_get_typename(p) : "(?)",
bart00344642008-03-01 15:27:41 +0000227 mutex,
bart2e3a3c12008-03-24 08:33:47 +0000228 p ? p->recursion_count : -1,
229 p ? p->owner : DRD_INVALID_THREADID);
bart00344642008-03-01 15:27:41 +0000230 }
231
bart2e3a3c12008-03-24 08:33:47 +0000232 if (p == 0)
233 {
bart6b717612008-03-24 09:29:38 +0000234 not_a_mutex(mutex);
bart2e3a3c12008-03-24 08:33:47 +0000235 return;
236 }
237
238 tl_assert(p);
239
bart00344642008-03-01 15:27:41 +0000240 if (mutex_type == mutex_type_invalid_mutex)
241 {
bart6b717612008-03-24 09:29:38 +0000242 not_a_mutex(mutex);
bart00344642008-03-01 15:27:41 +0000243 return;
244 }
245
bart2e3a3c12008-03-24 08:33:47 +0000246 if (! trylock
247 && p->owner == thread_get_running_tid()
bart8bba1f72008-02-27 16:13:05 +0000248 && p->recursion_count >= 1
249 && mutex_type != mutex_type_recursive_mutex)
250 {
bart4bb53d82008-02-28 19:06:34 +0000251 MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner };
bart8bba1f72008-02-27 16:13:05 +0000252 VG_(maybe_record_error)(VG_(get_running_tid)(),
253 MutexErr,
254 VG_(get_IP)(VG_(get_running_tid)()),
255 "Recursive locking not allowed",
256 &MEI);
257 }
258}
259
sewardjaf44c822007-11-25 14:01:38 +0000260/**
261 * Update mutex_info state when locking the pthread_mutex_t mutex.
262 * Note: this function must be called after pthread_mutex_lock() has been
263 * called, or a race condition is triggered !
264 */
bart4a975e12008-03-30 13:28:33 +0000265void mutex_post_lock(const Addr mutex, const Bool took_lock,
266 const Bool post_cond_wait)
sewardjaf44c822007-11-25 14:01:38 +0000267{
bart3b1ee452008-02-29 19:28:15 +0000268 const DrdThreadId drd_tid = thread_get_running_tid();
bart00344642008-03-01 15:27:41 +0000269 struct mutex_info* p;
270
271 p = mutex_get(mutex);
sewardjaf44c822007-11-25 14:01:38 +0000272
273 if (s_trace_mutex)
274 {
bart3b1ee452008-02-29 19:28:15 +0000275 VG_(message)(Vg_UserMsg,
bart4a975e12008-03-30 13:28:33 +0000276 "[%d/%d] %s %s 0x%lx rc %d owner %d%s",
bart3b1ee452008-02-29 19:28:15 +0000277 VG_(get_running_tid)(),
sewardjaf44c822007-11-25 14:01:38 +0000278 drd_tid,
bart4a975e12008-03-30 13:28:33 +0000279 post_cond_wait ? "cond_post_wait " : "post_mutex_lock",
bart00344642008-03-01 15:27:41 +0000280 p ? mutex_get_typename(p) : "(?)",
sewardjaf44c822007-11-25 14:01:38 +0000281 mutex,
282 p ? p->recursion_count : 0,
bartfa37c922008-03-30 08:41:59 +0000283 p ? p->owner : VG_INVALID_THREADID,
284 took_lock ? "" : " (locking failed)");
sewardjaf44c822007-11-25 14:01:38 +0000285 }
286
bart777f7fe2008-03-02 17:43:18 +0000287 if (! p || ! took_lock)
bart5bd9f2d2008-03-03 20:31:58 +0000288 return;
bart5357fcb2008-02-27 15:46:00 +0000289
sewardjaf44c822007-11-25 14:01:38 +0000290 if (p->recursion_count == 0)
291 {
bart5bd9f2d2008-03-03 20:31:58 +0000292 const DrdThreadId last_owner = p->owner;
293
294 if (last_owner != drd_tid && last_owner != DRD_INVALID_THREADID)
barta2b6e1b2008-03-17 18:32:39 +0000295 {
296 tl_assert(p->last_locked_segment);
297 thread_combine_vc2(drd_tid, &p->last_locked_segment->vc);
298 }
bart5bd9f2d2008-03-03 20:31:58 +0000299 thread_new_segment(drd_tid);
bart6bbefaf2008-04-19 15:16:45 +0000300 s_mutex_segment_creation_count++;
bart5bd9f2d2008-03-03 20:31:58 +0000301
bart9d5b7962008-05-14 12:25:00 +0000302 p->owner = drd_tid;
303 p->acquiry_time_ms = VG_(read_millisecond_timer)();
304 p->acquired_at = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);
sewardjaf44c822007-11-25 14:01:38 +0000305 s_mutex_lock_count++;
306 }
307 else if (p->owner != drd_tid)
308 {
bart3b1ee452008-02-29 19:28:15 +0000309 VG_(message)(Vg_UserMsg,
sewardjaf44c822007-11-25 14:01:38 +0000310 "The impossible happened: mutex 0x%lx is locked"
311 " simultaneously by two threads (recursion count %d,"
312 " owners %d and %d) !",
bart4bb53d82008-02-28 19:06:34 +0000313 p->a1, p->recursion_count, p->owner, drd_tid);
sewardj347eeba2008-01-21 14:19:07 +0000314 p->owner = drd_tid;
sewardjaf44c822007-11-25 14:01:38 +0000315 }
316 p->recursion_count++;
sewardjaf44c822007-11-25 14:01:38 +0000317}
318
bart9d5b7962008-05-14 12:25:00 +0000319/** Update mutex_info state when unlocking the pthread_mutex_t mutex.
320 *
321 * @param mutex Pointer to pthread_mutex_t data structure in the client space.
322 * @param tid ThreadId of the thread calling pthread_mutex_unlock().
323 * @param vc Pointer to the current vector clock of thread tid.
324 *
325 * @return New value of the mutex recursion count.
326 *
327 * @note This function must be called before pthread_mutex_unlock() is called,
328 * or a race condition is triggered !
sewardjaf44c822007-11-25 14:01:38 +0000329 */
bart777f7fe2008-03-02 17:43:18 +0000330void mutex_unlock(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000331{
bartb78312c2008-02-29 11:00:17 +0000332 const DrdThreadId drd_tid = thread_get_running_tid();
333 const ThreadId vg_tid = VG_(get_running_tid)();
sewardjaf44c822007-11-25 14:01:38 +0000334 struct mutex_info* const p = mutex_get(mutex);
335
bart777f7fe2008-03-02 17:43:18 +0000336 if (s_trace_mutex)
sewardjaf44c822007-11-25 14:01:38 +0000337 {
bart3b1ee452008-02-29 19:28:15 +0000338 VG_(message)(Vg_UserMsg,
339 "[%d/%d] mutex_unlock %s 0x%lx rc %d",
340 vg_tid,
341 drd_tid,
bart6b717612008-03-24 09:29:38 +0000342 p ? mutex_get_typename(p) : "(?)",
sewardjaf44c822007-11-25 14:01:38 +0000343 mutex,
barta2b6e1b2008-03-17 18:32:39 +0000344 p ? p->recursion_count : 0);
sewardjaf44c822007-11-25 14:01:38 +0000345 }
346
bart777f7fe2008-03-02 17:43:18 +0000347 if (p == 0 || mutex_type == mutex_type_invalid_mutex)
bartab7a6442008-02-25 19:46:14 +0000348 {
bart6b717612008-03-24 09:29:38 +0000349 not_a_mutex(mutex);
bart5bd9f2d2008-03-03 20:31:58 +0000350 return;
bartab7a6442008-02-25 19:46:14 +0000351 }
352
bart5357fcb2008-02-27 15:46:00 +0000353 if (p->owner == DRD_INVALID_THREADID)
354 {
bart4bb53d82008-02-28 19:06:34 +0000355 MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner };
bart5357fcb2008-02-27 15:46:00 +0000356 VG_(maybe_record_error)(vg_tid,
357 MutexErr,
358 VG_(get_IP)(vg_tid),
359 "Mutex not locked",
360 &MEI);
bart5bd9f2d2008-03-03 20:31:58 +0000361 return;
bart5357fcb2008-02-27 15:46:00 +0000362 }
363
sewardjaf44c822007-11-25 14:01:38 +0000364 tl_assert(p);
bart5357fcb2008-02-27 15:46:00 +0000365 if (p->mutex_type != mutex_type)
366 {
barta2b6e1b2008-03-17 18:32:39 +0000367 VG_(message)(Vg_UserMsg, "??? mutex 0x%lx: type changed from %d into %d",
bart5bd9f2d2008-03-03 20:31:58 +0000368 p->a1, p->mutex_type, mutex_type);
bart5357fcb2008-02-27 15:46:00 +0000369 }
sewardj721ad7b2007-11-30 08:30:29 +0000370 tl_assert(p->mutex_type == mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000371 tl_assert(p->owner != DRD_INVALID_THREADID);
sewardj721ad7b2007-11-30 08:30:29 +0000372
bart777f7fe2008-03-02 17:43:18 +0000373 if (p->owner != drd_tid || p->recursion_count <= 0)
sewardjaf44c822007-11-25 14:01:38 +0000374 {
bart4bb53d82008-02-28 19:06:34 +0000375 MutexErrInfo MEI = { p->a1, p->recursion_count, p->owner };
sewardjaf44c822007-11-25 14:01:38 +0000376 VG_(maybe_record_error)(vg_tid,
377 MutexErr,
378 VG_(get_IP)(vg_tid),
bart777f7fe2008-03-02 17:43:18 +0000379 "Mutex not locked by calling thread",
sewardjaf44c822007-11-25 14:01:38 +0000380 &MEI);
bart777f7fe2008-03-02 17:43:18 +0000381 return;
sewardjaf44c822007-11-25 14:01:38 +0000382 }
bart777f7fe2008-03-02 17:43:18 +0000383 tl_assert(p->recursion_count > 0);
sewardjaf44c822007-11-25 14:01:38 +0000384 p->recursion_count--;
bart777f7fe2008-03-02 17:43:18 +0000385 tl_assert(p->recursion_count >= 0);
sewardj347eeba2008-01-21 14:19:07 +0000386
sewardjaf44c822007-11-25 14:01:38 +0000387 if (p->recursion_count == 0)
388 {
bart9d5b7962008-05-14 12:25:00 +0000389 if (s_mutex_lock_threshold_ms > 0)
390 {
391 ULong held = VG_(read_millisecond_timer)() - p->acquiry_time_ms;
392 if (held > s_mutex_lock_threshold_ms)
393 {
394 HoldtimeErrInfo HEI
395 = { mutex, p->acquired_at, held, s_mutex_lock_threshold_ms };
396 VG_(maybe_record_error)(vg_tid,
397 HoldtimeErr,
398 VG_(get_IP)(vg_tid),
399 "mutex",
400 &HEI);
401 }
402 }
403
sewardjaf44c822007-11-25 14:01:38 +0000404 /* This pthread_mutex_unlock() call really unlocks the mutex. Save the */
405 /* current vector clock of the thread such that it is available when */
406 /* this mutex is locked again. */
sewardjaf44c822007-11-25 14:01:38 +0000407
barta2b6e1b2008-03-17 18:32:39 +0000408 thread_get_latest_segment(&p->last_locked_segment, drd_tid);
sewardjaf44c822007-11-25 14:01:38 +0000409 thread_new_segment(drd_tid);
bart9d5b7962008-05-14 12:25:00 +0000410 p->acquired_at = 0;
bart6bbefaf2008-04-19 15:16:45 +0000411 s_mutex_segment_creation_count++;
sewardjaf44c822007-11-25 14:01:38 +0000412 }
sewardjaf44c822007-11-25 14:01:38 +0000413}
414
415const char* mutex_get_typename(struct mutex_info* const p)
416{
417 tl_assert(p);
sewardj721ad7b2007-11-30 08:30:29 +0000418
sewardj347eeba2008-01-21 14:19:07 +0000419 return mutex_type_name(p->mutex_type);
420}
421
422const char* mutex_type_name(const MutexT mt)
423{
424 switch (mt)
sewardjaf44c822007-11-25 14:01:38 +0000425 {
bart635cb162008-02-28 08:30:43 +0000426 case mutex_type_invalid_mutex:
427 return "invalid mutex";
bart5357fcb2008-02-27 15:46:00 +0000428 case mutex_type_recursive_mutex:
429 return "recursive mutex";
430 case mutex_type_errorcheck_mutex:
431 return "error checking mutex";
432 case mutex_type_default_mutex:
sewardjaf44c822007-11-25 14:01:38 +0000433 return "mutex";
sewardj721ad7b2007-11-30 08:30:29 +0000434 case mutex_type_spinlock:
sewardjaf44c822007-11-25 14:01:38 +0000435 return "spinlock";
436 default:
437 tl_assert(0);
438 }
439 return "?";
440}
441
bart5357fcb2008-02-27 15:46:00 +0000442/** Return true if the specified mutex is locked by any thread. */
443static Bool mutex_is_locked(struct mutex_info* const p)
444{
445 tl_assert(p);
446 return (p->recursion_count > 0);
447}
448
sewardjaf44c822007-11-25 14:01:38 +0000449Bool mutex_is_locked_by(const Addr mutex, const DrdThreadId tid)
450{
451 struct mutex_info* const p = mutex_get(mutex);
sewardjaf44c822007-11-25 14:01:38 +0000452 if (p)
453 {
454 return (p->recursion_count > 0 && p->owner == tid);
455 }
456 return False;
457}
458
sewardjaf44c822007-11-25 14:01:38 +0000459int mutex_get_recursion_count(const Addr mutex)
460{
461 struct mutex_info* const p = mutex_get(mutex);
462 tl_assert(p);
463 return p->recursion_count;
464}
465
466/**
bart301c3112008-02-24 18:22:37 +0000467 * Call this function when thread tid stops to exist, such that the
sewardjaf44c822007-11-25 14:01:38 +0000468 * "last owner" field can be cleared if it still refers to that thread.
sewardjaf44c822007-11-25 14:01:38 +0000469 */
bart301c3112008-02-24 18:22:37 +0000470void mutex_thread_delete(const DrdThreadId tid)
sewardjaf44c822007-11-25 14:01:38 +0000471{
bart4bb53d82008-02-28 19:06:34 +0000472 struct mutex_info* p;
473
bart72b751c2008-03-01 13:44:24 +0000474 clientobj_resetiter();
475 for ( ; (p = &clientobj_next(ClientMutex)->mutex) != 0; )
sewardjaf44c822007-11-25 14:01:38 +0000476 {
bart4bb53d82008-02-28 19:06:34 +0000477 if (p->owner == tid && p->recursion_count > 0)
sewardjaf44c822007-11-25 14:01:38 +0000478 {
bart5357fcb2008-02-27 15:46:00 +0000479 MutexErrInfo MEI
bart4bb53d82008-02-28 19:06:34 +0000480 = { p->a1, p->recursion_count, p->owner };
bart5357fcb2008-02-27 15:46:00 +0000481 VG_(maybe_record_error)(VG_(get_running_tid)(),
482 MutexErr,
483 VG_(get_IP)(VG_(get_running_tid)()),
484 "Mutex still locked at thread exit",
485 &MEI);
sewardjaf44c822007-11-25 14:01:38 +0000486 p->owner = VG_INVALID_THREADID;
487 }
488 }
489}
490
sewardjaf44c822007-11-25 14:01:38 +0000491ULong get_mutex_lock_count(void)
492{
493 return s_mutex_lock_count;
494}
bart6bbefaf2008-04-19 15:16:45 +0000495
496ULong get_mutex_segment_creation_count(void)
497{
498 return s_mutex_segment_creation_count;
499}