blob: 326741656c341c9a756a044ad11f3fcffcff4363 [file] [log] [blame]
sewardjb4112022007-11-09 22:49:28 +00001
2/*--------------------------------------------------------------------*/
3/*--- pthread intercepts for thread checking. ---*/
sewardj3c944452011-09-05 20:39:57 +00004/*--- hg_intercepts.c ---*/
sewardjb4112022007-11-09 22:49:28 +00005/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Helgrind, a Valgrind tool for detecting errors
9 in threaded programs.
10
sewardj9eecbbb2010-05-03 21:37:12 +000011 Copyright (C) 2007-2010 OpenWorks LLP
sewardjb4112022007-11-09 22:49:28 +000012 info@open-works.co.uk
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30
31 Neither the names of the U.S. Department of Energy nor the
32 University of California nor the names of its contributors may be
33 used to endorse or promote products derived from this software
34 without prior written permission.
35*/
36
37/* RUNS ON SIMULATED CPU
38 Interceptors for pthread_* functions, so that tc_main can see
39 significant thread events.
40
41 Important: when adding a function wrapper to this file, remember to
42 add a test case to tc20_verifywrap.c. A common cause of failure is
43 for wrappers to not engage on different distros, and
44 tc20_verifywrap essentially checks that each wrapper is really
45 doing something.
46*/
47
sewardj1c147ff2009-07-26 19:52:06 +000048// DDD: for Darwin, need to have non-"@*"-suffixed versions for all pthread
49// functions that currently have them.
50// Note also, in the comments and code below, all Darwin symbols start
51// with a leading underscore, which is not shown either in the comments
52// nor in the redirect specs.
53
54
sewardjb4112022007-11-09 22:49:28 +000055#include "pub_tool_basics.h"
sewardj38e0cf92008-11-19 10:40:56 +000056#include "pub_tool_redir.h"
sewardjb4112022007-11-09 22:49:28 +000057#include "valgrind.h"
58#include "helgrind.h"
bart870f7452009-12-29 16:56:18 +000059#include "config.h"
sewardjb4112022007-11-09 22:49:28 +000060
61#define TRACE_PTH_FNS 0
62#define TRACE_QT4_FNS 0
63
64
65/*----------------------------------------------------------------*/
66/*--- ---*/
67/*----------------------------------------------------------------*/
68
69#define PTH_FUNC(ret_ty, f, args...) \
njn5f5ef2a2009-05-11 08:01:09 +000070 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args); \
71 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args)
sewardjb4112022007-11-09 22:49:28 +000072
sewardj406bac82010-03-03 23:03:40 +000073// Do a client request. These are macros rather than a functions so
74// as to avoid having an extra frame in stack traces.
75
76// NB: these duplicate definitions in helgrind.h. But here, we
77// can have better typing (Word etc) and assertions, whereas
78// in helgrind.h we can't. Obviously it's important the two
79// sets of definitions are kept in sync.
80
81// nuke the previous definitions
82#undef DO_CREQ_v_W
83#undef DO_CREQ_v_WW
84#undef DO_CREQ_W_WW
85#undef DO_CREQ_v_WWW
sewardjb4112022007-11-09 22:49:28 +000086
87#define DO_CREQ_v_W(_creqF, _ty1F,_arg1F) \
88 do { \
sewardjc7ffc942011-03-28 16:26:42 +000089 Word _arg1; \
sewardjb4112022007-11-09 22:49:28 +000090 assert(sizeof(_ty1F) == sizeof(Word)); \
91 _arg1 = (Word)(_arg1F); \
bart575ce8e2011-05-15 07:04:03 +000092 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, (_creqF), \
sewardjb4112022007-11-09 22:49:28 +000093 _arg1, 0,0,0,0); \
94 } while (0)
95
96#define DO_CREQ_v_WW(_creqF, _ty1F,_arg1F, _ty2F,_arg2F) \
97 do { \
sewardjc7ffc942011-03-28 16:26:42 +000098 Word _arg1, _arg2; \
sewardjb4112022007-11-09 22:49:28 +000099 assert(sizeof(_ty1F) == sizeof(Word)); \
100 assert(sizeof(_ty2F) == sizeof(Word)); \
101 _arg1 = (Word)(_arg1F); \
102 _arg2 = (Word)(_arg2F); \
bart575ce8e2011-05-15 07:04:03 +0000103 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, (_creqF), \
sewardjb4112022007-11-09 22:49:28 +0000104 _arg1,_arg2,0,0,0); \
105 } while (0)
106
sewardjc7ffc942011-03-28 16:26:42 +0000107#define DO_CREQ_W_WW(_resF, _creqF, _ty1F,_arg1F, \
108 _ty2F,_arg2F) \
sewardjb4112022007-11-09 22:49:28 +0000109 do { \
110 Word _res, _arg1, _arg2; \
111 assert(sizeof(_ty1F) == sizeof(Word)); \
112 assert(sizeof(_ty2F) == sizeof(Word)); \
113 _arg1 = (Word)(_arg1F); \
114 _arg2 = (Word)(_arg2F); \
bart575ce8e2011-05-15 07:04:03 +0000115 _res = VALGRIND_DO_CLIENT_REQUEST_EXPR(2, \
sewardjb4112022007-11-09 22:49:28 +0000116 (_creqF), \
117 _arg1,_arg2,0,0,0); \
118 _resF = _res; \
119 } while (0)
120
121#define DO_CREQ_v_WWW(_creqF, _ty1F,_arg1F, \
sewardj1c147ff2009-07-26 19:52:06 +0000122 _ty2F,_arg2F, _ty3F, _arg3F) \
sewardjb4112022007-11-09 22:49:28 +0000123 do { \
sewardjc7ffc942011-03-28 16:26:42 +0000124 Word _arg1, _arg2, _arg3; \
sewardjb4112022007-11-09 22:49:28 +0000125 assert(sizeof(_ty1F) == sizeof(Word)); \
126 assert(sizeof(_ty2F) == sizeof(Word)); \
127 assert(sizeof(_ty3F) == sizeof(Word)); \
128 _arg1 = (Word)(_arg1F); \
129 _arg2 = (Word)(_arg2F); \
130 _arg3 = (Word)(_arg3F); \
bart575ce8e2011-05-15 07:04:03 +0000131 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, (_creqF), \
sewardjb4112022007-11-09 22:49:28 +0000132 _arg1,_arg2,_arg3,0,0); \
133 } while (0)
134
135
136#define DO_PthAPIerror(_fnnameF, _errF) \
137 do { \
138 char* _fnname = (char*)(_fnnameF); \
sewardj1c147ff2009-07-26 19:52:06 +0000139 long _err = (long)(int)(_errF); \
sewardjb4112022007-11-09 22:49:28 +0000140 char* _errstr = lame_strerror(_err); \
141 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTH_API_ERROR, \
142 char*,_fnname, \
143 long,_err, char*,_errstr); \
144 } while (0)
145
146
147/* Needed for older glibcs (2.3 and older, at least) who don't
148 otherwise "know" about pthread_rwlock_anything or about
149 PTHREAD_MUTEX_RECURSIVE (amongst things). */
150#define _GNU_SOURCE 1
151
152#include <stdio.h>
153#include <assert.h>
154#include <errno.h>
155#include <pthread.h>
156
157
158/* A lame version of strerror which doesn't use the real libc
159 strerror_r, since using the latter just generates endless more
160 threading errors (glibc goes off and does tons of crap w.r.t.
161 locales etc) */
162static char* lame_strerror ( long err )
163{ switch (err) {
164 case EPERM: return "EPERM: Operation not permitted";
165 case ENOENT: return "ENOENT: No such file or directory";
166 case ESRCH: return "ESRCH: No such process";
167 case EINTR: return "EINTR: Interrupted system call";
168 case EBADF: return "EBADF: Bad file number";
169 case EAGAIN: return "EAGAIN: Try again";
170 case ENOMEM: return "ENOMEM: Out of memory";
171 case EACCES: return "EACCES: Permission denied";
172 case EFAULT: return "EFAULT: Bad address";
173 case EEXIST: return "EEXIST: File exists";
174 case EINVAL: return "EINVAL: Invalid argument";
175 case EMFILE: return "EMFILE: Too many open files";
176 case ENOSYS: return "ENOSYS: Function not implemented";
177 case EOVERFLOW: return "EOVERFLOW: Value too large "
178 "for defined data type";
179 case EBUSY: return "EBUSY: Device or resource busy";
180 case ETIMEDOUT: return "ETIMEDOUT: Connection timed out";
181 case EDEADLK: return "EDEADLK: Resource deadlock would occur";
182 case EOPNOTSUPP: return "EOPNOTSUPP: Operation not supported on "
183 "transport endpoint"; /* honest, guv */
184 default: return "tc_intercepts.c: lame_strerror(): "
185 "unhandled case -- please fix me!";
186 }
187}
188
189
190/*----------------------------------------------------------------*/
191/*--- pthread_create, pthread_join, pthread_exit ---*/
192/*----------------------------------------------------------------*/
193
sewardjb4112022007-11-09 22:49:28 +0000194static void* mythread_wrapper ( void* xargsV )
195{
bart31277bf2008-07-29 17:04:31 +0000196 volatile Word* xargs = (volatile Word*) xargsV;
sewardjb4112022007-11-09 22:49:28 +0000197 void*(*fn)(void*) = (void*(*)(void*))xargs[0];
198 void* arg = (void*)xargs[1];
199 pthread_t me = pthread_self();
200 /* Tell the tool what my pthread_t is. */
201 DO_CREQ_v_W(_VG_USERREQ__HG_SET_MY_PTHREAD_T, pthread_t,me);
202 /* allow the parent to proceed. We can't let it proceed until
203 we're ready because (1) we need to make sure it doesn't exit and
204 hence deallocate xargs[] while we still need it, and (2) we
205 don't want either parent nor child to proceed until the tool has
sewardjf38a74e2010-04-12 19:53:05 +0000206 been notified of the child's pthread_t.
207
208 Note that parent and child access args[] without a lock,
209 effectively using args[2] as a spinlock in order to get the
210 parent to wait until the child passes this point. The parent
211 disables checking on xargs[] before creating the child and
212 re-enables it once the child goes past this point, so the user
213 never sees the race. The previous approach (suppressing the
214 resulting error) was flawed, because it could leave shadow
215 memory for args[] in a state in which subsequent use of it by
216 the parent would report further races. */
sewardjb4112022007-11-09 22:49:28 +0000217 xargs[2] = 0;
218 /* Now we can no longer safely use xargs[]. */
219 return (void*) fn( (void*)arg );
220}
221
sewardj1c147ff2009-07-26 19:52:06 +0000222//-----------------------------------------------------------
223// glibc: pthread_create@GLIBC_2.0
224// glibc: pthread_create@@GLIBC_2.1
225// glibc: pthread_create@@GLIBC_2.2.5
226// darwin: pthread_create
227// darwin: pthread_create_suspended_np (trapped)
njnf76d27a2009-05-28 01:53:07 +0000228//
sewardj28a7f7d2009-07-26 20:15:37 +0000229/* ensure this has its own frame, so as to make it more distinguishable
230 in suppressions */
231__attribute__((noinline))
njnf76d27a2009-05-28 01:53:07 +0000232static int pthread_create_WRK(pthread_t *thread, const pthread_attr_t *attr,
233 void *(*start) (void *), void *arg)
sewardjb4112022007-11-09 22:49:28 +0000234{
235 int ret;
236 OrigFn fn;
237 volatile Word xargs[3];
238
239 VALGRIND_GET_ORIG_FN(fn);
240 if (TRACE_PTH_FNS) {
241 fprintf(stderr, "<< pthread_create wrapper"); fflush(stderr);
242 }
243 xargs[0] = (Word)start;
244 xargs[1] = (Word)arg;
245 xargs[2] = 1; /* serves as a spinlock -- sigh */
sewardjf38a74e2010-04-12 19:53:05 +0000246 /* Disable checking on the spinlock and the two words used to
247 convey args to the child. Basically we need to make it appear
248 as if the child never accessed this area, since merely
249 suppressing the resulting races does not address the issue that
250 that piece of the parent's stack winds up in the "wrong" state
251 and therefore may give rise to mysterious races when the parent
252 comes to re-use this piece of stack in some other frame. */
253 VALGRIND_HG_DISABLE_CHECKING(&xargs, sizeof(xargs));
sewardjb4112022007-11-09 22:49:28 +0000254
255 CALL_FN_W_WWWW(ret, fn, thread,attr,mythread_wrapper,&xargs[0]);
256
257 if (ret == 0) {
258 /* we have to wait for the child to notify the tool of its
259 pthread_t before continuing */
260 while (xargs[2] != 0) {
sewardjeafad3b2007-11-18 01:16:52 +0000261 /* Do nothing. We need to spin until the child writes to
262 xargs[2]. However, that can lead to starvation in the
263 child and very long delays (eg, tc19_shadowmem on
264 ppc64-linux Fedora Core 6). So yield the cpu if we can,
265 to let the child run at the earliest available
266 opportunity. */
267 sched_yield();
sewardjb4112022007-11-09 22:49:28 +0000268 }
269 } else {
270 DO_PthAPIerror( "pthread_create", ret );
271 }
272
sewardjf38a74e2010-04-12 19:53:05 +0000273 /* Reenable checking on the area previously used to communicate
274 with the child. */
275 VALGRIND_HG_ENABLE_CHECKING(&xargs, sizeof(xargs));
276
sewardjb4112022007-11-09 22:49:28 +0000277 if (TRACE_PTH_FNS) {
278 fprintf(stderr, " :: pth_create -> %d >>\n", ret);
279 }
280 return ret;
281}
sewardj1c147ff2009-07-26 19:52:06 +0000282#if defined(VGO_linux)
283 PTH_FUNC(int, pthreadZucreateZAZa, // pthread_create@*
284 pthread_t *thread, const pthread_attr_t *attr,
285 void *(*start) (void *), void *arg) {
286 return pthread_create_WRK(thread, attr, start, arg);
287 }
288#elif defined(VGO_darwin)
289 PTH_FUNC(int, pthreadZucreate, // pthread_create
290 pthread_t *thread, const pthread_attr_t *attr,
291 void *(*start) (void *), void *arg) {
292 return pthread_create_WRK(thread, attr, start, arg);
293 }
294 PTH_FUNC(int, pthreadZucreateZuZa, // pthread_create_*
295 pthread_t *thread, const pthread_attr_t *attr,
296 void *(*start) (void *), void *arg) {
297 // trap anything else
298 assert(0);
299 }
300#else
301# error "Unsupported OS"
302#endif
sewardjb4112022007-11-09 22:49:28 +0000303
sewardj1c147ff2009-07-26 19:52:06 +0000304
305//-----------------------------------------------------------
306// glibc: pthread_join
307// darwin: pthread_join
308// darwin: pthread_join$NOCANCEL$UNIX2003
309// darwin pthread_join$UNIX2003
310static int pthread_join_WRK(pthread_t thread, void** value_pointer)
sewardjb4112022007-11-09 22:49:28 +0000311{
312 int ret;
313 OrigFn fn;
314 VALGRIND_GET_ORIG_FN(fn);
315 if (TRACE_PTH_FNS) {
316 fprintf(stderr, "<< pthread_join wrapper"); fflush(stderr);
317 }
318
319 CALL_FN_W_WW(ret, fn, thread,value_pointer);
320
321 /* At least with NPTL as the thread library, this is safe because
322 it is guaranteed (by NPTL) that the joiner will completely gone
323 before pthread_join (the original) returns. See email below.*/
324 if (ret == 0 /*success*/) {
325 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_JOIN_POST, pthread_t,thread);
326 } else {
327 DO_PthAPIerror( "pthread_join", ret );
328 }
329
330 if (TRACE_PTH_FNS) {
331 fprintf(stderr, " :: pth_join -> %d >>\n", ret);
332 }
333 return ret;
334}
sewardj1c147ff2009-07-26 19:52:06 +0000335#if defined(VGO_linux)
336 PTH_FUNC(int, pthreadZujoin, // pthread_join
337 pthread_t thread, void** value_pointer) {
338 return pthread_join_WRK(thread, value_pointer);
339 }
340#elif defined(VGO_darwin)
341 PTH_FUNC(int, pthreadZujoinZa, // pthread_join*
342 pthread_t thread, void** value_pointer) {
343 return pthread_join_WRK(thread, value_pointer);
344 }
345#else
346# error "Unsupported OS"
347#endif
348
sewardjb4112022007-11-09 22:49:28 +0000349
350/* Behaviour of pthread_join on NPTL:
351
352Me:
353I have a question re the NPTL pthread_join implementation.
354
355 Suppose I am the thread 'stayer'.
356
357 If I call pthread_join(quitter), is it guaranteed that the
358 thread 'quitter' has really exited before pthread_join returns?
359
360 IOW, is it guaranteed that 'quitter' will not execute any further
361 instructions after pthread_join returns?
362
363I believe this is true based on the following analysis of
364glibc-2.5 sources. However am not 100% sure and would appreciate
365confirmation.
366
367 'quitter' will be running start_thread() in nptl/pthread_create.c
368
369 The last action of start_thread() is to exit via
370 __exit_thread_inline(0), which simply does sys_exit
371 (nptl/pthread_create.c:403)
372
373 'stayer' meanwhile is waiting for lll_wait_tid (pd->tid)
374 (call at nptl/pthread_join.c:89)
375
376 As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536,
377 lll_wait_tid will not return until kernel notifies via futex
378 wakeup that 'quitter' has terminated.
379
380 Hence pthread_join cannot return until 'quitter' really has
381 completely disappeared.
382
383Drepper:
384> As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536,
385> lll_wait_tid will not return until kernel notifies via futex
386> wakeup that 'quitter' has terminated.
387That's the key. The kernel resets the TID field after the thread is
388done. No way the joiner can return before the thread is gone.
389*/
390
391
392/*----------------------------------------------------------------*/
393/*--- pthread_mutex_t functions ---*/
394/*----------------------------------------------------------------*/
395
396/* Handled: pthread_mutex_init pthread_mutex_destroy
397 pthread_mutex_lock
398 pthread_mutex_trylock pthread_mutex_timedlock
399 pthread_mutex_unlock
sewardjb4112022007-11-09 22:49:28 +0000400*/
401
sewardj1c147ff2009-07-26 19:52:06 +0000402//-----------------------------------------------------------
403// glibc: pthread_mutex_init
404// darwin: pthread_mutex_init
sewardjb4112022007-11-09 22:49:28 +0000405PTH_FUNC(int, pthreadZumutexZuinit, // pthread_mutex_init
406 pthread_mutex_t *mutex,
407 pthread_mutexattr_t* attr)
408{
409 int ret;
410 long mbRec;
411 OrigFn fn;
412 VALGRIND_GET_ORIG_FN(fn);
413 if (TRACE_PTH_FNS) {
414 fprintf(stderr, "<< pthread_mxinit %p", mutex); fflush(stderr);
415 }
416
417 mbRec = 0;
418 if (attr) {
419 int ty, zzz;
420 zzz = pthread_mutexattr_gettype(attr, &ty);
421 if (zzz == 0 && ty == PTHREAD_MUTEX_RECURSIVE)
422 mbRec = 1;
423 }
424
425 CALL_FN_W_WW(ret, fn, mutex,attr);
426
427 if (ret == 0 /*success*/) {
428 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST,
429 pthread_mutex_t*,mutex, long,mbRec);
430 } else {
431 DO_PthAPIerror( "pthread_mutex_init", ret );
432 }
433
434 if (TRACE_PTH_FNS) {
435 fprintf(stderr, " :: mxinit -> %d >>\n", ret);
436 }
437 return ret;
438}
439
440
sewardj1c147ff2009-07-26 19:52:06 +0000441//-----------------------------------------------------------
442// glibc: pthread_mutex_destroy
443// darwin: pthread_mutex_destroy
sewardjb4112022007-11-09 22:49:28 +0000444PTH_FUNC(int, pthreadZumutexZudestroy, // pthread_mutex_destroy
445 pthread_mutex_t *mutex)
446{
447 int ret;
448 OrigFn fn;
449 VALGRIND_GET_ORIG_FN(fn);
450 if (TRACE_PTH_FNS) {
451 fprintf(stderr, "<< pthread_mxdestroy %p", mutex); fflush(stderr);
452 }
453
454 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE,
455 pthread_mutex_t*,mutex);
456
457 CALL_FN_W_W(ret, fn, mutex);
458
459 if (ret != 0) {
460 DO_PthAPIerror( "pthread_mutex_destroy", ret );
461 }
462
463 if (TRACE_PTH_FNS) {
464 fprintf(stderr, " :: mxdestroy -> %d >>\n", ret);
465 }
466 return ret;
467}
468
469
sewardj1c147ff2009-07-26 19:52:06 +0000470//-----------------------------------------------------------
471// glibc: pthread_mutex_lock
472// darwin: pthread_mutex_lock
sewardjb4112022007-11-09 22:49:28 +0000473PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock
474 pthread_mutex_t *mutex)
475{
476 int ret;
477 OrigFn fn;
478 VALGRIND_GET_ORIG_FN(fn);
479 if (TRACE_PTH_FNS) {
480 fprintf(stderr, "<< pthread_mxlock %p", mutex); fflush(stderr);
481 }
482
483 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
484 pthread_mutex_t*,mutex, long,0/*!isTryLock*/);
485
486 CALL_FN_W_W(ret, fn, mutex);
487
488 /* There's a hole here: libpthread now knows the lock is locked,
489 but the tool doesn't, so some other thread could run and detect
490 that the lock has been acquired by someone (this thread). Does
491 this matter? Not sure, but I don't think so. */
492
493 if (ret == 0 /*success*/) {
494 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
495 pthread_mutex_t*,mutex);
496 } else {
497 DO_PthAPIerror( "pthread_mutex_lock", ret );
498 }
499
500 if (TRACE_PTH_FNS) {
501 fprintf(stderr, " :: mxlock -> %d >>\n", ret);
502 }
503 return ret;
504}
505
506
sewardj1c147ff2009-07-26 19:52:06 +0000507//-----------------------------------------------------------
508// glibc: pthread_mutex_trylock
509// darwin: pthread_mutex_trylock
510//
sewardjb4112022007-11-09 22:49:28 +0000511// pthread_mutex_trylock. The handling needed here is very similar
512// to that for pthread_mutex_lock, except that we need to tell
513// the pre-lock creq that this is a trylock-style operation, and
514// therefore not to complain if the lock is nonrecursive and
515// already locked by this thread -- because then it'll just fail
516// immediately with EBUSY.
517PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock
518 pthread_mutex_t *mutex)
519{
520 int ret;
521 OrigFn fn;
522 VALGRIND_GET_ORIG_FN(fn);
523 if (TRACE_PTH_FNS) {
524 fprintf(stderr, "<< pthread_mxtrylock %p", mutex); fflush(stderr);
525 }
526
527 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
528 pthread_mutex_t*,mutex, long,1/*isTryLock*/);
529
530 CALL_FN_W_W(ret, fn, mutex);
531
532 /* There's a hole here: libpthread now knows the lock is locked,
533 but the tool doesn't, so some other thread could run and detect
534 that the lock has been acquired by someone (this thread). Does
535 this matter? Not sure, but I don't think so. */
536
537 if (ret == 0 /*success*/) {
538 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
539 pthread_mutex_t*,mutex);
540 } else {
541 if (ret != EBUSY)
542 DO_PthAPIerror( "pthread_mutex_trylock", ret );
543 }
544
545 if (TRACE_PTH_FNS) {
546 fprintf(stderr, " :: mxtrylock -> %d >>\n", ret);
547 }
548 return ret;
549}
550
551
sewardj1c147ff2009-07-26 19:52:06 +0000552//-----------------------------------------------------------
553// glibc: pthread_mutex_timedlock
554// darwin: (doesn't appear to exist)
555//
sewardjb4112022007-11-09 22:49:28 +0000556// pthread_mutex_timedlock. Identical logic to pthread_mutex_trylock.
557PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock
sewardj1c147ff2009-07-26 19:52:06 +0000558 pthread_mutex_t *mutex,
sewardjb4112022007-11-09 22:49:28 +0000559 void* timeout)
560{
561 int ret;
562 OrigFn fn;
563 VALGRIND_GET_ORIG_FN(fn);
564 if (TRACE_PTH_FNS) {
565 fprintf(stderr, "<< pthread_mxtimedlock %p %p", mutex, timeout);
566 fflush(stderr);
567 }
568
569 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
570 pthread_mutex_t*,mutex, long,1/*isTryLock-ish*/);
571
572 CALL_FN_W_WW(ret, fn, mutex,timeout);
573
574 /* There's a hole here: libpthread now knows the lock is locked,
575 but the tool doesn't, so some other thread could run and detect
576 that the lock has been acquired by someone (this thread). Does
577 this matter? Not sure, but I don't think so. */
578
579 if (ret == 0 /*success*/) {
580 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
581 pthread_mutex_t*,mutex);
582 } else {
583 if (ret != ETIMEDOUT)
584 DO_PthAPIerror( "pthread_mutex_timedlock", ret );
585 }
586
587 if (TRACE_PTH_FNS) {
588 fprintf(stderr, " :: mxtimedlock -> %d >>\n", ret);
589 }
590 return ret;
591}
592
593
sewardj1c147ff2009-07-26 19:52:06 +0000594//-----------------------------------------------------------
595// glibc: pthread_mutex_unlock
596// darwin: pthread_mutex_unlock
sewardjb4112022007-11-09 22:49:28 +0000597PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock
598 pthread_mutex_t *mutex)
599{
600 int ret;
601 OrigFn fn;
602 VALGRIND_GET_ORIG_FN(fn);
603
604 if (TRACE_PTH_FNS) {
605 fprintf(stderr, "<< pthread_mxunlk %p", mutex); fflush(stderr);
606 }
607
608 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
609 pthread_mutex_t*,mutex);
610
611 CALL_FN_W_W(ret, fn, mutex);
612
613 if (ret == 0 /*success*/) {
614 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST,
615 pthread_mutex_t*,mutex);
616 } else {
617 DO_PthAPIerror( "pthread_mutex_unlock", ret );
618 }
619
620 if (TRACE_PTH_FNS) {
621 fprintf(stderr, " mxunlk -> %d >>\n", ret);
622 }
623 return ret;
624}
625
626
627/*----------------------------------------------------------------*/
628/*--- pthread_cond_t functions ---*/
629/*----------------------------------------------------------------*/
630
631/* Handled: pthread_cond_wait pthread_cond_timedwait
632 pthread_cond_signal pthread_cond_broadcast
sewardjf98e1c02008-10-25 16:22:41 +0000633 pthread_cond_destroy
sewardjb4112022007-11-09 22:49:28 +0000634
sewardjf98e1c02008-10-25 16:22:41 +0000635 Unhandled: pthread_cond_init
636 -- is this important?
sewardjb4112022007-11-09 22:49:28 +0000637*/
638
sewardj1c147ff2009-07-26 19:52:06 +0000639//-----------------------------------------------------------
640// glibc: pthread_cond_wait@GLIBC_2.2.5
641// glibc: pthread_cond_wait@@GLIBC_2.3.2
642// darwin: pthread_cond_wait
643// darwin: pthread_cond_wait$NOCANCEL$UNIX2003
644// darwin: pthread_cond_wait$UNIX2003
645//
646static int pthread_cond_wait_WRK(pthread_cond_t* cond,
647 pthread_mutex_t* mutex)
sewardjb4112022007-11-09 22:49:28 +0000648{
649 int ret;
650 OrigFn fn;
651 unsigned long mutex_is_valid;
652
653 VALGRIND_GET_ORIG_FN(fn);
654
655 if (TRACE_PTH_FNS) {
656 fprintf(stderr, "<< pthread_cond_wait %p %p", cond, mutex);
657 fflush(stderr);
658 }
659
660 /* Tell the tool a cond-wait is about to happen, so it can check
661 for bogus argument values. In return it tells us whether it
662 thinks the mutex is valid or not. */
663 DO_CREQ_W_WW(mutex_is_valid,
664 _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE,
665 pthread_cond_t*,cond, pthread_mutex_t*,mutex);
666 assert(mutex_is_valid == 1 || mutex_is_valid == 0);
667
668 /* Tell the tool we're about to drop the mutex. This reflects the
669 fact that in a cond_wait, we show up holding the mutex, and the
670 call atomically drops the mutex and waits for the cv to be
671 signalled. */
672 if (mutex_is_valid) {
673 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
674 pthread_mutex_t*,mutex);
675 }
676
677 CALL_FN_W_WW(ret, fn, cond,mutex);
678
679 /* these conditionals look stupid, but compare w/ same logic for
680 pthread_cond_timedwait below */
681 if (ret == 0 && mutex_is_valid) {
682 /* and now we have the mutex again */
683 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
684 pthread_mutex_t*,mutex);
685 }
686
687 if (ret == 0 && mutex_is_valid) {
688 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST,
689 pthread_cond_t*,cond, pthread_mutex_t*,mutex);
690 }
691
692 if (ret != 0) {
693 DO_PthAPIerror( "pthread_cond_wait", ret );
694 }
695
696 if (TRACE_PTH_FNS) {
697 fprintf(stderr, " cowait -> %d >>\n", ret);
698 }
699
700 return ret;
701}
sewardj1c147ff2009-07-26 19:52:06 +0000702#if defined(VGO_linux)
703 PTH_FUNC(int, pthreadZucondZuwaitZAZa, // pthread_cond_wait@*
704 pthread_cond_t* cond, pthread_mutex_t* mutex) {
705 return pthread_cond_wait_WRK(cond, mutex);
706 }
707#elif defined(VGO_darwin)
708 PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait*
709 pthread_cond_t* cond, pthread_mutex_t* mutex) {
710 return pthread_cond_wait_WRK(cond, mutex);
711 }
712#else
713# error "Unsupported OS"
714#endif
sewardjb4112022007-11-09 22:49:28 +0000715
716
sewardj1c147ff2009-07-26 19:52:06 +0000717//-----------------------------------------------------------
718// glibc: pthread_cond_timedwait@@GLIBC_2.3.2
719// glibc: pthread_cond_timedwait@GLIBC_2.2.5
720// glibc: pthread_cond_timedwait@GLIBC_2.0
721// darwin: pthread_cond_timedwait
722// darwin: pthread_cond_timedwait$NOCANCEL$UNIX2003
723// darwin: pthread_cond_timedwait$UNIX2003
724// darwin: pthread_cond_timedwait_relative_np (trapped)
725//
726static int pthread_cond_timedwait_WRK(pthread_cond_t* cond,
727 pthread_mutex_t* mutex,
728 struct timespec* abstime)
sewardjb4112022007-11-09 22:49:28 +0000729{
730 int ret;
731 OrigFn fn;
732 unsigned long mutex_is_valid;
733 VALGRIND_GET_ORIG_FN(fn);
734
735 if (TRACE_PTH_FNS) {
736 fprintf(stderr, "<< pthread_cond_timedwait %p %p %p",
737 cond, mutex, abstime);
738 fflush(stderr);
739 }
740
741 /* Tell the tool a cond-wait is about to happen, so it can check
742 for bogus argument values. In return it tells us whether it
743 thinks the mutex is valid or not. */
744 DO_CREQ_W_WW(mutex_is_valid,
745 _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE,
746 pthread_cond_t*,cond, pthread_mutex_t*,mutex);
747 assert(mutex_is_valid == 1 || mutex_is_valid == 0);
748
749 /* Tell the tool we're about to drop the mutex. This reflects the
750 fact that in a cond_wait, we show up holding the mutex, and the
751 call atomically drops the mutex and waits for the cv to be
752 signalled. */
753 if (mutex_is_valid) {
754 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
755 pthread_mutex_t*,mutex);
756 }
757
758 CALL_FN_W_WWW(ret, fn, cond,mutex,abstime);
759
760 if ((ret == 0 || ret == ETIMEDOUT) && mutex_is_valid) {
761 /* and now we have the mutex again */
762 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
763 pthread_mutex_t*,mutex);
764 }
765
766 if (ret == 0 && mutex_is_valid) {
767 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST,
768 pthread_cond_t*,cond, pthread_mutex_t*,mutex);
769 }
770
771 if (ret != 0 && ret != ETIMEDOUT) {
772 DO_PthAPIerror( "pthread_cond_timedwait", ret );
773 }
774
775 if (TRACE_PTH_FNS) {
776 fprintf(stderr, " cotimedwait -> %d >>\n", ret);
777 }
778
779 return ret;
780}
sewardj1c147ff2009-07-26 19:52:06 +0000781#if defined(VGO_linux)
782 PTH_FUNC(int, pthreadZucondZutimedwaitZAZa, // pthread_cond_timedwait@*
783 pthread_cond_t* cond, pthread_mutex_t* mutex,
784 struct timespec* abstime) {
785 return pthread_cond_timedwait_WRK(cond, mutex, abstime);
786 }
787#elif defined(VGO_darwin)
788 PTH_FUNC(int, pthreadZucondZutimedwait, // pthread_cond_timedwait
789 pthread_cond_t* cond, pthread_mutex_t* mutex,
790 struct timespec* abstime) {
791 return pthread_cond_timedwait_WRK(cond, mutex, abstime);
792 }
793 PTH_FUNC(int, pthreadZucondZutimedwaitZDZa, // pthread_cond_timedwait$*
794 pthread_cond_t* cond, pthread_mutex_t* mutex,
795 struct timespec* abstime) {
796 return pthread_cond_timedwait_WRK(cond, mutex, abstime);
797 }
798 PTH_FUNC(int, pthreadZucondZutimedwaitZuZa, // pthread_cond_timedwait_*
799 pthread_cond_t* cond, pthread_mutex_t* mutex,
800 struct timespec* abstime) {
801 assert(0);
802 }
803#else
804# error "Unsupported OS"
805#endif
sewardjb4112022007-11-09 22:49:28 +0000806
807
sewardj1c147ff2009-07-26 19:52:06 +0000808//-----------------------------------------------------------
809// glibc: pthread_cond_signal@GLIBC_2.0
810// glibc: pthread_cond_signal@GLIBC_2.2.5
811// glibc: pthread_cond_signal@@GLIBC_2.3.2
812// darwin: pthread_cond_signal
813// darwin: pthread_cond_signal_thread_np (don't intercept this)
814//
815static int pthread_cond_signal_WRK(pthread_cond_t* cond)
sewardjb4112022007-11-09 22:49:28 +0000816{
817 int ret;
818 OrigFn fn;
819 VALGRIND_GET_ORIG_FN(fn);
820
821 if (TRACE_PTH_FNS) {
822 fprintf(stderr, "<< pthread_cond_signal %p", cond);
823 fflush(stderr);
824 }
825
826 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_SIGNAL_PRE,
827 pthread_cond_t*,cond);
828
829 CALL_FN_W_W(ret, fn, cond);
830
831 if (ret != 0) {
832 DO_PthAPIerror( "pthread_cond_signal", ret );
833 }
834
835 if (TRACE_PTH_FNS) {
836 fprintf(stderr, " cosig -> %d >>\n", ret);
837 }
838
839 return ret;
840}
sewardj1c147ff2009-07-26 19:52:06 +0000841#if defined(VGO_linux)
842 PTH_FUNC(int, pthreadZucondZusignalZAZa, // pthread_cond_signal@*
843 pthread_cond_t* cond) {
844 return pthread_cond_signal_WRK(cond);
845 }
846#elif defined(VGO_darwin)
847 PTH_FUNC(int, pthreadZucondZusignal, // pthread_cond_signal
848 pthread_cond_t* cond) {
849 return pthread_cond_signal_WRK(cond);
850 }
851#else
852# error "Unsupported OS"
853#endif
sewardjb4112022007-11-09 22:49:28 +0000854
855
sewardj1c147ff2009-07-26 19:52:06 +0000856//-----------------------------------------------------------
857// glibc: pthread_cond_broadcast@GLIBC_2.0
858// glibc: pthread_cond_broadcast@GLIBC_2.2.5
859// glibc: pthread_cond_broadcast@@GLIBC_2.3.2
860// darwin: pthread_cond_broadcast
861//
sewardjb4112022007-11-09 22:49:28 +0000862// Note, this is pretty much identical, from a dependency-graph
863// point of view, with cond_signal, so the code is duplicated.
864// Maybe it should be commoned up.
sewardj1c147ff2009-07-26 19:52:06 +0000865//
866static int pthread_cond_broadcast_WRK(pthread_cond_t* cond)
sewardjb4112022007-11-09 22:49:28 +0000867{
868 int ret;
869 OrigFn fn;
870 VALGRIND_GET_ORIG_FN(fn);
871
872 if (TRACE_PTH_FNS) {
sewardj1c147ff2009-07-26 19:52:06 +0000873 fprintf(stderr, "<< pthread_cond_broadcast %p", cond);
sewardjb4112022007-11-09 22:49:28 +0000874 fflush(stderr);
875 }
876
877 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_BROADCAST_PRE,
878 pthread_cond_t*,cond);
879
880 CALL_FN_W_W(ret, fn, cond);
881
882 if (ret != 0) {
883 DO_PthAPIerror( "pthread_cond_broadcast", ret );
884 }
885
886 if (TRACE_PTH_FNS) {
887 fprintf(stderr, " cobro -> %d >>\n", ret);
888 }
889
890 return ret;
891}
sewardj1c147ff2009-07-26 19:52:06 +0000892#if defined(VGO_linux)
893 PTH_FUNC(int, pthreadZucondZubroadcastZAZa, // pthread_cond_broadcast@*
894 pthread_cond_t* cond) {
895 return pthread_cond_broadcast_WRK(cond);
896 }
897#elif defined(VGO_darwin)
898 PTH_FUNC(int, pthreadZucondZubroadcast, // pthread_cond_broadcast
899 pthread_cond_t* cond) {
900 return pthread_cond_broadcast_WRK(cond);
901 }
902#else
903# error "Unsupported OS"
904#endif
sewardjb4112022007-11-09 22:49:28 +0000905
906
sewardj1c147ff2009-07-26 19:52:06 +0000907//-----------------------------------------------------------
908// glibc: pthread_cond_destroy@@GLIBC_2.3.2
909// glibc: pthread_cond_destroy@GLIBC_2.2.5
910// glibc: pthread_cond_destroy@GLIBC_2.0
911// darwin: pthread_cond_destroy
912//
913static int pthread_cond_destroy_WRK(pthread_cond_t* cond)
sewardjf98e1c02008-10-25 16:22:41 +0000914{
915 int ret;
916 OrigFn fn;
917
918 VALGRIND_GET_ORIG_FN(fn);
919
920 if (TRACE_PTH_FNS) {
921 fprintf(stderr, "<< pthread_cond_destroy %p", cond);
922 fflush(stderr);
923 }
924
925 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_DESTROY_PRE,
926 pthread_cond_t*,cond);
927
928 CALL_FN_W_W(ret, fn, cond);
929
930 if (ret != 0) {
931 DO_PthAPIerror( "pthread_cond_destroy", ret );
932 }
933
934 if (TRACE_PTH_FNS) {
935 fprintf(stderr, " codestr -> %d >>\n", ret);
936 }
937
938 return ret;
939}
sewardj1c147ff2009-07-26 19:52:06 +0000940#if defined(VGO_linux)
941 PTH_FUNC(int, pthreadZucondZudestroyZAZa, // pthread_cond_destroy@*
942 pthread_cond_t* cond) {
943 return pthread_cond_destroy_WRK(cond);
944 }
945#elif defined(VGO_darwin)
946 PTH_FUNC(int, pthreadZucondZudestroy, // pthread_cond_destroy
947 pthread_cond_t* cond) {
948 return pthread_cond_destroy_WRK(cond);
949 }
950#else
951# error "Unsupported OS"
952#endif
sewardjf98e1c02008-10-25 16:22:41 +0000953
954
955/*----------------------------------------------------------------*/
956/*--- pthread_barrier_t functions ---*/
957/*----------------------------------------------------------------*/
958
njnf76d27a2009-05-28 01:53:07 +0000959#if defined(HAVE_PTHREAD_BARRIER_INIT)
960
sewardj9f569b72008-11-13 13:33:09 +0000961/* Handled: pthread_barrier_init
962 pthread_barrier_wait
963 pthread_barrier_destroy
964
965 Unhandled: pthread_barrierattr_destroy
966 pthread_barrierattr_getpshared
967 pthread_barrierattr_init
968 pthread_barrierattr_setpshared
969 -- are these important?
970*/
971
sewardj1c147ff2009-07-26 19:52:06 +0000972//-----------------------------------------------------------
973// glibc: pthread_barrier_init
974// darwin: (doesn't appear to exist)
sewardj9f569b72008-11-13 13:33:09 +0000975PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init
976 pthread_barrier_t* bar,
977 pthread_barrierattr_t* attr, unsigned long count)
sewardjf98e1c02008-10-25 16:22:41 +0000978{
979 int ret;
980 OrigFn fn;
981 VALGRIND_GET_ORIG_FN(fn);
982
983 if (TRACE_PTH_FNS) {
sewardj9f569b72008-11-13 13:33:09 +0000984 fprintf(stderr, "<< pthread_barrier_init %p %p %lu",
985 bar, attr, count);
sewardjf98e1c02008-10-25 16:22:41 +0000986 fflush(stderr);
987 }
988
sewardj406bac82010-03-03 23:03:40 +0000989 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_BARRIER_INIT_PRE,
990 pthread_barrier_t*, bar,
991 unsigned long, count,
992 unsigned long, 0/*!resizable*/);
sewardjf98e1c02008-10-25 16:22:41 +0000993
sewardj9f569b72008-11-13 13:33:09 +0000994 CALL_FN_W_WWW(ret, fn, bar,attr,count);
sewardjf98e1c02008-10-25 16:22:41 +0000995
sewardj9f569b72008-11-13 13:33:09 +0000996 if (ret != 0) {
997 DO_PthAPIerror( "pthread_barrier_init", ret );
998 }
999
1000 if (TRACE_PTH_FNS) {
1001 fprintf(stderr, " pthread_barrier_init -> %d >>\n", ret);
1002 }
1003
1004 return ret;
1005}
1006
1007
sewardj1c147ff2009-07-26 19:52:06 +00001008//-----------------------------------------------------------
1009// glibc: pthread_barrier_wait
1010// darwin: (doesn't appear to exist)
sewardj9f569b72008-11-13 13:33:09 +00001011PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait
1012 pthread_barrier_t* bar)
1013{
1014 int ret;
1015 OrigFn fn;
1016 VALGRIND_GET_ORIG_FN(fn);
1017
1018 if (TRACE_PTH_FNS) {
1019 fprintf(stderr, "<< pthread_barrier_wait %p", bar);
1020 fflush(stderr);
1021 }
1022
1023 /* That this works correctly, and doesn't screw up when a thread
1024 leaving the barrier races round to the front and re-enters while
1025 other threads are still leaving it, is quite subtle. See
1026 comments in the handler for PTHREAD_BARRIER_WAIT_PRE in
1027 hg_main.c. */
1028 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_WAIT_PRE,
1029 pthread_barrier_t*,bar);
1030
1031 CALL_FN_W_W(ret, fn, bar);
1032
1033 if (ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
1034 DO_PthAPIerror( "pthread_barrier_wait", ret );
1035 }
sewardjf98e1c02008-10-25 16:22:41 +00001036
1037 if (TRACE_PTH_FNS) {
1038 fprintf(stderr, " pthread_barrier_wait -> %d >>\n", ret);
1039 }
1040
1041 return ret;
1042}
1043
1044
sewardj1c147ff2009-07-26 19:52:06 +00001045//-----------------------------------------------------------
1046// glibc: pthread_barrier_destroy
1047// darwin: (doesn't appear to exist)
sewardj9f569b72008-11-13 13:33:09 +00001048PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy
1049 pthread_barrier_t* bar)
1050{
1051 int ret;
1052 OrigFn fn;
1053 VALGRIND_GET_ORIG_FN(fn);
1054
1055 if (TRACE_PTH_FNS) {
1056 fprintf(stderr, "<< pthread_barrier_destroy %p", bar);
1057 fflush(stderr);
1058 }
1059
1060 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_DESTROY_PRE,
1061 pthread_barrier_t*,bar);
1062
1063 CALL_FN_W_W(ret, fn, bar);
1064
1065 if (ret != 0) {
1066 DO_PthAPIerror( "pthread_barrier_destroy", ret );
1067 }
1068
1069 if (TRACE_PTH_FNS) {
1070 fprintf(stderr, " pthread_barrier_destroy -> %d >>\n", ret);
1071 }
1072
1073 return ret;
1074}
sewardjf98e1c02008-10-25 16:22:41 +00001075
njnf76d27a2009-05-28 01:53:07 +00001076#endif // defined(HAVE_PTHREAD_BARRIER_INIT)
1077
sewardj5a644da2009-08-11 10:35:58 +00001078
1079/*----------------------------------------------------------------*/
1080/*--- pthread_spinlock_t functions ---*/
1081/*----------------------------------------------------------------*/
1082
1083#if defined(HAVE_PTHREAD_SPIN_LOCK)
1084
1085/* Handled: pthread_spin_init pthread_spin_destroy
1086 pthread_spin_lock pthread_spin_trylock
1087 pthread_spin_unlock
1088
1089 Unhandled:
1090*/
1091
1092/* This is a nasty kludge, in that glibc "knows" that initialising a
1093 spin lock unlocks it, and pthread_spin_{init,unlock} are names for
1094 the same function. Hence we have to have a wrapper which does both
1095 things, without knowing which the user intended to happen. */
1096
1097//-----------------------------------------------------------
1098// glibc: pthread_spin_init
1099// glibc: pthread_spin_unlock
1100// darwin: (doesn't appear to exist)
1101static int pthread_spin_init_or_unlock_WRK(pthread_spinlock_t* lock,
1102 int pshared) {
1103 int ret;
1104 OrigFn fn;
1105 VALGRIND_GET_ORIG_FN(fn);
1106 if (TRACE_PTH_FNS) {
1107 fprintf(stderr, "<< pthread_spin_iORu %p", lock); fflush(stderr);
1108 }
1109
1110 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE,
1111 pthread_spinlock_t*, lock);
1112
1113 CALL_FN_W_WW(ret, fn, lock,pshared);
1114
1115 if (ret == 0 /*success*/) {
1116 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST,
1117 pthread_spinlock_t*,lock);
1118 } else {
1119 DO_PthAPIerror( "pthread_spinlock_{init,unlock}", ret );
1120 }
1121
1122 if (TRACE_PTH_FNS) {
1123 fprintf(stderr, " :: spiniORu -> %d >>\n", ret);
1124 }
1125 return ret;
1126}
1127#if defined(VGO_linux)
1128 PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init
1129 pthread_spinlock_t* lock, int pshared) {
1130 return pthread_spin_init_or_unlock_WRK(lock, pshared);
1131 }
1132 PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock
1133 pthread_spinlock_t* lock) {
1134 /* this is never actually called */
1135 return pthread_spin_init_or_unlock_WRK(lock, 0/*pshared*/);
1136 }
1137#elif defined(VGO_darwin)
1138#else
1139# error "Unsupported OS"
1140#endif
1141
1142
1143//-----------------------------------------------------------
1144// glibc: pthread_spin_destroy
1145// darwin: (doesn't appear to exist)
1146#if defined(VGO_linux)
1147
1148PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy
1149 pthread_spinlock_t* lock)
1150{
1151 int ret;
1152 OrigFn fn;
1153 VALGRIND_GET_ORIG_FN(fn);
1154 if (TRACE_PTH_FNS) {
1155 fprintf(stderr, "<< pthread_spin_destroy %p", lock);
1156 fflush(stderr);
1157 }
1158
1159 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_DESTROY_PRE,
1160 pthread_spinlock_t*,lock);
1161
1162 CALL_FN_W_W(ret, fn, lock);
1163
1164 if (ret != 0) {
1165 DO_PthAPIerror( "pthread_spin_destroy", ret );
1166 }
1167
1168 if (TRACE_PTH_FNS) {
1169 fprintf(stderr, " :: spindestroy -> %d >>\n", ret);
1170 }
1171 return ret;
1172}
1173
1174#elif defined(VGO_darwin)
1175#else
1176# error "Unsupported OS"
1177#endif
1178
1179
1180//-----------------------------------------------------------
1181// glibc: pthread_spin_lock
1182// darwin: (doesn't appear to exist)
1183#if defined(VGO_linux)
1184
1185PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock
1186 pthread_spinlock_t* lock)
1187{
1188 int ret;
1189 OrigFn fn;
1190 VALGRIND_GET_ORIG_FN(fn);
1191 if (TRACE_PTH_FNS) {
1192 fprintf(stderr, "<< pthread_spinlock %p", lock);
1193 fflush(stderr);
1194 }
1195
1196 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE,
1197 pthread_spinlock_t*,lock, long,0/*!isTryLock*/);
1198
1199 CALL_FN_W_W(ret, fn, lock);
1200
1201 /* There's a hole here: libpthread now knows the lock is locked,
1202 but the tool doesn't, so some other thread could run and detect
1203 that the lock has been acquired by someone (this thread). Does
1204 this matter? Not sure, but I don't think so. */
1205
1206 if (ret == 0 /*success*/) {
1207 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST,
1208 pthread_spinlock_t*,lock);
1209 } else {
1210 DO_PthAPIerror( "pthread_spin_lock", ret );
1211 }
1212
1213 if (TRACE_PTH_FNS) {
1214 fprintf(stderr, " :: spinlock -> %d >>\n", ret);
1215 }
1216 return ret;
1217}
1218
1219#elif defined(VGO_darwin)
1220#else
1221# error "Unsupported OS"
1222#endif
1223
1224
1225//-----------------------------------------------------------
1226// glibc: pthread_spin_trylock
1227// darwin: (doesn't appear to exist)
1228#if defined(VGO_linux)
1229
1230PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock
1231 pthread_spinlock_t* lock)
1232{
1233 int ret;
1234 OrigFn fn;
1235 VALGRIND_GET_ORIG_FN(fn);
1236 if (TRACE_PTH_FNS) {
1237 fprintf(stderr, "<< pthread_spin_trylock %p", lock);
1238 fflush(stderr);
1239 }
1240
1241 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE,
1242 pthread_spinlock_t*,lock, long,1/*isTryLock*/);
1243
1244 CALL_FN_W_W(ret, fn, lock);
1245
1246 /* There's a hole here: libpthread now knows the lock is locked,
1247 but the tool doesn't, so some other thread could run and detect
1248 that the lock has been acquired by someone (this thread). Does
1249 this matter? Not sure, but I don't think so. */
1250
1251 if (ret == 0 /*success*/) {
1252 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST,
1253 pthread_spinlock_t*,lock);
1254 } else {
1255 if (ret != EBUSY)
1256 DO_PthAPIerror( "pthread_spin_trylock", ret );
1257 }
1258
1259 if (TRACE_PTH_FNS) {
1260 fprintf(stderr, " :: spin_trylock -> %d >>\n", ret);
1261 }
1262 return ret;
1263}
1264
1265#elif defined(VGO_darwin)
1266#else
1267# error "Unsupported OS"
1268#endif
1269
1270#endif // defined(HAVE_PTHREAD_SPIN_LOCK)
1271
1272
sewardjb4112022007-11-09 22:49:28 +00001273/*----------------------------------------------------------------*/
1274/*--- pthread_rwlock_t functions ---*/
1275/*----------------------------------------------------------------*/
1276
sewardj0c09bf02011-07-11 22:11:58 +00001277/* Android's pthread.h doesn't say anything about rwlocks, hence these
1278 functions have to be conditionally compiled. */
1279#if defined(HAVE_PTHREAD_RWLOCK_T)
1280
sewardjb4112022007-11-09 22:49:28 +00001281/* Handled: pthread_rwlock_init pthread_rwlock_destroy
1282 pthread_rwlock_rdlock
1283 pthread_rwlock_wrlock
1284 pthread_rwlock_unlock
1285
1286 Unhandled: pthread_rwlock_timedrdlock
1287 pthread_rwlock_tryrdlock
1288
1289 pthread_rwlock_timedwrlock
1290 pthread_rwlock_trywrlock
1291*/
1292
sewardj1c147ff2009-07-26 19:52:06 +00001293//-----------------------------------------------------------
1294// glibc: pthread_rwlock_init
1295// darwin: pthread_rwlock_init
1296// darwin: pthread_rwlock_init$UNIX2003
1297static int pthread_rwlock_init_WRK(pthread_rwlock_t *rwl,
1298 pthread_rwlockattr_t* attr)
sewardjb4112022007-11-09 22:49:28 +00001299{
1300 int ret;
1301 OrigFn fn;
1302 VALGRIND_GET_ORIG_FN(fn);
1303 if (TRACE_PTH_FNS) {
1304 fprintf(stderr, "<< pthread_rwl_init %p", rwl); fflush(stderr);
1305 }
1306
1307 CALL_FN_W_WW(ret, fn, rwl,attr);
1308
1309 if (ret == 0 /*success*/) {
1310 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST,
1311 pthread_rwlock_t*,rwl);
1312 } else {
1313 DO_PthAPIerror( "pthread_rwlock_init", ret );
1314 }
1315
1316 if (TRACE_PTH_FNS) {
1317 fprintf(stderr, " :: rwl_init -> %d >>\n", ret);
1318 }
1319 return ret;
1320}
sewardj1c147ff2009-07-26 19:52:06 +00001321#if defined(VGO_linux)
1322 PTH_FUNC(int, pthreadZurwlockZuinit, // pthread_rwlock_init
1323 pthread_rwlock_t *rwl,
1324 pthread_rwlockattr_t* attr) {
1325 return pthread_rwlock_init_WRK(rwl, attr);
1326 }
1327#elif defined(VGO_darwin)
1328 PTH_FUNC(int, pthreadZurwlockZuinitZa, // pthread_rwlock_init*
1329 pthread_rwlock_t *rwl,
1330 pthread_rwlockattr_t* attr) {
1331 return pthread_rwlock_init_WRK(rwl, attr);
1332 }
1333#else
1334# error "Unsupported OS"
1335#endif
sewardjb4112022007-11-09 22:49:28 +00001336
1337
sewardj1c147ff2009-07-26 19:52:06 +00001338//-----------------------------------------------------------
1339// glibc: pthread_rwlock_destroy
1340// darwin: pthread_rwlock_destroy
1341// darwin: pthread_rwlock_destroy$UNIX2003
1342//
1343static int pthread_rwlock_destroy_WRK(pthread_rwlock_t* rwl)
sewardjb4112022007-11-09 22:49:28 +00001344{
1345 int ret;
1346 OrigFn fn;
1347 VALGRIND_GET_ORIG_FN(fn);
1348 if (TRACE_PTH_FNS) {
1349 fprintf(stderr, "<< pthread_rwl_destroy %p", rwl); fflush(stderr);
1350 }
1351
1352 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE,
1353 pthread_rwlock_t*,rwl);
1354
1355 CALL_FN_W_W(ret, fn, rwl);
1356
1357 if (ret != 0) {
1358 DO_PthAPIerror( "pthread_rwlock_destroy", ret );
1359 }
1360
1361 if (TRACE_PTH_FNS) {
1362 fprintf(stderr, " :: rwl_destroy -> %d >>\n", ret);
1363 }
1364 return ret;
1365}
sewardj1c147ff2009-07-26 19:52:06 +00001366#if defined(VGO_linux)
1367 PTH_FUNC(int, pthreadZurwlockZudestroy, // pthread_rwlock_destroy
1368 pthread_rwlock_t *rwl) {
1369 return pthread_rwlock_destroy_WRK(rwl);
1370 }
1371#elif defined(VGO_darwin)
1372 PTH_FUNC(int, pthreadZurwlockZudestroyZa, // pthread_rwlock_destroy*
1373 pthread_rwlock_t *rwl) {
1374 return pthread_rwlock_destroy_WRK(rwl);
1375 }
1376#else
1377# error "Unsupported OS"
1378#endif
sewardjb4112022007-11-09 22:49:28 +00001379
1380
sewardj1c147ff2009-07-26 19:52:06 +00001381//-----------------------------------------------------------
1382// glibc: pthread_rwlock_wrlock
1383// darwin: pthread_rwlock_wrlock
1384// darwin: pthread_rwlock_wrlock$UNIX2003
1385//
1386static int pthread_rwlock_wrlock_WRK(pthread_rwlock_t* rwlock)
sewardjb4112022007-11-09 22:49:28 +00001387{
1388 int ret;
1389 OrigFn fn;
1390 VALGRIND_GET_ORIG_FN(fn);
1391 if (TRACE_PTH_FNS) {
1392 fprintf(stderr, "<< pthread_rwl_wlk %p", rwlock); fflush(stderr);
1393 }
1394
sewardj789c3c52008-02-25 12:10:07 +00001395 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1396 pthread_rwlock_t*,rwlock,
1397 long,1/*isW*/, long,0/*!isTryLock*/);
sewardjb4112022007-11-09 22:49:28 +00001398
1399 CALL_FN_W_W(ret, fn, rwlock);
1400
1401 if (ret == 0 /*success*/) {
1402 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1403 pthread_rwlock_t*,rwlock, long,1/*isW*/);
1404 } else {
1405 DO_PthAPIerror( "pthread_rwlock_wrlock", ret );
1406 }
1407
1408 if (TRACE_PTH_FNS) {
1409 fprintf(stderr, " :: rwl_wlk -> %d >>\n", ret);
1410 }
1411 return ret;
1412}
sewardj1c147ff2009-07-26 19:52:06 +00001413#if defined(VGO_linux)
1414 PTH_FUNC(int, pthreadZurwlockZuwrlock, // pthread_rwlock_wrlock
1415 pthread_rwlock_t* rwlock) {
1416 return pthread_rwlock_wrlock_WRK(rwlock);
1417 }
1418#elif defined(VGO_darwin)
1419 PTH_FUNC(int, pthreadZurwlockZuwrlockZa, // pthread_rwlock_wrlock*
1420 pthread_rwlock_t* rwlock) {
1421 return pthread_rwlock_wrlock_WRK(rwlock);
1422 }
1423#else
1424# error "Unsupported OS"
1425#endif
sewardjb4112022007-11-09 22:49:28 +00001426
1427
sewardj1c147ff2009-07-26 19:52:06 +00001428//-----------------------------------------------------------
1429// glibc: pthread_rwlock_rdlock
1430// darwin: pthread_rwlock_rdlock
1431// darwin: pthread_rwlock_rdlock$UNIX2003
1432//
1433static int pthread_rwlock_rdlock_WRK(pthread_rwlock_t* rwlock)
sewardjb4112022007-11-09 22:49:28 +00001434{
1435 int ret;
1436 OrigFn fn;
1437 VALGRIND_GET_ORIG_FN(fn);
1438 if (TRACE_PTH_FNS) {
1439 fprintf(stderr, "<< pthread_rwl_rlk %p", rwlock); fflush(stderr);
1440 }
1441
sewardj789c3c52008-02-25 12:10:07 +00001442 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1443 pthread_rwlock_t*,rwlock,
1444 long,0/*!isW*/, long,0/*!isTryLock*/);
sewardjb4112022007-11-09 22:49:28 +00001445
1446 CALL_FN_W_W(ret, fn, rwlock);
1447
1448 if (ret == 0 /*success*/) {
1449 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1450 pthread_rwlock_t*,rwlock, long,0/*!isW*/);
1451 } else {
1452 DO_PthAPIerror( "pthread_rwlock_rdlock", ret );
1453 }
1454
1455 if (TRACE_PTH_FNS) {
1456 fprintf(stderr, " :: rwl_rlk -> %d >>\n", ret);
1457 }
1458 return ret;
1459}
sewardj1c147ff2009-07-26 19:52:06 +00001460#if defined(VGO_linux)
1461 PTH_FUNC(int, pthreadZurwlockZurdlock, // pthread_rwlock_rdlock
1462 pthread_rwlock_t* rwlock) {
1463 return pthread_rwlock_rdlock_WRK(rwlock);
1464 }
1465#elif defined(VGO_darwin)
1466 PTH_FUNC(int, pthreadZurwlockZurdlockZa, // pthread_rwlock_rdlock*
1467 pthread_rwlock_t* rwlock) {
1468 return pthread_rwlock_rdlock_WRK(rwlock);
1469 }
1470#else
1471# error "Unsupported OS"
1472#endif
sewardjb4112022007-11-09 22:49:28 +00001473
1474
sewardj1c147ff2009-07-26 19:52:06 +00001475//-----------------------------------------------------------
1476// glibc: pthread_rwlock_trywrlock
1477// darwin: pthread_rwlock_trywrlock
1478// darwin: pthread_rwlock_trywrlock$UNIX2003
1479//
1480static int pthread_rwlock_trywrlock_WRK(pthread_rwlock_t* rwlock)
sewardj789c3c52008-02-25 12:10:07 +00001481{
1482 int ret;
1483 OrigFn fn;
1484 VALGRIND_GET_ORIG_FN(fn);
1485 if (TRACE_PTH_FNS) {
1486 fprintf(stderr, "<< pthread_rwl_trywlk %p", rwlock); fflush(stderr);
1487 }
1488
1489 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1490 pthread_rwlock_t*,rwlock,
1491 long,1/*isW*/, long,1/*isTryLock*/);
1492
1493 CALL_FN_W_W(ret, fn, rwlock);
1494
1495 /* There's a hole here: libpthread now knows the lock is locked,
1496 but the tool doesn't, so some other thread could run and detect
1497 that the lock has been acquired by someone (this thread). Does
1498 this matter? Not sure, but I don't think so. */
1499
1500 if (ret == 0 /*success*/) {
1501 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1502 pthread_rwlock_t*,rwlock, long,1/*isW*/);
1503 } else {
1504 if (ret != EBUSY)
1505 DO_PthAPIerror( "pthread_rwlock_trywrlock", ret );
1506 }
1507
1508 if (TRACE_PTH_FNS) {
1509 fprintf(stderr, " :: rwl_trywlk -> %d >>\n", ret);
1510 }
1511 return ret;
1512}
sewardj1c147ff2009-07-26 19:52:06 +00001513#if defined(VGO_linux)
1514 PTH_FUNC(int, pthreadZurwlockZutrywrlock, // pthread_rwlock_trywrlock
1515 pthread_rwlock_t* rwlock) {
1516 return pthread_rwlock_trywrlock_WRK(rwlock);
1517 }
1518#elif defined(VGO_darwin)
1519 PTH_FUNC(int, pthreadZurwlockZutrywrlockZa, // pthread_rwlock_trywrlock*
1520 pthread_rwlock_t* rwlock) {
1521 return pthread_rwlock_trywrlock_WRK(rwlock);
1522 }
1523#else
1524# error "Unsupported OS"
1525#endif
sewardj789c3c52008-02-25 12:10:07 +00001526
1527
sewardj1c147ff2009-07-26 19:52:06 +00001528//-----------------------------------------------------------
1529// glibc: pthread_rwlock_tryrdlock
1530// darwin: pthread_rwlock_trywrlock
1531// darwin: pthread_rwlock_trywrlock$UNIX2003
1532//
1533static int pthread_rwlock_tryrdlock_WRK(pthread_rwlock_t* rwlock)
sewardj789c3c52008-02-25 12:10:07 +00001534{
1535 int ret;
1536 OrigFn fn;
1537 VALGRIND_GET_ORIG_FN(fn);
1538 if (TRACE_PTH_FNS) {
1539 fprintf(stderr, "<< pthread_rwl_tryrlk %p", rwlock); fflush(stderr);
1540 }
1541
1542 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1543 pthread_rwlock_t*,rwlock,
1544 long,0/*!isW*/, long,1/*isTryLock*/);
1545
1546 CALL_FN_W_W(ret, fn, rwlock);
1547
1548 /* There's a hole here: libpthread now knows the lock is locked,
1549 but the tool doesn't, so some other thread could run and detect
1550 that the lock has been acquired by someone (this thread). Does
1551 this matter? Not sure, but I don't think so. */
1552
1553 if (ret == 0 /*success*/) {
1554 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1555 pthread_rwlock_t*,rwlock, long,0/*!isW*/);
1556 } else {
1557 if (ret != EBUSY)
1558 DO_PthAPIerror( "pthread_rwlock_tryrdlock", ret );
1559 }
1560
1561 if (TRACE_PTH_FNS) {
1562 fprintf(stderr, " :: rwl_tryrlk -> %d >>\n", ret);
1563 }
1564 return ret;
1565}
sewardj1c147ff2009-07-26 19:52:06 +00001566#if defined(VGO_linux)
1567 PTH_FUNC(int, pthreadZurwlockZutryrdlock, // pthread_rwlock_tryrdlock
1568 pthread_rwlock_t* rwlock) {
1569 return pthread_rwlock_tryrdlock_WRK(rwlock);
1570 }
1571#elif defined(VGO_darwin)
1572 PTH_FUNC(int, pthreadZurwlockZutryrdlockZa, // pthread_rwlock_tryrdlock*
1573 pthread_rwlock_t* rwlock) {
1574 return pthread_rwlock_tryrdlock_WRK(rwlock);
1575 }
1576#else
1577# error "Unsupported OS"
1578#endif
sewardj789c3c52008-02-25 12:10:07 +00001579
1580
sewardj1c147ff2009-07-26 19:52:06 +00001581//-----------------------------------------------------------
1582// glibc: pthread_rwlock_unlock
1583// darwin: pthread_rwlock_unlock
1584// darwin: pthread_rwlock_unlock$UNIX2003
1585static int pthread_rwlock_unlock_WRK(pthread_rwlock_t* rwlock)
sewardjb4112022007-11-09 22:49:28 +00001586{
1587 int ret;
1588 OrigFn fn;
1589 VALGRIND_GET_ORIG_FN(fn);
1590 if (TRACE_PTH_FNS) {
1591 fprintf(stderr, "<< pthread_rwl_unlk %p", rwlock); fflush(stderr);
1592 }
1593
1594 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE,
1595 pthread_rwlock_t*,rwlock);
1596
1597 CALL_FN_W_W(ret, fn, rwlock);
1598
1599 if (ret == 0 /*success*/) {
1600 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST,
1601 pthread_rwlock_t*,rwlock);
1602 } else {
1603 DO_PthAPIerror( "pthread_rwlock_unlock", ret );
1604 }
1605
1606 if (TRACE_PTH_FNS) {
1607 fprintf(stderr, " :: rwl_unlk -> %d >>\n", ret);
1608 }
1609 return ret;
1610}
sewardj1c147ff2009-07-26 19:52:06 +00001611#if defined(VGO_linux)
1612 PTH_FUNC(int, pthreadZurwlockZuunlock, // pthread_rwlock_unlock
1613 pthread_rwlock_t* rwlock) {
1614 return pthread_rwlock_unlock_WRK(rwlock);
1615 }
1616#elif defined(VGO_darwin)
1617 PTH_FUNC(int, pthreadZurwlockZuunlockZa, // pthread_rwlock_unlock*
1618 pthread_rwlock_t* rwlock) {
1619 return pthread_rwlock_unlock_WRK(rwlock);
1620 }
1621#else
1622# error "Unsupported OS"
1623#endif
sewardjb4112022007-11-09 22:49:28 +00001624
sewardj0c09bf02011-07-11 22:11:58 +00001625#endif /* defined(HAVE_PTHREAD_RWLOCK_T) */
1626
sewardjb4112022007-11-09 22:49:28 +00001627
1628/*----------------------------------------------------------------*/
1629/*--- POSIX semaphores ---*/
1630/*----------------------------------------------------------------*/
1631
1632#include <semaphore.h>
sewardj28a7f7d2009-07-26 20:15:37 +00001633#include <fcntl.h> /* O_CREAT */
sewardjb4112022007-11-09 22:49:28 +00001634
1635#define TRACE_SEM_FNS 0
1636
1637/* Handled:
1638 int sem_init(sem_t *sem, int pshared, unsigned value);
1639 int sem_destroy(sem_t *sem);
1640 int sem_wait(sem_t *sem);
1641 int sem_post(sem_t *sem);
sewardj1c147ff2009-07-26 19:52:06 +00001642 sem_t* sem_open(const char *name, int oflag,
1643 ... [mode_t mode, unsigned value]);
1644 [complete with its idiotic semantics]
1645 int sem_close(sem_t* sem);
sewardjb4112022007-11-09 22:49:28 +00001646
1647 Unhandled:
1648 int sem_trywait(sem_t *sem);
1649 int sem_timedwait(sem_t *restrict sem,
1650 const struct timespec *restrict abs_timeout);
1651*/
1652
sewardj1c147ff2009-07-26 19:52:06 +00001653//-----------------------------------------------------------
1654// glibc: sem_init@@GLIBC_2.2.5
1655// glibc: sem_init@@GLIBC_2.1
1656// glibc: sem_init@GLIBC_2.0
1657// darwin: sem_init
1658//
1659static int sem_init_WRK(sem_t* sem, int pshared, unsigned long value)
sewardjb4112022007-11-09 22:49:28 +00001660{
1661 OrigFn fn;
1662 int ret;
1663 VALGRIND_GET_ORIG_FN(fn);
1664
1665 if (TRACE_SEM_FNS) {
1666 fprintf(stderr, "<< sem_init(%p,%d,%lu) ", sem,pshared,value);
1667 fflush(stderr);
1668 }
1669
1670 CALL_FN_W_WWW(ret, fn, sem,pshared,value);
1671
1672 if (ret == 0) {
sewardj11e352f2007-11-30 11:11:02 +00001673 DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST,
1674 sem_t*, sem, unsigned long, value);
sewardjb4112022007-11-09 22:49:28 +00001675 } else {
1676 DO_PthAPIerror( "sem_init", errno );
1677 }
1678
1679 if (TRACE_SEM_FNS) {
1680 fprintf(stderr, " sem_init -> %d >>\n", ret);
1681 fflush(stderr);
1682 }
1683
1684 return ret;
1685}
sewardj1c147ff2009-07-26 19:52:06 +00001686#if defined(VGO_linux)
1687 PTH_FUNC(int, semZuinitZAZa, // sem_init@*
1688 sem_t* sem, int pshared, unsigned long value) {
1689 return sem_init_WRK(sem, pshared, value);
1690 }
1691#elif defined(VGO_darwin)
1692 PTH_FUNC(int, semZuinit, // sem_init
1693 sem_t* sem, int pshared, unsigned long value) {
1694 return sem_init_WRK(sem, pshared, value);
1695 }
1696#else
1697# error "Unsupported OS"
1698#endif
sewardjb4112022007-11-09 22:49:28 +00001699
1700
sewardj1c147ff2009-07-26 19:52:06 +00001701//-----------------------------------------------------------
1702// glibc: sem_destroy@GLIBC_2.0
1703// glibc: sem_destroy@@GLIBC_2.1
1704// glibc: sem_destroy@@GLIBC_2.2.5
1705// darwin: sem_destroy
1706static int sem_destroy_WRK(sem_t* sem)
sewardjb4112022007-11-09 22:49:28 +00001707{
1708 OrigFn fn;
1709 int ret;
1710 VALGRIND_GET_ORIG_FN(fn);
1711
1712 if (TRACE_SEM_FNS) {
1713 fprintf(stderr, "<< sem_destroy(%p) ", sem);
1714 fflush(stderr);
1715 }
1716
sewardj11e352f2007-11-30 11:11:02 +00001717 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, sem_t*, sem);
sewardjb4112022007-11-09 22:49:28 +00001718
1719 CALL_FN_W_W(ret, fn, sem);
1720
1721 if (ret != 0) {
1722 DO_PthAPIerror( "sem_destroy", errno );
1723 }
1724
1725 if (TRACE_SEM_FNS) {
1726 fprintf(stderr, " sem_destroy -> %d >>\n", ret);
1727 fflush(stderr);
1728 }
1729
1730 return ret;
1731}
sewardj1c147ff2009-07-26 19:52:06 +00001732#if defined(VGO_linux)
1733 PTH_FUNC(int, semZudestroyZAZa, // sem_destroy*
1734 sem_t* sem) {
1735 return sem_destroy_WRK(sem);
1736 }
1737#elif defined(VGO_darwin)
1738 PTH_FUNC(int, semZudestroy, // sem_destroy
1739 sem_t* sem) {
1740 return sem_destroy_WRK(sem);
1741 }
1742#else
1743# error "Unsupported OS"
1744#endif
sewardjb4112022007-11-09 22:49:28 +00001745
1746
sewardj1c147ff2009-07-26 19:52:06 +00001747//-----------------------------------------------------------
1748// glibc: sem_wait
1749// glibc: sem_wait@GLIBC_2.0
1750// glibc: sem_wait@@GLIBC_2.1
1751// darwin: sem_wait
1752// darwin: sem_wait$NOCANCEL$UNIX2003
1753// darwin: sem_wait$UNIX2003
1754//
sewardjb4112022007-11-09 22:49:28 +00001755/* wait: decrement semaphore - acquire lockage */
1756static int sem_wait_WRK(sem_t* sem)
1757{
1758 OrigFn fn;
1759 int ret;
1760 VALGRIND_GET_ORIG_FN(fn);
1761
1762 if (TRACE_SEM_FNS) {
1763 fprintf(stderr, "<< sem_wait(%p) ", sem);
1764 fflush(stderr);
1765 }
1766
1767 CALL_FN_W_W(ret, fn, sem);
1768
1769 if (ret == 0) {
sewardj11e352f2007-11-30 11:11:02 +00001770 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_WAIT_POST, sem_t*,sem);
sewardjb4112022007-11-09 22:49:28 +00001771 } else {
1772 DO_PthAPIerror( "sem_wait", errno );
1773 }
1774
1775 if (TRACE_SEM_FNS) {
1776 fprintf(stderr, " sem_wait -> %d >>\n", ret);
1777 fflush(stderr);
1778 }
1779
1780 return ret;
1781}
sewardj1c147ff2009-07-26 19:52:06 +00001782#if defined(VGO_linux)
1783 PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */
1784 return sem_wait_WRK(sem);
1785 }
1786 PTH_FUNC(int, semZuwaitZAZa, sem_t* sem) { /* sem_wait@* */
1787 return sem_wait_WRK(sem);
1788 }
1789#elif defined(VGO_darwin)
1790 PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */
1791 return sem_wait_WRK(sem);
1792 }
1793 PTH_FUNC(int, semZuwaitZDZa, sem_t* sem) { /* sem_wait$* */
1794 return sem_wait_WRK(sem);
1795 }
1796#else
1797# error "Unsupported OS"
1798#endif
sewardjb4112022007-11-09 22:49:28 +00001799
1800
sewardj1c147ff2009-07-26 19:52:06 +00001801//-----------------------------------------------------------
1802// glibc: sem_post
1803// glibc: sem_post@GLIBC_2.0
1804// glibc: sem_post@@GLIBC_2.1
1805// darwin: sem_post
1806//
sewardjb4112022007-11-09 22:49:28 +00001807/* post: increment semaphore - release lockage */
1808static int sem_post_WRK(sem_t* sem)
1809{
1810 OrigFn fn;
1811 int ret;
1812
1813 VALGRIND_GET_ORIG_FN(fn);
1814
1815 if (TRACE_SEM_FNS) {
1816 fprintf(stderr, "<< sem_post(%p) ", sem);
1817 fflush(stderr);
1818 }
1819
sewardj11e352f2007-11-30 11:11:02 +00001820 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_POST_PRE, sem_t*,sem);
sewardjb4112022007-11-09 22:49:28 +00001821
1822 CALL_FN_W_W(ret, fn, sem);
1823
1824 if (ret != 0) {
1825 DO_PthAPIerror( "sem_post", errno );
1826 }
1827
1828 if (TRACE_SEM_FNS) {
1829 fprintf(stderr, " sem_post -> %d >>\n", ret);
1830 fflush(stderr);
1831 }
1832
1833 return ret;
1834}
sewardj1c147ff2009-07-26 19:52:06 +00001835#if defined(VGO_linux)
1836 PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */
1837 return sem_post_WRK(sem);
1838 }
1839 PTH_FUNC(int, semZupostZAZa, sem_t* sem) { /* sem_post@* */
1840 return sem_post_WRK(sem);
1841 }
1842#elif defined(VGO_darwin)
1843 PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */
1844 return sem_post_WRK(sem);
1845 }
1846#else
1847# error "Unsupported OS"
1848#endif
1849
1850
1851//-----------------------------------------------------------
1852// glibc: sem_open
1853// darwin: sem_open
1854//
1855PTH_FUNC(sem_t*, semZuopen,
1856 const char* name, long oflag,
1857 long mode, unsigned long value)
1858{
1859 /* A copy of sem_init_WRK (more or less). Is this correct? */
1860 OrigFn fn;
1861 sem_t* ret;
1862 VALGRIND_GET_ORIG_FN(fn);
1863
1864 if (TRACE_SEM_FNS) {
1865 fprintf(stderr, "<< sem_open(\"%s\",%ld,%lx,%lu) ",
1866 name,oflag,mode,value);
1867 fflush(stderr);
1868 }
1869
1870 CALL_FN_W_WWWW(ret, fn, name,oflag,mode,value);
1871
1872 if (ret != SEM_FAILED && (oflag & O_CREAT)) {
1873 DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST,
1874 sem_t*, ret, unsigned long, value);
1875 }
1876 if (ret == SEM_FAILED) {
1877 DO_PthAPIerror( "sem_open", errno );
1878 }
1879
1880 if (TRACE_SEM_FNS) {
1881 fprintf(stderr, " sem_open -> %p >>\n", ret);
1882 fflush(stderr);
1883 }
1884
1885 return ret;
sewardjb4112022007-11-09 22:49:28 +00001886}
1887
1888
sewardj1c147ff2009-07-26 19:52:06 +00001889//-----------------------------------------------------------
1890// glibc: sem_close
1891// darwin: sem_close
1892PTH_FUNC(int, sem_close, sem_t* sem)
1893{
1894 OrigFn fn;
1895 int ret;
1896 VALGRIND_GET_ORIG_FN(fn);
1897
1898 if (TRACE_SEM_FNS) {
1899 fprintf(stderr, "<< sem_close(%p) ", sem);
1900 fflush(stderr);
1901 }
1902
1903 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, sem_t*, sem);
1904
1905 CALL_FN_W_W(ret, fn, sem);
1906
1907 if (ret != 0) {
1908 DO_PthAPIerror( "sem_close", errno );
1909 }
1910
1911 if (TRACE_SEM_FNS) {
1912 fprintf(stderr, " close -> %d >>\n", ret);
1913 fflush(stderr);
1914 }
1915
1916 return ret;
1917}
1918
sewardjb4112022007-11-09 22:49:28 +00001919
1920/*----------------------------------------------------------------*/
1921/*--- Qt 4 threading functions (w/ GNU name mangling) ---*/
1922/*----------------------------------------------------------------*/
1923
sewardj38e0cf92008-11-19 10:40:56 +00001924/* Handled:
1925 QMutex::lock()
1926 QMutex::unlock()
1927 QMutex::tryLock()
1928 QMutex::tryLock(int)
sewardjb4112022007-11-09 22:49:28 +00001929
sewardj38e0cf92008-11-19 10:40:56 +00001930 QMutex::QMutex(QMutex::RecursionMode) _ZN6QMutexC1ENS_13RecursionModeE
1931 QMutex::QMutex(QMutex::RecursionMode) _ZN6QMutexC2ENS_13RecursionModeE
1932 QMutex::~QMutex() _ZN6QMutexD1Ev
1933 QMutex::~QMutex() _ZN6QMutexD2Ev
sewardjb4112022007-11-09 22:49:28 +00001934
sewardj38e0cf92008-11-19 10:40:56 +00001935 Unhandled:
1936 QReadWriteLock::lockForRead()
1937 QReadWriteLock::lockForWrite()
1938 QReadWriteLock::unlock()
1939 QReadWriteLock::tryLockForRead(int)
1940 QReadWriteLock::tryLockForRead()
1941 QReadWriteLock::tryLockForWrite(int)
1942 QReadWriteLock::tryLockForWrite()
1943
1944 QWaitCondition::wait(QMutex*, unsigned long)
1945 QWaitCondition::wakeAll()
1946 QWaitCondition::wakeOne()
1947
1948 QSemaphore::*
1949*/
1950/* More comments, 19 Nov 08, based on assessment of qt-4.5.0TP1,
1951 at least on Unix:
1952
1953 It's apparently only necessary to intercept QMutex, since that is
1954 not implemented using pthread_mutex_t; instead Qt4 has its own
1955 implementation based on atomics (to check the non-contended case)
1956 and pthread_cond_wait (to wait in the contended case).
1957
1958 QReadWriteLock is built on top of QMutex, counters, and a wait
1959 queue. So we don't need to handle it specially once QMutex
1960 handling is correct -- presumably the dependencies through QMutex
1961 are sufficient to avoid any false race reports. On the other hand,
1962 it is an open question whether too many dependencies are observed
1963 -- in which case we may miss races (false negatives). I suspect
1964 this is likely to be the case, unfortunately.
1965
1966 QWaitCondition is built on pthread_cond_t, pthread_mutex_t, QMutex
1967 and QReadWriteLock. Same compositional-correctness justificiation
1968 and limitations as fro QReadWriteLock.
1969
1970 Ditto QSemaphore (from cursory examination).
1971
1972 Does it matter that only QMutex is handled directly? Open
1973 question. From testing with drd/tests/qt4_* and with KDE4 apps, it
1974 appears that no false errors are reported; however it is not clear
1975 if this is causing false negatives.
1976
1977 Another problem with Qt4 is thread exiting. Threads are created
1978 with pthread_create (fine); but they detach and simply exit when
1979 done. There is no use of pthread_join, and the provided
1980 wait-for-a-thread-to-exit mechanism (QThread::wait, I believe)
1981 relies on a system of mutexes and flags. I suspect this also
1982 causes too many dependencies to appear. Consequently H sometimes
1983 fails to detect races at exit in some very short-lived racy
1984 programs, because it appears that a thread can exit _and_ have an
1985 observed dependency edge back to the main thread (presumably)
1986 before the main thread reaps the child (that is, calls
1987 QThread::wait).
1988
1989 This theory is supported by the observation that if all threads are
1990 made to wait at a pthread_barrier_t immediately before they exit,
1991 then H's detection of races in such programs becomes reliable;
1992 without the barrier, it is varies from run to run, depending
1993 (according to investigation) on whether aforementioned
1994 exit-before-reaping behaviour happens or not.
1995
1996 Finally, why is it necessary to intercept the QMutex constructors
1997 and destructors? The constructors are intercepted only as a matter
1998 of convenience, so H can print accurate "first observed at"
1999 clauses. However, it is actually necessary to intercept the
2000 destructors (as it is with pthread_mutex_destroy) in order that
2001 locks get removed from LAOG when they are destroyed.
sewardjb4112022007-11-09 22:49:28 +00002002*/
2003
2004// soname is libQtCore.so.4 ; match against libQtCore.so*
2005#define QT4_FUNC(ret_ty, f, args...) \
sewardj38e0cf92008-11-19 10:40:56 +00002006 ret_ty I_WRAP_SONAME_FNNAME_ZU(libQtCoreZdsoZa,f)(args); \
2007 ret_ty I_WRAP_SONAME_FNNAME_ZU(libQtCoreZdsoZa,f)(args)
sewardjb4112022007-11-09 22:49:28 +00002008
sewardj1c147ff2009-07-26 19:52:06 +00002009//-----------------------------------------------------------
sewardjb4112022007-11-09 22:49:28 +00002010// QMutex::lock()
sewardj38e0cf92008-11-19 10:40:56 +00002011QT4_FUNC(void, _ZN6QMutex4lockEv, void* self)
sewardjb4112022007-11-09 22:49:28 +00002012{
2013 OrigFn fn;
2014 VALGRIND_GET_ORIG_FN(fn);
2015 if (TRACE_QT4_FNS) {
2016 fprintf(stderr, "<< QMutex::lock %p", self); fflush(stderr);
2017 }
2018
2019 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
2020 void*,self, long,0/*!isTryLock*/);
2021
2022 CALL_FN_v_W(fn, self);
2023
2024 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
2025 void*, self);
2026
2027 if (TRACE_QT4_FNS) {
2028 fprintf(stderr, " :: Q::lock done >>\n");
2029 }
2030}
2031
sewardj1c147ff2009-07-26 19:52:06 +00002032//-----------------------------------------------------------
sewardjb4112022007-11-09 22:49:28 +00002033// QMutex::unlock()
sewardj38e0cf92008-11-19 10:40:56 +00002034QT4_FUNC(void, _ZN6QMutex6unlockEv, void* self)
sewardjb4112022007-11-09 22:49:28 +00002035{
2036 OrigFn fn;
2037 VALGRIND_GET_ORIG_FN(fn);
2038
2039 if (TRACE_QT4_FNS) {
2040 fprintf(stderr, "<< QMutex::unlock %p", self); fflush(stderr);
2041 }
2042
2043 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
2044 void*, self);
2045
2046 CALL_FN_v_W(fn, self);
2047
2048 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST,
2049 void*, self);
2050
2051 if (TRACE_QT4_FNS) {
2052 fprintf(stderr, " Q::unlock done >>\n");
2053 }
2054}
2055
sewardj1c147ff2009-07-26 19:52:06 +00002056//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002057// bool QMutex::tryLock()
sewardjb4112022007-11-09 22:49:28 +00002058// using 'long' to mimic C++ 'bool'
sewardj38e0cf92008-11-19 10:40:56 +00002059QT4_FUNC(long, _ZN6QMutex7tryLockEv, void* self)
sewardjb4112022007-11-09 22:49:28 +00002060{
2061 OrigFn fn;
2062 long ret;
2063 VALGRIND_GET_ORIG_FN(fn);
2064 if (TRACE_QT4_FNS) {
2065 fprintf(stderr, "<< QMutex::tryLock %p", self); fflush(stderr);
2066 }
2067
2068 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
2069 void*,self, long,1/*isTryLock*/);
2070
2071 CALL_FN_W_W(ret, fn, self);
2072
2073 // assumes that only the low 8 bits of the 'bool' are significant
2074 if (ret & 0xFF) {
2075 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
2076 void*, self);
2077 }
2078
2079 if (TRACE_QT4_FNS) {
2080 fprintf(stderr, " :: Q::tryLock -> %lu >>\n", ret);
2081 }
2082
2083 return ret;
2084}
2085
sewardj1c147ff2009-07-26 19:52:06 +00002086//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002087// bool QMutex::tryLock(int)
2088// using 'long' to mimic C++ 'bool'
2089QT4_FUNC(long, _ZN6QMutex7tryLockEi, void* self, long arg2)
sewardjb4112022007-11-09 22:49:28 +00002090{
2091 OrigFn fn;
sewardj38e0cf92008-11-19 10:40:56 +00002092 long ret;
sewardjb4112022007-11-09 22:49:28 +00002093 VALGRIND_GET_ORIG_FN(fn);
2094 if (TRACE_QT4_FNS) {
sewardj38e0cf92008-11-19 10:40:56 +00002095 fprintf(stderr, "<< QMutex::tryLock(int) %p %d", self, (int)arg2);
sewardjb4112022007-11-09 22:49:28 +00002096 fflush(stderr);
2097 }
2098
sewardj38e0cf92008-11-19 10:40:56 +00002099 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
2100 void*,self, long,1/*isTryLock*/);
sewardjb4112022007-11-09 22:49:28 +00002101
sewardj38e0cf92008-11-19 10:40:56 +00002102 CALL_FN_W_WW(ret, fn, self,arg2);
sewardjb4112022007-11-09 22:49:28 +00002103
sewardj38e0cf92008-11-19 10:40:56 +00002104 // assumes that only the low 8 bits of the 'bool' are significant
2105 if (ret & 0xFF) {
2106 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
2107 void*, self);
2108 }
sewardjb4112022007-11-09 22:49:28 +00002109
2110 if (TRACE_QT4_FNS) {
sewardj38e0cf92008-11-19 10:40:56 +00002111 fprintf(stderr, " :: Q::tryLock(int) -> %lu >>\n", ret);
sewardjb4112022007-11-09 22:49:28 +00002112 }
sewardj38e0cf92008-11-19 10:40:56 +00002113
2114 return ret;
sewardjb4112022007-11-09 22:49:28 +00002115}
2116
sewardj38e0cf92008-11-19 10:40:56 +00002117
sewardj1c147ff2009-07-26 19:52:06 +00002118//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002119// It's not really very clear what the args are here. But from
2120// a bit of dataflow analysis of the generated machine code of
2121// the original function, it appears this takes two args, and
2122// returns nothing. Nevertheless preserve return value just in
2123// case. A bit of debug printing indicates that the first arg
2124// is that of the mutex and the second is either zero or one,
2125// probably being the recursion mode, therefore.
2126// QMutex::QMutex(QMutex::RecursionMode) ("C1ENS" variant)
2127QT4_FUNC(void*, _ZN6QMutexC1ENS_13RecursionModeE,
2128 void* mutex,
2129 long recmode)
sewardjb4112022007-11-09 22:49:28 +00002130{
2131 OrigFn fn;
sewardj38e0cf92008-11-19 10:40:56 +00002132 long ret;
sewardjb4112022007-11-09 22:49:28 +00002133 VALGRIND_GET_ORIG_FN(fn);
sewardj38e0cf92008-11-19 10:40:56 +00002134 CALL_FN_W_WW(ret, fn, mutex, recmode);
2135 // fprintf(stderr, "QMutex constructor 1: %p <- %p %p\n", ret, arg1, arg2);
2136 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST,
2137 void*,mutex, long,1/*mbRec*/);
2138 return (void*)ret;
sewardjb4112022007-11-09 22:49:28 +00002139}
2140
sewardj1c147ff2009-07-26 19:52:06 +00002141//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002142// QMutex::~QMutex() ("D1Ev" variant)
2143QT4_FUNC(void*, _ZN6QMutexD1Ev, void* mutex)
sewardjb4112022007-11-09 22:49:28 +00002144{
2145 OrigFn fn;
sewardj38e0cf92008-11-19 10:40:56 +00002146 long ret;
sewardjb4112022007-11-09 22:49:28 +00002147 VALGRIND_GET_ORIG_FN(fn);
sewardj38e0cf92008-11-19 10:40:56 +00002148 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE,
2149 void*,mutex);
2150 CALL_FN_W_W(ret, fn, mutex);
2151 return (void*)ret;
sewardjb4112022007-11-09 22:49:28 +00002152}
2153
2154
sewardj1c147ff2009-07-26 19:52:06 +00002155//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002156// QMutex::QMutex(QMutex::RecursionMode) ("C2ENS" variant)
2157QT4_FUNC(void*, _ZN6QMutexC2ENS_13RecursionModeE,
2158 void* mutex,
2159 long recmode)
2160{
2161 assert(0);
sewardj211c2532011-07-12 06:13:08 +00002162 /*NOTREACHED*/
2163 /* Android's gcc behaves like it doesn't know that assert(0)
2164 never returns. Hence: */
2165 return NULL;
sewardj38e0cf92008-11-19 10:40:56 +00002166}
2167
sewardj1c147ff2009-07-26 19:52:06 +00002168
2169//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002170// QMutex::~QMutex() ("D2Ev" variant)
2171QT4_FUNC(void*, _ZN6QMutexD2Ev, void* mutex)
2172{
2173 assert(0);
sewardj211c2532011-07-12 06:13:08 +00002174 /* Android's gcc behaves like it doesn't know that assert(0)
2175 never returns. Hence: */
2176 return NULL;
sewardj38e0cf92008-11-19 10:40:56 +00002177}
2178
2179
2180// QReadWriteLock is not intercepted directly. See comments
2181// above.
2182
2183//// QReadWriteLock::lockForRead()
2184//// _ZN14QReadWriteLock11lockForReadEv == QReadWriteLock::lockForRead()
2185//QT4_FUNC(void, ZuZZN14QReadWriteLock11lockForReadEv,
2186// // _ZN14QReadWriteLock11lockForReadEv
2187// void* self)
2188//{
2189// OrigFn fn;
2190// VALGRIND_GET_ORIG_FN(fn);
2191// if (TRACE_QT4_FNS) {
2192// fprintf(stderr, "<< QReadWriteLock::lockForRead %p", self);
2193// fflush(stderr);
2194// }
2195//
2196// DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
2197// void*,self,
2198// long,0/*!isW*/, long,0/*!isTryLock*/);
2199//
2200// CALL_FN_v_W(fn, self);
2201//
2202// DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
2203// void*,self, long,0/*!isW*/);
2204//
2205// if (TRACE_QT4_FNS) {
2206// fprintf(stderr, " :: Q::lockForRead :: done >>\n");
2207// }
2208//}
2209//
2210//// QReadWriteLock::lockForWrite()
2211//// _ZN14QReadWriteLock12lockForWriteEv == QReadWriteLock::lockForWrite()
2212//QT4_FUNC(void, ZuZZN14QReadWriteLock12lockForWriteEv,
2213// // _ZN14QReadWriteLock12lockForWriteEv
2214// void* self)
2215//{
2216// OrigFn fn;
2217// VALGRIND_GET_ORIG_FN(fn);
2218// if (TRACE_QT4_FNS) {
2219// fprintf(stderr, "<< QReadWriteLock::lockForWrite %p", self);
2220// fflush(stderr);
2221// }
2222//
2223// DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
2224// void*,self,
2225// long,1/*isW*/, long,0/*!isTryLock*/);
2226//
2227// CALL_FN_v_W(fn, self);
2228//
2229// DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
2230// void*,self, long,1/*isW*/);
2231//
2232// if (TRACE_QT4_FNS) {
2233// fprintf(stderr, " :: Q::lockForWrite :: done >>\n");
2234// }
2235//}
2236//
2237//// QReadWriteLock::unlock()
2238//// _ZN14QReadWriteLock6unlockEv == QReadWriteLock::unlock()
2239//QT4_FUNC(void, ZuZZN14QReadWriteLock6unlockEv,
2240// // _ZN14QReadWriteLock6unlockEv
2241// void* self)
2242//{
2243// OrigFn fn;
2244// VALGRIND_GET_ORIG_FN(fn);
2245// if (TRACE_QT4_FNS) {
2246// fprintf(stderr, "<< QReadWriteLock::unlock %p", self);
2247// fflush(stderr);
2248// }
2249//
2250// DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE,
2251// void*,self);
2252//
2253// CALL_FN_v_W(fn, self);
2254//
2255// DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST,
2256// void*,self);
2257//
2258// if (TRACE_QT4_FNS) {
2259// fprintf(stderr, " :: Q::unlock :: done >>\n");
2260// }
2261//}
2262
2263
2264/*----------------------------------------------------------------*/
2265/*--- Replacements for basic string functions, that don't ---*/
sewardjb80f0c92008-11-19 16:33:59 +00002266/*--- overrun the input arrays. ---*/
sewardj38e0cf92008-11-19 10:40:56 +00002267/*----------------------------------------------------------------*/
2268
2269/* Copied verbatim from memcheck/mc_replace_strmem.c. When copying
2270 new functions, please keep them in the same order as they appear in
2271 mc_replace_strmem.c. */
2272
sewardj38e0cf92008-11-19 10:40:56 +00002273
2274#define STRCHR(soname, fnname) \
2275 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
2276 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
2277 { \
2278 UChar ch = (UChar)((UInt)c); \
2279 UChar* p = (UChar*)s; \
2280 while (True) { \
2281 if (*p == ch) return p; \
2282 if (*p == 0) return NULL; \
2283 p++; \
2284 } \
2285 }
2286
2287// Apparently index() is the same thing as strchr()
njnb4cfbc42009-05-04 04:20:02 +00002288#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00002289 STRCHR(VG_Z_LIBC_SONAME, strchr)
2290 STRCHR(VG_Z_LIBC_SONAME, index)
2291 STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
2292 STRCHR(VG_Z_LD_LINUX_SO_2, index)
2293 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
2294 STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
2295#elif defined(VGO_darwin)
2296 STRCHR(VG_Z_LIBC_SONAME, strchr)
2297 STRCHR(VG_Z_LIBC_SONAME, index)
njnb4cfbc42009-05-04 04:20:02 +00002298#endif
sewardj38e0cf92008-11-19 10:40:56 +00002299
2300
2301// Note that this replacement often doesn't get used because gcc inlines
2302// calls to strlen() with its own built-in version. This can be very
2303// confusing if you aren't expecting it. Other small functions in this file
2304// may also be inline by gcc.
2305#define STRLEN(soname, fnname) \
2306 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
2307 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
2308 { \
2309 SizeT i = 0; \
2310 while (str[i] != 0) i++; \
2311 return i; \
2312 }
2313
njnb4cfbc42009-05-04 04:20:02 +00002314#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00002315 STRLEN(VG_Z_LIBC_SONAME, strlen)
2316 STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
2317 STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
2318#elif defined(VGO_darwin)
2319 STRLEN(VG_Z_LIBC_SONAME, strlen)
njnb4cfbc42009-05-04 04:20:02 +00002320#endif
sewardj38e0cf92008-11-19 10:40:56 +00002321
2322
2323#define STRCPY(soname, fnname) \
2324 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
2325 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
2326 { \
2327 const Char* dst_orig = dst; \
2328 \
2329 while (*src) *dst++ = *src++; \
2330 *dst = 0; \
2331 \
2332 return (char*)dst_orig; \
2333 }
2334
sewardj3c944452011-09-05 20:39:57 +00002335#if defined(VGO_linux)
2336 STRCPY(VG_Z_LIBC_SONAME, strcpy)
2337#elif defined(VGO_darwin)
2338 STRCPY(VG_Z_LIBC_SONAME, strcpy)
2339#endif
sewardj38e0cf92008-11-19 10:40:56 +00002340
2341
2342#define STRCMP(soname, fnname) \
2343 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2344 ( const char* s1, const char* s2 ); \
2345 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2346 ( const char* s1, const char* s2 ) \
2347 { \
2348 register unsigned char c1; \
2349 register unsigned char c2; \
2350 while (True) { \
2351 c1 = *(unsigned char *)s1; \
2352 c2 = *(unsigned char *)s2; \
2353 if (c1 != c2) break; \
2354 if (c1 == 0) break; \
2355 s1++; s2++; \
2356 } \
2357 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
2358 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
2359 return 0; \
2360 }
2361
njnb4cfbc42009-05-04 04:20:02 +00002362#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00002363 STRCMP(VG_Z_LIBC_SONAME, strcmp)
2364 STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
2365 STRCMP(VG_Z_LD64_SO_1, strcmp)
2366#elif defined(VGO_darwin)
2367 STRCMP(VG_Z_LIBC_SONAME, strcmp)
njnb4cfbc42009-05-04 04:20:02 +00002368#endif
sewardj38e0cf92008-11-19 10:40:56 +00002369
2370
2371#define MEMCPY(soname, fnname) \
2372 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2373 ( void *dst, const void *src, SizeT len ); \
2374 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2375 ( void *dst, const void *src, SizeT len ) \
2376 { \
2377 register char *d; \
2378 register char *s; \
2379 \
2380 if (len == 0) \
2381 return dst; \
2382 \
2383 if ( dst > src ) { \
2384 d = (char *)dst + len - 1; \
2385 s = (char *)src + len - 1; \
2386 while ( len >= 4 ) { \
2387 *d-- = *s--; \
2388 *d-- = *s--; \
2389 *d-- = *s--; \
2390 *d-- = *s--; \
2391 len -= 4; \
2392 } \
2393 while ( len-- ) { \
2394 *d-- = *s--; \
2395 } \
2396 } else if ( dst < src ) { \
2397 d = (char *)dst; \
2398 s = (char *)src; \
2399 while ( len >= 4 ) { \
2400 *d++ = *s++; \
2401 *d++ = *s++; \
2402 *d++ = *s++; \
2403 *d++ = *s++; \
2404 len -= 4; \
2405 } \
2406 while ( len-- ) { \
2407 *d++ = *s++; \
2408 } \
2409 } \
2410 return dst; \
2411 }
2412
njnb4cfbc42009-05-04 04:20:02 +00002413#if defined(VGO_linux)
sewardj3c944452011-09-05 20:39:57 +00002414 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
2415 MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
2416 MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
2417 /* icc9 blats these around all over the place. Not only in the main
2418 executable but various .so's. They are highly tuned and read
2419 memory beyond the source boundary (although work correctly and
2420 never go across page boundaries), so give errors when run
2421 natively, at least for misaligned source arg. Just intercepting
2422 in the exe only until we understand more about the problem. See
2423 http://bugs.kde.org/show_bug.cgi?id=139776
sewardj38e0cf92008-11-19 10:40:56 +00002424 */
sewardj3c944452011-09-05 20:39:57 +00002425 MEMCPY(NONE, _intel_fast_memcpy)
2426#elif defined(VGO_darwin)
2427 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
2428#endif
sewardj38e0cf92008-11-19 10:40:56 +00002429
2430
sewardjb4112022007-11-09 22:49:28 +00002431/*--------------------------------------------------------------------*/
sewardj3c944452011-09-05 20:39:57 +00002432/*--- end hg_intercepts.c ---*/
sewardjb4112022007-11-09 22:49:28 +00002433/*--------------------------------------------------------------------*/