2 /*--------------------------------------------------------------------*/
3 /*--- pthread intercepts for thread checking. ---*/
4 /*--- hg_intercepts.c ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Helgrind, a Valgrind tool for detecting errors
11 Copyright (C) 2007-2017 OpenWorks LLP
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.
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.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, see <http://www.gnu.org/licenses/>.
27 The GNU General Public License is contained in the file COPYING.
29 Neither the names of the U.S. Department of Energy nor the
30 University of California nor the names of its contributors may be
31 used to endorse or promote products derived from this software
32 without prior written permission.
35 /* RUNS ON SIMULATED CPU
36 Interceptors for pthread_* functions, so that tc_main can see
37 significant thread events.
39 Important: when adding a function wrapper to this file, remember to
40 add a test case to tc20_verifywrap.c. A common cause of failure is
41 for wrappers to not engage on different distros, and
42 tc20_verifywrap essentially checks that each wrapper is really
46 // DDD: for Darwin, need to have non-"@*"-suffixed versions for all pthread
47 // functions that currently have them.
48 // Note also, in the comments and code below, all Darwin symbols start
49 // with a leading underscore, which is not shown either in the comments
50 // nor in the redirect specs.
53 #include "pub_tool_basics.h"
54 #include "pub_tool_redir.h"
55 #include "pub_tool_clreq.h"
60 #if defined(VGO_solaris)
61 /* See porting comments in drd/drd_pthread_intercepts.c
62 However when a POSIX threads API function (for example pthread_cond_init)
63 is built upon the Solaris one (cond_init), intercept only the bottom one.
64 Helgrind does not contain generic synchronization nesting like DRD
65 and double intercept confuses it. */
68 #endif /* VGO_solaris */
71 #define TRACE_PTH_FNS 0
72 #define TRACE_QT4_FNS 0
73 #define TRACE_GNAT_FNS 0
76 /*----------------------------------------------------------------*/
78 /*----------------------------------------------------------------*/
80 #if defined(VGO_solaris)
81 /* pthread_t is typedef'd to 'unsigned int' but in DO_CREQ_* macros
82 sizeof(Word) is expected. */
83 #define CREQ_PTHREAD_T Word
86 #define CREQ_PTHREAD_T pthread_t
87 #define SEM_ERROR errno
88 #endif /* VGO_solaris */
90 #define HG_EXPAND(tok) #tok
91 #define HG_STR(tok) HG_EXPAND(tok)
92 #define HG_WEAK_ALIAS(name, aliasname) \
93 extern __typeof (name) aliasname __attribute__ ((weak, alias(HG_STR(name))))
95 #if defined(VG_WRAP_THREAD_FUNCTION_LIBPTHREAD_ONLY)
96 #define PTH_FUNC(ret_ty, f, args...) \
97 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args); \
98 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args)
99 #elif defined(VG_WRAP_THREAD_FUNCTION_LIBC_AND_LIBPTHREAD)
100 #define PTH_FUNC(ret_ty, f, args...) \
101 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args); \
102 HG_WEAK_ALIAS(I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f), I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBC_SONAME,f)); \
103 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args)
104 #elif defined(VG_WRAP_THREAD_FUNCTION_LIBC_ONLY)
105 #define PTH_FUNC(ret_ty, f, args...) \
106 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBC_SONAME,f)(args); \
107 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBC_SONAME,f)(args)
109 # error "Unknown platform/thread wrapping"
112 #if defined(VGO_freebsd)
113 #define LIBC_FUNC(ret_ty, f, args...) \
114 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBC_SONAME,f)(args); \
115 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBC_SONAME,f)(args)
118 // Do a client request. These are macros rather than a functions so
119 // as to avoid having an extra frame in stack traces.
121 // NB: these duplicate definitions in helgrind.h. But here, we
122 // can have better typing (Word etc) and assertions, whereas
123 // in helgrind.h we can't. Obviously it's important the two
124 // sets of definitions are kept in sync.
126 // nuke the previous definitions
132 #define DO_CREQ_v_W(_creqF, _ty1F,_arg1F) \
135 assert(sizeof(_ty1F) == sizeof(Word)); \
136 _arg1 = (Word)(_arg1F); \
137 VALGRIND_DO_CLIENT_REQUEST_STMT((_creqF), \
141 #define DO_CREQ_v_WW(_creqF, _ty1F,_arg1F, _ty2F,_arg2F) \
144 assert(sizeof(_ty1F) == sizeof(Word)); \
145 assert(sizeof(_ty2F) == sizeof(Word)); \
146 _arg1 = (Word)(_arg1F); \
147 _arg2 = (Word)(_arg2F); \
148 VALGRIND_DO_CLIENT_REQUEST_STMT((_creqF), \
149 _arg1,_arg2,0,0,0); \
152 #define DO_CREQ_W_WW(_resF, _creqF, _ty1F,_arg1F, \
155 Word _res, _arg1, _arg2; \
156 assert(sizeof(_ty1F) == sizeof(Word)); \
157 assert(sizeof(_ty2F) == sizeof(Word)); \
158 _arg1 = (Word)(_arg1F); \
159 _arg2 = (Word)(_arg2F); \
160 _res = VALGRIND_DO_CLIENT_REQUEST_EXPR(2, \
162 _arg1,_arg2,0,0,0); \
166 #define DO_CREQ_v_WWW(_creqF, _ty1F,_arg1F, \
167 _ty2F,_arg2F, _ty3F, _arg3F) \
169 Word _arg1, _arg2, _arg3; \
170 assert(sizeof(_ty1F) == sizeof(Word)); \
171 assert(sizeof(_ty2F) == sizeof(Word)); \
172 assert(sizeof(_ty3F) == sizeof(Word)); \
173 _arg1 = (Word)(_arg1F); \
174 _arg2 = (Word)(_arg2F); \
175 _arg3 = (Word)(_arg3F); \
176 VALGRIND_DO_CLIENT_REQUEST_STMT((_creqF), \
177 _arg1,_arg2,_arg3,0,0); \
180 #define DO_CREQ_v_WWWW(_creqF, _ty1F,_arg1F, \
181 _ty2F, _arg2F, _ty3F, _arg3F, \
184 Word _arg1, _arg2, _arg3, _arg4; \
185 assert(sizeof(_ty1F) == sizeof(Word)); \
186 assert(sizeof(_ty2F) == sizeof(Word)); \
187 assert(sizeof(_ty3F) == sizeof(Word)); \
188 assert(sizeof(_ty4F) == sizeof(Word)); \
189 _arg1 = (Word)(_arg1F); \
190 _arg2 = (Word)(_arg2F); \
191 _arg3 = (Word)(_arg3F); \
192 _arg4 = (Word)(_arg4F); \
193 VALGRIND_DO_CLIENT_REQUEST_STMT((_creqF), \
194 _arg1,_arg2,_arg3,_arg4,0); \
197 #define DO_PthAPIerror(_fnnameF, _errF) \
199 const char* _fnname = (_fnnameF); \
200 long _err = (long)(int)(_errF); \
201 const char* _errstr = lame_strerror(_err); \
202 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTH_API_ERROR, \
204 long,_err, char*,_errstr); \
208 /* Needed for older glibcs (2.3 and older, at least) who don't
209 otherwise "know" about pthread_rwlock_anything or about
210 PTHREAD_MUTEX_RECURSIVE (amongst things). */
211 #define _GNU_SOURCE 1
218 /* A standalone memcmp. */
219 __attribute__((noinline
))
220 static int my_memcmp ( const void* ptr1
, const void* ptr2
, size_t size
)
222 const unsigned char* uchar_ptr1
= (const unsigned char*) ptr1
;
223 const unsigned char* uchar_ptr2
= (const unsigned char*) ptr2
;
225 for (i
= 0; i
< size
; ++i
) {
226 if (uchar_ptr1
[i
] != uchar_ptr2
[i
])
227 return (uchar_ptr1
[i
] < uchar_ptr2
[i
]) ? -1 : 1;
232 /* A lame version of strerror which doesn't use the real libc
233 strerror_r, since using the latter just generates endless more
234 threading errors (glibc goes off and does tons of crap w.r.t.
236 static const HChar
* lame_strerror ( long err
)
239 case EPERM
: return "EPERM: Operation not permitted";
240 case ENOENT
: return "ENOENT: No such file or directory";
241 case ESRCH
: return "ESRCH: No such process";
242 case EINTR
: return "EINTR: Interrupted system call";
243 case EBADF
: return "EBADF: Bad file number";
244 case EAGAIN
: return "EAGAIN: Try again";
245 case ENOMEM
: return "ENOMEM: Out of memory";
246 case EACCES
: return "EACCES: Permission denied";
247 case EFAULT
: return "EFAULT: Bad address";
248 case EEXIST
: return "EEXIST: File exists";
249 case EINVAL
: return "EINVAL: Invalid argument";
250 case EMFILE
: return "EMFILE: Too many open files";
251 case ENOSYS
: return "ENOSYS: Function not implemented";
252 case EOVERFLOW
: return "EOVERFLOW: Value too large "
253 "for defined data type";
254 case EBUSY
: return "EBUSY: Device or resource busy";
255 case ETIMEDOUT
: return "ETIMEDOUT: Connection timed out";
256 case EDEADLK
: return "EDEADLK: Resource deadlock would occur";
257 case EOPNOTSUPP
: return "EOPNOTSUPP: Operation not supported on "
258 "transport endpoint"; /* honest, guv */
259 #if !defined(VGO_freebsd)
260 case ETIME
: return "ETIME: Timer expired";
262 default: return "hg_intercepts.c: lame_strerror(): "
263 "unhandled case -- please fix me!";
267 #if defined(VGO_solaris)
269 * Solaris provides higher throughput, parallelism and scalability than other
270 * operating systems, at the cost of more fine-grained locking activity.
271 * This means for example that when a thread is created under Linux, just one
272 * big lock in glibc is used for all thread setup. Solaris libc uses several
273 * fine-grained locks and the creator thread resumes its activities as soon
274 * as possible, leaving for example stack and TLS setup activities to the
277 * This situation confuses Helgrind as it assumes there is some false ordering
278 * in place between creator and created thread; and therefore many types of
279 * race conditions in the application would not be reported. To prevent such
280 * false ordering, command line option --ignore-thread-creation is set to
281 * 'yes' by default on Solaris. All activity (loads, stores, client requests)
282 * is therefore ignored during:
283 * - pthread_create() call in the creator thread [libc.so]
284 * - thread creation phase (stack and TLS setup) in the created thread [libc.so]
286 * As explained in the comments for _ti_bind_guard(), whenever the runtime
287 * linker has to perform any activity (such as resolving a symbol), it protects
288 * its data structures by calling into rt_bind_guard() which in turn invokes
289 * _ti_bind_guard() in libc. Pointers to _ti_bind_guard() and _ti_bind_clear()
290 * are passed from libc to runtime linker in _ld_libc() call during libc_init().
291 * All activity is also ignored during:
292 * - runtime dynamic linker work between rt_bind_guard() and rt_bind_clear()
295 * This also means that Helgrind does not report race conditions in libc (when
296 * --ignore-thread-creation=yes) and runtime linker itself (unconditionally)
297 * during these ignored sequences.
300 #include "pub_tool_libcassert.h"
301 #include "pub_tool_vki.h"
304 * Original function pointers for _ti_bind_guard() and _ti_bind_clear()
305 * from libc. They are intercepted in function wrapper of _ld_libc().
307 typedef int (*hg_rtld_guard_fn
)(int flags
);
308 static hg_rtld_guard_fn hg_rtld_bind_guard
= NULL
;
309 static hg_rtld_guard_fn hg_rtld_bind_clear
= NULL
;
311 static void hg_init(void) __attribute__((constructor
));
312 static void hg_init(void)
314 if ((hg_rtld_bind_guard
== NULL
) || (hg_rtld_bind_clear
== NULL
)) {
316 "Bind guard functions for the runtime linker (ld.so.1) were not intercepted.\n"
317 "This means the interface between libc and runtime linker changed\n"
318 "and Helgrind needs to be ported properly. Giving up.\n");
324 * Intercepts for _ti_bind_guard() and _ti_bind_clear() functions from libc.
325 * These are intercepted during _ld_libc() call by identifying CI_BIND_GUARD
326 * and CI_BIND_CLEAR, to provide resilience against function renaming.
328 static int _ti_bind_guard_intercept_WRK(int flags
)
330 VALGRIND_DO_CLIENT_REQUEST_STMT(_VG_USERREQ__HG_RTLD_BIND_GUARD
,
332 return hg_rtld_bind_guard(flags
);
335 static int _ti_bind_clear_intercept_WRK(int flags
)
337 int ret
= hg_rtld_bind_clear(flags
);
338 VALGRIND_DO_CLIENT_REQUEST_STMT(_VG_USERREQ__HG_RTLD_BIND_CLEAR
,
344 * Wrapped _ld_libc() from the runtime linker ld.so.1.
346 void I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LD_SO_1
, ZuldZulibc
)(vki_Lc_interface
*ptr
);
347 void I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LD_SO_1
, ZuldZulibc
)(vki_Lc_interface
*ptr
)
352 VALGRIND_GET_ORIG_FN(fn
);
354 vki_Lc_interface
*funcs
= ptr
;
355 for (tag
= funcs
->ci_tag
; tag
!= 0; tag
= (++funcs
)->ci_tag
) {
357 case VKI_CI_BIND_GUARD
:
358 if (funcs
->vki_ci_un
.ci_func
!= _ti_bind_guard_intercept_WRK
) {
359 hg_rtld_bind_guard
= funcs
->vki_ci_un
.ci_func
;
360 funcs
->vki_ci_un
.ci_func
= _ti_bind_guard_intercept_WRK
;
363 case VKI_CI_BIND_CLEAR
:
364 if (funcs
->vki_ci_un
.ci_func
!= _ti_bind_clear_intercept_WRK
) {
365 hg_rtld_bind_clear
= funcs
->vki_ci_un
.ci_func
;
366 funcs
->vki_ci_un
.ci_func
= _ti_bind_clear_intercept_WRK
;
372 CALL_FN_v_W(fn
, ptr
);
374 #endif /* VGO_solaris */
377 /*----------------------------------------------------------------*/
378 /*--- pthread_create, pthread_join, pthread_exit ---*/
379 /*----------------------------------------------------------------*/
381 static void* mythread_wrapper ( void* xargsV
)
383 volatile Word
* xargs
= (volatile Word
*) xargsV
;
384 void*(*fn
)(void*) = (void*(*)(void*))xargs
[0];
385 void* arg
= (void*)xargs
[1];
386 pthread_t me
= pthread_self();
387 /* Tell the tool what my pthread_t is. */
388 DO_CREQ_v_W(_VG_USERREQ__HG_SET_MY_PTHREAD_T
, CREQ_PTHREAD_T
, me
);
389 /* allow the parent to proceed. We can't let it proceed until
390 we're ready because (1) we need to make sure it doesn't exit and
391 hence deallocate xargs[] while we still need it, and (2) we
392 don't want either parent nor child to proceed until the tool has
393 been notified of the child's pthread_t.
395 Note that parent and child access args[] without a lock,
396 effectively using args[2] as a spinlock in order to get the
397 parent to wait until the child passes this point. The parent
398 disables checking on xargs[] before creating the child and
399 re-enables it once the child goes past this point, so the user
400 never sees the race. The previous approach (suppressing the
401 resulting error) was flawed, because it could leave shadow
402 memory for args[] in a state in which subsequent use of it by
403 the parent would report further races. */
405 /* Now we can no longer safely use xargs[]. */
406 return (void*) fn( (void*)arg
);
409 //-----------------------------------------------------------
410 // glibc: pthread_create@GLIBC_2.0
411 // glibc: pthread_create@@GLIBC_2.1
412 // glibc: pthread_create@@GLIBC_2.2.5
413 // darwin: pthread_create
414 // darwin: pthread_create_suspended_np (trapped)
415 // FreeBSD: pthread_create
417 /* ensure this has its own frame, so as to make it more distinguishable
419 __attribute__((noinline
))
420 static int pthread_create_WRK(pthread_t
*thread
, const pthread_attr_t
*attr
,
421 void *(*start
) (void *), void *arg
)
425 volatile Word xargs
[3];
427 VALGRIND_GET_ORIG_FN(fn
);
429 fprintf(stderr
, "<< pthread_create wrapper"); fflush(stderr
);
431 xargs
[0] = (Word
)start
;
432 xargs
[1] = (Word
)arg
;
433 xargs
[2] = 1; /* serves as a spinlock -- sigh */
434 /* Disable checking on the spinlock and the two words used to
435 convey args to the child. Basically we need to make it appear
436 as if the child never accessed this area, since merely
437 suppressing the resulting races does not address the issue that
438 that piece of the parent's stack winds up in the "wrong" state
439 and therefore may give rise to mysterious races when the parent
440 comes to re-use this piece of stack in some other frame. */
441 VALGRIND_HG_DISABLE_CHECKING(&xargs
, sizeof(xargs
));
443 VALGRIND_DO_CLIENT_REQUEST_STMT(_VG_USERREQ__HG_PTHREAD_CREATE_BEGIN
,
445 CALL_FN_W_WWWW(ret
, fn
, thread
,attr
,mythread_wrapper
,&xargs
[0]);
446 VALGRIND_DO_CLIENT_REQUEST_STMT(_VG_USERREQ__HG_PTHREAD_CREATE_END
,
450 /* we have to wait for the child to notify the tool of its
451 pthread_t before continuing */
452 while (xargs
[2] != 0) {
453 /* Do nothing. We need to spin until the child writes to
454 xargs[2]. However, that can lead to starvation in the
455 child and very long delays (eg, tc19_shadowmem on
456 ppc64-linux Fedora Core 6). So yield the cpu if we can,
457 to let the child run at the earliest available
462 DO_PthAPIerror( "pthread_create", ret
);
465 /* Reenable checking on the area previously used to communicate
467 VALGRIND_HG_ENABLE_CHECKING(&xargs
, sizeof(xargs
));
470 fprintf(stderr
, " :: pth_create -> %d >>\n", ret
);
474 #if defined(VGO_linux)
475 PTH_FUNC(int, pthreadZucreateZAZa
, // pthread_create@*
476 pthread_t
*thread
, const pthread_attr_t
*attr
,
477 void *(*start
) (void *), void *arg
) {
478 return pthread_create_WRK(thread
, attr
, start
, arg
);
480 #elif defined(VGO_freebsd)
481 PTH_FUNC(int, pthreadZucreate
, // pthread_create
482 pthread_t
*thread
, const pthread_attr_t
*attr
,
483 void *(*start
) (void *), void *arg
) {
484 return pthread_create_WRK(thread
, attr
, start
, arg
);
486 #elif defined(VGO_darwin)
487 PTH_FUNC(int, pthreadZucreate
, // pthread_create
488 pthread_t
*thread
, const pthread_attr_t
*attr
,
489 void *(*start
) (void *), void *arg
) {
490 return pthread_create_WRK(thread
, attr
, start
, arg
);
492 PTH_FUNC(int, pthreadZucreateZuZa
, // pthread_create_*
493 pthread_t
*thread
, const pthread_attr_t
*attr
,
494 void *(*start
) (void *), void *arg
) {
495 // trap anything else
498 #elif defined(VGO_solaris)
499 PTH_FUNC(int, pthreadZucreate
, // pthread_create
500 pthread_t
*thread
, const pthread_attr_t
*attr
,
501 void *(*start
) (void *), void *arg
) {
502 return pthread_create_WRK(thread
, attr
, start
, arg
);
505 # error "Unsupported OS"
508 #if defined(VGO_solaris)
509 /* Solaris also provides thr_create() in addition to pthread_create().
510 * Both pthread_create(3C) and thr_create(3C) are based on private
513 __attribute__((noinline
))
514 static int thr_create_WRK(void *stk
, size_t stksize
, void *(*start
)(void *),
515 void *arg
, long flags
, thread_t
*new_thread
)
519 volatile Word xargs
[3];
521 VALGRIND_GET_ORIG_FN(fn
);
523 fprintf(stderr
, "<< thr_create wrapper"); fflush(stderr
);
525 xargs
[0] = (Word
)start
;
526 xargs
[1] = (Word
)arg
;
527 xargs
[2] = 1; /* serves as a spinlock -- sigh */
528 /* See comments in pthread_create_WRK() */
529 VALGRIND_HG_DISABLE_CHECKING(&xargs
, sizeof(xargs
));
531 VALGRIND_DO_CLIENT_REQUEST_STMT(_VG_USERREQ__HG_PTHREAD_CREATE_BEGIN
,
533 CALL_FN_W_6W(ret
, fn
, stk
, stksize
, mythread_wrapper
, start
, flags
,
535 VALGRIND_DO_CLIENT_REQUEST_STMT(_VG_USERREQ__HG_PTHREAD_CREATE_END
,
539 while (xargs
[2] != 0) {
540 /* See comments in pthread_create_WRK(). */
544 DO_PthAPIerror("thr_create", ret
);
547 VALGRIND_HG_ENABLE_CHECKING(&xargs
, sizeof(xargs
));
550 fprintf(stderr
, " :: thr_create -> %d >>\n", ret
);
554 PTH_FUNC(int, thrZucreate
, // thr_create
555 void *stk
, size_t stksize
, void *(*start
)(void *),
556 void *arg
, long flags
, thread_t
*new_thread
) {
557 return thr_create_WRK(stk
, stksize
, start
, arg
, flags
, new_thread
);
559 #endif /* VGO_solaris */
562 //-----------------------------------------------------------
563 // glibc: pthread_join
564 // darwin: pthread_join
565 // darwin: pthread_join$NOCANCEL$UNIX2003
566 // darwin pthread_join$UNIX2003
567 // FreeBSD: pthread_join
568 __attribute__((noinline
))
569 static int pthread_join_WRK(pthread_t thread
, void** value_pointer
)
573 VALGRIND_GET_ORIG_FN(fn
);
575 fprintf(stderr
, "<< pthread_join wrapper"); fflush(stderr
);
578 CALL_FN_W_WW(ret
, fn
, thread
,value_pointer
);
580 /* At least with NPTL as the thread library, this is safe because
581 it is guaranteed (by NPTL) that the joiner will completely gone
582 before pthread_join (the original) returns. See email below.*/
583 if (ret
== 0 /*success*/) {
584 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_JOIN_POST
, CREQ_PTHREAD_T
, thread
);
586 DO_PthAPIerror( "pthread_join", ret
);
590 fprintf(stderr
, " :: pth_join -> %d >>\n", ret
);
594 #if defined(VGO_linux)
595 PTH_FUNC(int, pthreadZujoin
, // pthread_join
596 pthread_t thread
, void** value_pointer
) {
597 return pthread_join_WRK(thread
, value_pointer
);
599 #elif defined(VGO_freebsd)
600 PTH_FUNC(int, pthreadZujoin
, // pthread_join
601 pthread_t thread
, void** value_pointer
) {
602 return pthread_join_WRK(thread
, value_pointer
);
604 #elif defined(VGO_darwin)
605 PTH_FUNC(int, pthreadZujoinZa
, // pthread_join*
606 pthread_t thread
, void** value_pointer
) {
607 return pthread_join_WRK(thread
, value_pointer
);
609 #elif defined(VGO_solaris)
610 PTH_FUNC(int, pthreadZujoin
, // pthread_join
611 pthread_t thread
, void** value_pointer
) {
612 return pthread_join_WRK(thread
, value_pointer
);
615 # error "Unsupported OS"
619 /* Behaviour of pthread_join on NPTL:
622 I have a question re the NPTL pthread_join implementation.
624 Suppose I am the thread 'stayer'.
626 If I call pthread_join(quitter), is it guaranteed that the
627 thread 'quitter' has really exited before pthread_join returns?
629 IOW, is it guaranteed that 'quitter' will not execute any further
630 instructions after pthread_join returns?
632 I believe this is true based on the following analysis of
633 glibc-2.5 sources. However am not 100% sure and would appreciate
636 'quitter' will be running start_thread() in nptl/pthread_create.c
638 The last action of start_thread() is to exit via
639 __exit_thread_inline(0), which simply does sys_exit
640 (nptl/pthread_create.c:403)
642 'stayer' meanwhile is waiting for lll_wait_tid (pd->tid)
643 (call at nptl/pthread_join.c:89)
645 As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536,
646 lll_wait_tid will not return until kernel notifies via futex
647 wakeup that 'quitter' has terminated.
649 Hence pthread_join cannot return until 'quitter' really has
650 completely disappeared.
653 > As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536,
654 > lll_wait_tid will not return until kernel notifies via futex
655 > wakeup that 'quitter' has terminated.
656 That's the key. The kernel resets the TID field after the thread is
657 done. No way the joiner can return before the thread is gone.
660 #if defined(VGO_solaris)
661 /* Solaris also provides thr_join() in addition to pthread_join().
662 * Both pthread_join(3C) and thr_join(3C) are based on private _thrp_join().
664 * :TODO: No functionality is currently provided for joinee == 0 and departed.
665 * This would require another client request, of course.
667 __attribute__((noinline
))
668 static int thr_join_WRK(thread_t joinee
, thread_t
*departed
, void **thread_return
)
672 VALGRIND_GET_ORIG_FN(fn
);
674 fprintf(stderr
, "<< thr_join wrapper"); fflush(stderr
);
677 CALL_FN_W_WWW(ret
, fn
, joinee
, departed
, thread_return
);
679 if (ret
== 0 /*success*/) {
680 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_JOIN_POST
, CREQ_PTHREAD_T
, joinee
);
682 DO_PthAPIerror("thr_join", ret
);
686 fprintf(stderr
, " :: thr_join -> %d >>\n", ret
);
690 PTH_FUNC(int, thrZujoin
, // thr_join
691 thread_t joinee
, thread_t
*departed
, void **thread_return
) {
692 return thr_join_WRK(joinee
, departed
, thread_return
);
694 #endif /* VGO_solaris */
697 //-----------------------------------------------------------
698 // Ada gcc gnat runtime:
699 // The gnat gcc Ada runtime does not use pthread_join. Instead, it uses
700 // a combination of other pthread primitives to ensure a child thread
701 // is gone. This combination is somewhat functionally equivalent to a
703 // We wrap two hook procedures called by the gnat gcc Ada runtime
704 // that allows helgrind to understand the semantic of Ada task dependencies
706 // procedure Master_Hook
707 // (Dependent : Task_Id;
709 // Master_Level : Integer);
710 // where type Task_Id is access all Ada_Task_Control_Block;
711 // System.Tasking.Debug.Master_Hook is called by a task Dependent to
712 // indicate that its master is identified by master+master_level.
713 void I_WRAP_SONAME_FNNAME_ZU
715 system__tasking__debug__master_hook
)
716 (void *dependent
, void *master
, int master_level
);
717 void I_WRAP_SONAME_FNNAME_ZU
719 system__tasking__debug__master_hook
)
720 (void *dependent
, void *master
, int master_level
)
723 VALGRIND_GET_ORIG_FN(fn
);
724 if (TRACE_GNAT_FNS
) {
725 fprintf(stderr
, "<< GNAT master_hook wrapper "
726 "dependent %p master %p master_level %d\n",
727 dependent
, master
, master_level
); fflush(stderr
);
730 // We call the wrapped function, even if it is a null body.
731 CALL_FN_v_WWW(fn
, dependent
, master
, master_level
);
733 DO_CREQ_v_WWW(_VG_USERREQ__HG_GNAT_MASTER_HOOK
,
734 void*,dependent
, void*,master
,
735 Word
, (Word
)master_level
);
737 if (TRACE_GNAT_FNS
) {
738 fprintf(stderr
, " :: GNAT master_hook >>\n");
742 // System.Tasking.Debug.Master_Completed_Hook is called by a task to
743 // indicate that it has completed a master.
744 // procedure Master_Completed_Hook
745 // (Self_ID : Task_Id;
746 // Master_Level : Integer);
747 // where type Task_Id is access all Ada_Task_Control_Block;
748 // This indicates that all its Dependent tasks (that identified themselves
749 // with the Master_Hook call) are terminated. Helgrind can consider
750 // at this point that the equivalent of a 'pthread_join' has been done
751 // between self_id and all dependent tasks at master_level.
752 void I_WRAP_SONAME_FNNAME_ZU
754 system__tasking__debug__master_completed_hook
)
755 (void *self_id
, int master_level
);
756 void I_WRAP_SONAME_FNNAME_ZU
758 system__tasking__debug__master_completed_hook
)
759 (void *self_id
, int master_level
)
762 VALGRIND_GET_ORIG_FN(fn
);
763 if (TRACE_GNAT_FNS
) {
764 fprintf(stderr
, "<< GNAT master_completed_hook wrapper "
765 "self_id %p master_level %d\n",
766 self_id
, master_level
); fflush(stderr
);
769 // We call the wrapped function, even if it is a null body.
770 CALL_FN_v_WW(fn
, self_id
, master_level
);
772 DO_CREQ_v_WW(_VG_USERREQ__HG_GNAT_MASTER_COMPLETED_HOOK
,
773 void*,self_id
, Word
,(Word
)master_level
);
775 if (TRACE_GNAT_FNS
) {
776 fprintf(stderr
, " :: GNAT master_completed_hook >>\n");
780 /*----------------------------------------------------------------*/
781 /*--- pthread_mutex_t functions ---*/
782 /*----------------------------------------------------------------*/
784 /* Handled: pthread_mutex_init pthread_mutex_destroy
786 pthread_mutex_trylock pthread_mutex_timedlock
790 //-----------------------------------------------------------
791 #if !defined(VGO_solaris)
792 // glibc: pthread_mutex_init
793 // darwin: pthread_mutex_init
794 // FreeBSD: pthread_mutex_init
795 PTH_FUNC(int, pthreadZumutexZuinit
, // pthread_mutex_init
796 pthread_mutex_t
*mutex
,
797 pthread_mutexattr_t
* attr
)
802 VALGRIND_GET_ORIG_FN(fn
);
804 fprintf(stderr
, "<< pthread_mxinit %p", mutex
); fflush(stderr
);
810 zzz
= pthread_mutexattr_gettype(attr
, &ty
);
811 if (zzz
== 0 && ty
== PTHREAD_MUTEX_RECURSIVE
)
815 CALL_FN_W_WW(ret
, fn
, mutex
,attr
);
817 if (ret
== 0 /*success*/) {
818 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST
,
819 pthread_mutex_t
*,mutex
, long,mbRec
);
821 DO_PthAPIerror( "pthread_mutex_init", ret
);
825 fprintf(stderr
, " :: mxinit -> %d >>\n", ret
);
830 #else /* VGO_solaris */
832 // Solaris: mutex_init (pthread_mutex_init calls here)
833 PTH_FUNC(int, mutexZuinit
, // mutex_init
834 mutex_t
*mutex
, int type
, void *arg
)
839 VALGRIND_GET_ORIG_FN(fn
);
841 fprintf(stderr
, "<< mxinit %p", mutex
); fflush(stderr
);
844 mbRec
= ((type
& LOCK_RECURSIVE
) != 0) ? 1 : 0;
846 CALL_FN_W_WWW(ret
, fn
, mutex
, type
, arg
);
848 if (ret
== 0 /*success*/) {
849 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST
,
850 mutex_t
*, mutex
, long, mbRec
);
852 DO_PthAPIerror("mutex_init", ret
);
856 fprintf(stderr
, " :: mxinit -> %d >>\n", ret
);
860 #endif /* VGO_solaris */
863 //-----------------------------------------------------------
864 // glibc: pthread_mutex_destroy
865 // darwin: pthread_mutex_destroy
866 // Solaris: mutex_destroy (pthread_mutex_destroy is a weak alias)
867 // FreeBSD: pthread_mutex_destroy
868 __attribute__((noinline
))
869 static int mutex_destroy_WRK(pthread_mutex_t
*mutex
)
872 unsigned long mutex_is_init
;
875 VALGRIND_GET_ORIG_FN(fn
);
877 fprintf(stderr
, "<< pthread_mxdestroy %p", mutex
); fflush(stderr
);
881 static const pthread_mutex_t mutex_init
= PTHREAD_MUTEX_INITIALIZER
;
882 VALGRIND_HG_DISABLE_CHECKING(mutex
, sizeof(*mutex
));
883 mutex_is_init
= my_memcmp(mutex
, &mutex_init
, sizeof(*mutex
)) == 0;
884 VALGRIND_HG_ENABLE_CHECKING(mutex
, sizeof(*mutex
));
889 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE
,
890 pthread_mutex_t
*, mutex
, unsigned long, mutex_is_init
);
892 CALL_FN_W_W(ret
, fn
, mutex
);
895 DO_PthAPIerror( "pthread_mutex_destroy", ret
);
899 fprintf(stderr
, " :: mxdestroy -> %d >>\n", ret
);
904 #if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
905 PTH_FUNC(int, pthreadZumutexZudestroy
, // pthread_mutex_destroy
906 pthread_mutex_t
*mutex
) {
907 return mutex_destroy_WRK(mutex
);
909 #elif defined(VGO_solaris)
910 PTH_FUNC(int, mutexZudestroy
, // mutex_destroy
911 pthread_mutex_t
*mutex
) {
912 return mutex_destroy_WRK(mutex
);
915 # error "Unsupported OS"
919 //-----------------------------------------------------------
920 // glibc: pthread_mutex_lock
921 // darwin: pthread_mutex_lock
922 // Solaris: mutex_lock (pthread_mutex_lock is a weak alias)
923 // FreeBSD: pthread_mutex_lock
924 __attribute__((noinline
))
925 static int mutex_lock_WRK(pthread_mutex_t
*mutex
)
929 VALGRIND_GET_ORIG_FN(fn
);
931 fprintf(stderr
, "<< pthread_mxlock %p", mutex
); fflush(stderr
);
934 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE
,
935 pthread_mutex_t
*,mutex
, long,0/*!isTryLock*/);
937 CALL_FN_W_W(ret
, fn
, mutex
);
939 /* There's a hole here: libpthread now knows the lock is locked,
940 but the tool doesn't, so some other thread could run and detect
941 that the lock has been acquired by someone (this thread). Does
942 this matter? Not sure, but I don't think so. */
944 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST
,
945 pthread_mutex_t
*, mutex
, long, (ret
== 0) ? True
: False
);
948 DO_PthAPIerror( "pthread_mutex_lock", ret
);
952 fprintf(stderr
, " :: mxlock -> %d >>\n", ret
);
957 #if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
958 PTH_FUNC(int, pthreadZumutexZulock
, // pthread_mutex_lock
959 pthread_mutex_t
*mutex
) {
960 return mutex_lock_WRK(mutex
);
962 #elif defined(VGO_solaris)
963 PTH_FUNC(int, mutexZulock
, // mutex_lock
964 pthread_mutex_t
*mutex
) {
965 return mutex_lock_WRK(mutex
);
968 # error "Unsupported OS"
971 #if defined(VGO_solaris)
972 /* Internal to libc. Mutex is usually initialized only implicitly,
973 * by zeroing mutex_t structure.
975 __attribute__((noinline
))
976 PTH_FUNC(void, lmutexZulock
, // lmutex_lock
980 VALGRIND_GET_ORIG_FN(fn
);
982 fprintf(stderr
, "<< lmxlock %p", mutex
); fflush(stderr
);
985 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE
,
986 mutex_t
*, mutex
, long, 0 /*!isTryLock*/);
987 CALL_FN_v_W(fn
, mutex
);
988 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST
,
989 mutex_t
*, mutex
, long, True
);
992 fprintf(stderr
, " :: lmxlock >>\n");
995 #endif /* VGO_solaris */
998 //-----------------------------------------------------------
999 // glibc: pthread_mutex_trylock
1000 // darwin: pthread_mutex_trylock
1001 // Solaris: mutex_trylock (pthread_mutex_trylock is a weak alias)
1002 // FreeBSD: pthread_mutext_trylock
1004 // pthread_mutex_trylock. The handling needed here is very similar
1005 // to that for pthread_mutex_lock, except that we need to tell
1006 // the pre-lock creq that this is a trylock-style operation, and
1007 // therefore not to complain if the lock is nonrecursive and
1008 // already locked by this thread -- because then it'll just fail
1009 // immediately with EBUSY.
1010 __attribute__((noinline
))
1011 static int mutex_trylock_WRK(pthread_mutex_t
*mutex
)
1015 VALGRIND_GET_ORIG_FN(fn
);
1016 if (TRACE_PTH_FNS
) {
1017 fprintf(stderr
, "<< pthread_mxtrylock %p", mutex
); fflush(stderr
);
1020 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE
,
1021 pthread_mutex_t
*,mutex
, long,1/*isTryLock*/);
1023 CALL_FN_W_W(ret
, fn
, mutex
);
1025 /* There's a hole here: libpthread now knows the lock is locked,
1026 but the tool doesn't, so some other thread could run and detect
1027 that the lock has been acquired by someone (this thread). Does
1028 this matter? Not sure, but I don't think so. */
1030 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST
,
1031 pthread_mutex_t
*, mutex
, long, (ret
== 0) ? True
: False
);
1035 DO_PthAPIerror( "pthread_mutex_trylock", ret
);
1038 if (TRACE_PTH_FNS
) {
1039 fprintf(stderr
, " :: mxtrylock -> %d >>\n", ret
);
1044 #if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
1045 PTH_FUNC(int, pthreadZumutexZutrylock
, // pthread_mutex_trylock
1046 pthread_mutex_t
*mutex
) {
1047 return mutex_trylock_WRK(mutex
);
1049 #elif defined(VGO_solaris)
1050 PTH_FUNC(int, mutexZutrylock
, // mutex_trylock
1051 pthread_mutex_t
*mutex
) {
1052 return mutex_trylock_WRK(mutex
);
1055 # error "Unsupported OS"
1059 //-----------------------------------------------------------
1060 // glibc: pthread_mutex_timedlock
1061 // darwin: (doesn't appear to exist)
1062 // Solaris: pthread_mutex_timedlock
1063 // FreeBSD: pthread_mutex_timedlock
1065 // pthread_mutex_timedlock. Identical logic to pthread_mutex_trylock.
1066 __attribute__((noinline
))
1067 static int mutex_timedlock_WRK(pthread_mutex_t
*mutex
,
1072 VALGRIND_GET_ORIG_FN(fn
);
1073 if (TRACE_PTH_FNS
) {
1074 fprintf(stderr
, "<< pthread_mxtimedlock %p %p", mutex
, timeout
);
1078 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE
,
1079 pthread_mutex_t
*,mutex
, long,1/*isTryLock-ish*/);
1081 CALL_FN_W_WW(ret
, fn
, mutex
,timeout
);
1083 /* There's a hole here: libpthread now knows the lock is locked,
1084 but the tool doesn't, so some other thread could run and detect
1085 that the lock has been acquired by someone (this thread). Does
1086 this matter? Not sure, but I don't think so. */
1088 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST
,
1089 pthread_mutex_t
*, mutex
, long, (ret
== 0) ? True
: False
);
1092 if (ret
!= ETIMEDOUT
)
1093 DO_PthAPIerror( "pthread_mutex_timedlock", ret
);
1096 if (TRACE_PTH_FNS
) {
1097 fprintf(stderr
, " :: mxtimedlock -> %d >>\n", ret
);
1102 PTH_FUNC(int, pthreadZumutexZutimedlock
, // pthread_mutex_timedlock
1103 pthread_mutex_t
*mutex
,
1105 return mutex_timedlock_WRK(mutex
, timeout
);
1107 #if defined(VGO_solaris)
1108 PTH_FUNC(int, pthreadZumutexZureltimedlock
, // pthread_mutex_reltimedlock
1109 pthread_mutex_t
*mutex
,
1111 return mutex_timedlock_WRK(mutex
, timeout
);
1115 #if defined(VGO_linux)
1116 //-----------------------------------------------------------
1117 // glibc: pthread_mutex_clocklock
1119 // pthread_mutex_clocklock. Identical logic to pthread_mutex_timedlock.
1120 __attribute__((noinline
))
1121 static int mutex_clocklock_WRK(pthread_mutex_t
*mutex
,
1127 VALGRIND_GET_ORIG_FN(fn
);
1128 if (TRACE_PTH_FNS
) {
1129 fprintf(stderr
, "<< pthread_mxclocklock %p %p", mutex
, timeout
);
1133 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE
,
1134 pthread_mutex_t
*,mutex
, long,1/*isTryLock-ish*/);
1136 CALL_FN_W_WWW(ret
, fn
, mutex
, clockid
, timeout
);
1138 /* There's a hole here: libpthread now knows the lock is locked,
1139 but the tool doesn't, so some other thread could run and detect
1140 that the lock has been acquired by someone (this thread). Does
1141 this matter? Not sure, but I don't think so. */
1143 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST
,
1144 pthread_mutex_t
*, mutex
, long, (ret
== 0) ? True
: False
);
1147 if (ret
!= ETIMEDOUT
)
1148 DO_PthAPIerror( "pthread_mutex_clocklock", ret
);
1151 if (TRACE_PTH_FNS
) {
1152 fprintf(stderr
, " :: mxclocklock -> %d >>\n", ret
);
1157 PTH_FUNC(int, pthreadZumutexZuclocklock
, // pthread_mutex_clocklock
1158 pthread_mutex_t
*mutex
,
1161 return mutex_clocklock_WRK(mutex
, clockid
, timeout
);
1165 //-----------------------------------------------------------
1166 // glibc: pthread_mutex_unlock
1167 // darwin: pthread_mutex_unlock
1168 // Solaris: mutex_unlock (pthread_mutex_unlock is a weak alias)
1169 // FreeBSD: pthread_mutex_unlock
1170 __attribute__((noinline
))
1171 static int mutex_unlock_WRK(pthread_mutex_t
*mutex
)
1175 VALGRIND_GET_ORIG_FN(fn
);
1177 if (TRACE_PTH_FNS
) {
1178 fprintf(stderr
, "<< pthread_mxunlk %p", mutex
); fflush(stderr
);
1181 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE
,
1182 pthread_mutex_t
*,mutex
);
1184 CALL_FN_W_W(ret
, fn
, mutex
);
1186 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST
,
1187 pthread_mutex_t
*,mutex
);
1190 DO_PthAPIerror( "pthread_mutex_unlock", ret
);
1193 if (TRACE_PTH_FNS
) {
1194 fprintf(stderr
, " mxunlk -> %d >>\n", ret
);
1199 #if defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
1200 PTH_FUNC(int, pthreadZumutexZuunlock
, // pthread_mutex_unlock
1201 pthread_mutex_t
*mutex
) {
1202 return mutex_unlock_WRK(mutex
);
1204 #elif defined(VGO_solaris)
1205 PTH_FUNC(int, mutexZuunlock
, // mutex_unlock
1206 pthread_mutex_t
*mutex
) {
1207 return mutex_unlock_WRK(mutex
);
1210 # error "Unsupported OS"
1214 #if defined(VGO_solaris)
1215 /* Internal to libc. */
1216 __attribute__((noinline
))
1217 PTH_FUNC(void, lmutexZuunlock
, // lmutex_unlock
1221 VALGRIND_GET_ORIG_FN(fn
);
1223 if (TRACE_PTH_FNS
) {
1224 fprintf(stderr
, "<< lmxunlk %p", mutex
); fflush(stderr
);
1227 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE
,
1229 CALL_FN_v_W(fn
, mutex
);
1230 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST
,
1233 if (TRACE_PTH_FNS
) {
1234 fprintf(stderr
, " lmxunlk >>\n");
1237 #endif /* VGO_solaris */
1240 /*----------------------------------------------------------------*/
1241 /*--- pthread_cond_t functions ---*/
1242 /*----------------------------------------------------------------*/
1244 /* Handled: pthread_cond_wait pthread_cond_timedwait
1245 pthread_cond_signal pthread_cond_broadcast
1247 pthread_cond_destroy
1250 //-----------------------------------------------------------
1251 // glibc: pthread_cond_wait@GLIBC_2.2.5
1252 // glibc: pthread_cond_wait@@GLIBC_2.3.2
1253 // darwin: pthread_cond_wait
1254 // darwin: pthread_cond_wait$NOCANCEL$UNIX2003
1255 // darwin: pthread_cond_wait$UNIX2003
1256 // Solaris: cond_wait (pthread_cond_wait is built atop of cond_wait)
1257 // FreeBSD: pthread_cond_wait
1259 __attribute__((noinline
))
1260 static int pthread_cond_wait_WRK(pthread_cond_t
* cond
,
1261 pthread_mutex_t
* mutex
)
1265 unsigned long mutex_is_valid
;
1267 VALGRIND_GET_ORIG_FN(fn
);
1269 if (TRACE_PTH_FNS
) {
1270 fprintf(stderr
, "<< pthread_cond_wait %p %p", cond
, mutex
);
1274 /* Tell the tool a cond-wait is about to happen, so it can check
1275 for bogus argument values. In return it tells us whether it
1276 thinks the mutex is valid or not. */
1277 DO_CREQ_W_WW(mutex_is_valid
,
1278 _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE
,
1279 pthread_cond_t
*,cond
, pthread_mutex_t
*,mutex
);
1280 assert(mutex_is_valid
== 1 || mutex_is_valid
== 0);
1282 /* Tell the tool we're about to drop the mutex. This reflects the
1283 fact that in a cond_wait, we show up holding the mutex, and the
1284 call atomically drops the mutex and waits for the cv to be
1286 if (mutex_is_valid
) {
1287 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE
,
1288 pthread_mutex_t
*,mutex
);
1291 CALL_FN_W_WW(ret
, fn
, cond
,mutex
);
1293 /* this conditional look stupid, but compare w/ same logic for
1294 pthread_cond_timedwait below */
1295 if (mutex_is_valid
) {
1296 /* and now we have the mutex again if (ret == 0) */
1297 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST
,
1298 pthread_mutex_t
*, mutex
, long, (ret
== 0) ? True
: False
);
1301 DO_CREQ_v_WWWW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST
,
1302 pthread_cond_t
*,cond
, pthread_mutex_t
*,mutex
, long,0,
1303 long, (ret
== 0 && mutex_is_valid
) ? True
: False
);
1306 DO_PthAPIerror( "pthread_cond_wait", ret
);
1309 if (TRACE_PTH_FNS
) {
1310 fprintf(stderr
, " cowait -> %d >>\n", ret
);
1315 #if defined(VGO_linux)
1316 PTH_FUNC(int, pthreadZucondZuwaitZAZa
, // pthread_cond_wait@*
1317 pthread_cond_t
* cond
, pthread_mutex_t
* mutex
) {
1318 return pthread_cond_wait_WRK(cond
, mutex
);
1320 #elif defined(VGO_freebsd)
1321 PTH_FUNC(int, pthreadZucondZuwait
, // pthread_cond_wait
1322 pthread_cond_t
* cond
, pthread_mutex_t
* mutex
) {
1323 return pthread_cond_wait_WRK(cond
, mutex
);
1325 #elif defined(VGO_darwin)
1326 PTH_FUNC(int, pthreadZucondZuwaitZa
, // pthread_cond_wait*
1327 pthread_cond_t
* cond
, pthread_mutex_t
* mutex
) {
1328 return pthread_cond_wait_WRK(cond
, mutex
);
1330 #elif defined(VGO_solaris)
1331 PTH_FUNC(int, condZuwait
, // cond_wait
1332 pthread_cond_t
*cond
, pthread_mutex_t
*mutex
) {
1333 return pthread_cond_wait_WRK(cond
, mutex
);
1336 # error "Unsupported OS"
1340 //-----------------------------------------------------------
1341 // glibc: pthread_cond_timedwait@@GLIBC_2.3.2
1342 // glibc: pthread_cond_timedwait@GLIBC_2.2.5
1343 // glibc: pthread_cond_timedwait@GLIBC_2.0
1344 // darwin: pthread_cond_timedwait
1345 // darwin: pthread_cond_timedwait$NOCANCEL$UNIX2003
1346 // darwin: pthread_cond_timedwait$UNIX2003
1347 // darwin: pthread_cond_timedwait_relative_np (trapped)
1348 // Solaris: cond_timedwait (pthread_cond_timedwait is built on cond_timedwait)
1349 // Solaris: cond_reltimedwait (pthread_cond_reltimedwait_np is built on this)
1350 // FreeBSD: pthread_cond_timedwait
1352 __attribute__((noinline
))
1353 static int pthread_cond_timedwait_WRK(pthread_cond_t
* cond
,
1354 pthread_mutex_t
* mutex
,
1355 struct timespec
* abstime
,
1360 unsigned long mutex_is_valid
;
1361 Bool abstime_is_valid
;
1362 VALGRIND_GET_ORIG_FN(fn
);
1364 if (TRACE_PTH_FNS
) {
1365 fprintf(stderr
, "<< pthread_cond_timedwait %p %p %p",
1366 cond
, mutex
, abstime
);
1370 /* Tell the tool a cond-wait is about to happen, so it can check
1371 for bogus argument values. In return it tells us whether it
1372 thinks the mutex is valid or not. */
1373 DO_CREQ_W_WW(mutex_is_valid
,
1374 _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE
,
1375 pthread_cond_t
*,cond
, pthread_mutex_t
*,mutex
);
1376 assert(mutex_is_valid
== 1 || mutex_is_valid
== 0);
1378 abstime_is_valid
= abstime
->tv_nsec
>= 0 && abstime
->tv_nsec
< 1000000000;
1380 /* Tell the tool we're about to drop the mutex. This reflects the
1381 fact that in a cond_wait, we show up holding the mutex, and the
1382 call atomically drops the mutex and waits for the cv to be
1384 if (mutex_is_valid
&& abstime_is_valid
) {
1385 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE
,
1386 pthread_mutex_t
*,mutex
);
1389 CALL_FN_W_WWW(ret
, fn
, cond
,mutex
,abstime
);
1391 if (mutex_is_valid
&& !abstime_is_valid
&& ret
!= EINVAL
) {
1392 DO_PthAPIerror("Bug in libpthread: pthread_cond_timedwait "
1393 "invalid abstime did not cause"
1397 if (mutex_is_valid
&& abstime_is_valid
) {
1398 /* and now we have the mutex again if (ret == 0 || ret == timeout) */
1399 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST
,
1400 pthread_mutex_t
*, mutex
,
1401 long, (ret
== 0 || ret
== timeout_error
) ? True
: False
);
1404 DO_CREQ_v_WWWW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST
,
1405 pthread_cond_t
*,cond
, pthread_mutex_t
*,mutex
,
1406 long,ret
== timeout_error
,
1407 long, (ret
== 0 || ret
== timeout_error
) && mutex_is_valid
1410 if (ret
!= 0 && ret
!= timeout_error
) {
1411 DO_PthAPIerror( "pthread_cond_timedwait", ret
);
1414 if (TRACE_PTH_FNS
) {
1415 fprintf(stderr
, " cotimedwait -> %d >>\n", ret
);
1420 #if defined(VGO_linux)
1421 PTH_FUNC(int, pthreadZucondZutimedwaitZAZa
, // pthread_cond_timedwait@*
1422 pthread_cond_t
* cond
, pthread_mutex_t
* mutex
,
1423 struct timespec
* abstime
) {
1424 return pthread_cond_timedwait_WRK(cond
, mutex
, abstime
, ETIMEDOUT
);
1426 #elif defined(VGO_freebsd)
1427 PTH_FUNC(int, pthreadZucondZutimedwait
, // pthread_cond_timedwait
1428 pthread_cond_t
* cond
, pthread_mutex_t
* mutex
,
1429 struct timespec
* abstime
) {
1430 return pthread_cond_timedwait_WRK(cond
, mutex
, abstime
, ETIMEDOUT
);
1432 #elif defined(VGO_darwin)
1433 PTH_FUNC(int, pthreadZucondZutimedwait
, // pthread_cond_timedwait
1434 pthread_cond_t
* cond
, pthread_mutex_t
* mutex
,
1435 struct timespec
* abstime
) {
1436 return pthread_cond_timedwait_WRK(cond
, mutex
, abstime
, ETIMEDOUT
);
1438 PTH_FUNC(int, pthreadZucondZutimedwaitZDZa
, // pthread_cond_timedwait$*
1439 pthread_cond_t
* cond
, pthread_mutex_t
* mutex
,
1440 struct timespec
* abstime
) {
1441 return pthread_cond_timedwait_WRK(cond
, mutex
, abstime
, ETIMEDOUT
);
1443 PTH_FUNC(int, pthreadZucondZutimedwaitZuZa
, // pthread_cond_timedwait_*
1444 pthread_cond_t
* cond
, pthread_mutex_t
* mutex
,
1445 struct timespec
* abstime
) {
1448 #elif defined(VGO_solaris)
1449 PTH_FUNC(int, condZutimedwait
, // cond_timedwait
1450 pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
1451 struct timespec
*abstime
) {
1452 return pthread_cond_timedwait_WRK(cond
, mutex
, abstime
, ETIME
);
1454 PTH_FUNC(int, condZureltimedwait
, // cond_reltimedwait
1455 pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
1456 struct timespec
*reltime
) {
1457 return pthread_cond_timedwait_WRK(cond
, mutex
, reltime
, ETIME
);
1460 # error "Unsupported OS"
1463 #if defined(VGO_linux)
1464 //-----------------------------------------------------------
1465 // glibc: pthread_cond_clockwait
1467 __attribute__((noinline
))
1468 static int pthread_cond_clockwait_WRK(pthread_cond_t
* cond
,
1469 pthread_mutex_t
* mutex
,
1471 struct timespec
* abstime
,
1476 unsigned long mutex_is_valid
;
1477 Bool abstime_is_valid
;
1478 VALGRIND_GET_ORIG_FN(fn
);
1480 if (TRACE_PTH_FNS
) {
1481 fprintf(stderr
, "<< pthread_cond_clockwait %p %p %p",
1482 cond
, mutex
, abstime
);
1486 /* Tell the tool a cond-wait is about to happen, so it can check
1487 for bogus argument values. In return it tells us whether it
1488 thinks the mutex is valid or not. */
1489 DO_CREQ_W_WW(mutex_is_valid
,
1490 _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE
,
1491 pthread_cond_t
*,cond
, pthread_mutex_t
*,mutex
);
1492 assert(mutex_is_valid
== 1 || mutex_is_valid
== 0);
1494 abstime_is_valid
= abstime
->tv_nsec
>= 0 && abstime
->tv_nsec
< 1000000000;
1496 /* Tell the tool we're about to drop the mutex. This reflects the
1497 fact that in a cond_wait, we show up holding the mutex, and the
1498 call atomically drops the mutex and waits for the cv to be
1500 if (mutex_is_valid
&& abstime_is_valid
) {
1501 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE
,
1502 pthread_mutex_t
*,mutex
);
1505 CALL_FN_W_WWWW(ret
, fn
, cond
,mutex
,clockid
,abstime
);
1507 if (mutex_is_valid
&& !abstime_is_valid
&& ret
!= EINVAL
) {
1508 DO_PthAPIerror("Bug in libpthread: pthread_cond_clockwait "
1509 "invalid abstime did not cause"
1513 if (mutex_is_valid
&& abstime_is_valid
) {
1514 /* and now we have the mutex again if (ret == 0 || ret == timeout) */
1515 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST
,
1516 pthread_mutex_t
*, mutex
,
1517 long, (ret
== 0 || ret
== timeout_error
) ? True
: False
);
1520 DO_CREQ_v_WWWW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST
,
1521 pthread_cond_t
*,cond
, pthread_mutex_t
*,mutex
,
1522 long,ret
== timeout_error
,
1523 long, (ret
== 0 || ret
== timeout_error
) && mutex_is_valid
1526 if (ret
!= 0 && ret
!= timeout_error
) {
1527 DO_PthAPIerror( "pthread_cond_clockwait", ret
);
1530 if (TRACE_PTH_FNS
) {
1531 fprintf(stderr
, " cotimedwait -> %d >>\n", ret
);
1537 PTH_FUNC(int, pthreadZucondZuclockwait
, // pthread_cond_clockwait
1538 pthread_cond_t
* cond
, pthread_mutex_t
* mutex
,
1540 struct timespec
* abstime
) {
1541 return pthread_cond_clockwait_WRK(cond
, mutex
, clockid
, abstime
, ETIMEDOUT
);
1546 //-----------------------------------------------------------
1547 // glibc: pthread_cond_signal@GLIBC_2.0
1548 // glibc: pthread_cond_signal@GLIBC_2.2.5
1549 // glibc: pthread_cond_signal@@GLIBC_2.3.2
1550 // darwin: pthread_cond_signal
1551 // darwin: pthread_cond_signal_thread_np (don't intercept this)
1552 // Solaris: cond_signal (pthread_cond_signal is a weak alias)
1553 // FreeBSD: pthread_cond_signal
1555 __attribute__((noinline
))
1556 static int pthread_cond_signal_WRK(pthread_cond_t
* cond
)
1560 VALGRIND_GET_ORIG_FN(fn
);
1562 if (TRACE_PTH_FNS
) {
1563 fprintf(stderr
, "<< pthread_cond_signal %p", cond
);
1567 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_SIGNAL_PRE
,
1568 pthread_cond_t
*,cond
);
1570 CALL_FN_W_W(ret
, fn
, cond
);
1572 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_SIGNAL_POST
,
1573 pthread_cond_t
*,cond
);
1576 DO_PthAPIerror( "pthread_cond_signal", ret
);
1579 if (TRACE_PTH_FNS
) {
1580 fprintf(stderr
, " cosig -> %d >>\n", ret
);
1585 #if defined(VGO_linux)
1586 PTH_FUNC(int, pthreadZucondZusignalZAZa
, // pthread_cond_signal@*
1587 pthread_cond_t
* cond
) {
1588 return pthread_cond_signal_WRK(cond
);
1590 #elif defined(VGO_freebsd)
1591 PTH_FUNC(int, pthreadZucondZusignal
, // pthread_cond_signal
1592 pthread_cond_t
* cond
) {
1593 return pthread_cond_signal_WRK(cond
);
1595 #elif defined(VGO_darwin)
1596 PTH_FUNC(int, pthreadZucondZusignal
, // pthread_cond_signal
1597 pthread_cond_t
* cond
) {
1598 return pthread_cond_signal_WRK(cond
);
1600 #elif defined(VGO_solaris)
1601 PTH_FUNC(int, condZusignal
, // cond_signal
1602 pthread_cond_t
*cond
) {
1603 return pthread_cond_signal_WRK(cond
);
1606 # error "Unsupported OS"
1610 //-----------------------------------------------------------
1611 // glibc: pthread_cond_broadcast@GLIBC_2.0
1612 // glibc: pthread_cond_broadcast@GLIBC_2.2.5
1613 // glibc: pthread_cond_broadcast@@GLIBC_2.3.2
1614 // darwin: pthread_cond_broadcast
1615 // Solaris: cond_broadcast (pthread_cond_broadcast is a weak alias)
1616 // FreeBSD: pthread_cond_broadcast
1618 // Note, this is pretty much identical, from a dependency-graph
1619 // point of view, with cond_signal, so the code is duplicated.
1620 // Maybe it should be commoned up.
1622 __attribute__((noinline
))
1623 static int pthread_cond_broadcast_WRK(pthread_cond_t
* cond
)
1627 VALGRIND_GET_ORIG_FN(fn
);
1629 if (TRACE_PTH_FNS
) {
1630 fprintf(stderr
, "<< pthread_cond_broadcast %p", cond
);
1634 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_BROADCAST_PRE
,
1635 pthread_cond_t
*,cond
);
1637 CALL_FN_W_W(ret
, fn
, cond
);
1639 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_BROADCAST_POST
,
1640 pthread_cond_t
*,cond
);
1643 DO_PthAPIerror( "pthread_cond_broadcast", ret
);
1646 if (TRACE_PTH_FNS
) {
1647 fprintf(stderr
, " cobro -> %d >>\n", ret
);
1652 #if defined(VGO_linux)
1653 PTH_FUNC(int, pthreadZucondZubroadcastZAZa
, // pthread_cond_broadcast@*
1654 pthread_cond_t
* cond
) {
1655 return pthread_cond_broadcast_WRK(cond
);
1657 #elif defined(VGO_freebsd)
1658 PTH_FUNC(int, pthreadZucondZubroadcast
, // pthread_cond_broadcast
1659 pthread_cond_t
* cond
) {
1660 return pthread_cond_broadcast_WRK(cond
);
1662 #elif defined(VGO_darwin)
1663 PTH_FUNC(int, pthreadZucondZubroadcast
, // pthread_cond_broadcast
1664 pthread_cond_t
* cond
) {
1665 return pthread_cond_broadcast_WRK(cond
);
1667 #elif defined(VGO_solaris)
1668 PTH_FUNC(int, condZubroadcast
, // cond_broadcast
1669 pthread_cond_t
*cond
) {
1670 return pthread_cond_broadcast_WRK(cond
);
1673 # error "Unsupported OS"
1676 // glibc: pthread_cond_init@GLIBC_2.0
1677 // glibc: pthread_cond_init@GLIBC_2.2.5
1678 // glibc: pthread_cond_init@@GLIBC_2.3.2
1679 // darwin: pthread_cond_init
1680 // Solaris: cond_init (pthread_cond_init is built atop on this function)
1681 // FreeBSD: pthread_cond_init
1682 // Easy way out: Handling of attr could have been messier.
1683 // It turns out that pthread_cond_init under linux ignores
1684 // all information in cond_attr, so do we.
1686 #if !defined(VGO_solaris)
1687 __attribute__((noinline
))
1688 static int pthread_cond_init_WRK(pthread_cond_t
* cond
, pthread_condattr_t
*cond_attr
)
1692 VALGRIND_GET_ORIG_FN(fn
);
1694 if (TRACE_PTH_FNS
) {
1695 fprintf(stderr
, "<< pthread_cond_init %p", cond
);
1699 CALL_FN_W_WW(ret
, fn
, cond
, cond_attr
);
1702 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_INIT_POST
,
1703 pthread_cond_t
*,cond
, pthread_condattr_t
*, cond_attr
);
1705 DO_PthAPIerror( "pthread_cond_init", ret
);
1708 if (TRACE_PTH_FNS
) {
1709 fprintf(stderr
, " coinit -> %d >>\n", ret
);
1714 #if defined(VGO_linux)
1715 PTH_FUNC(int, pthreadZucondZuinitZAZa
, // pthread_cond_init@*
1716 pthread_cond_t
* cond
, pthread_condattr_t
* cond_attr
) {
1717 return pthread_cond_init_WRK(cond
, cond_attr
);
1719 #elif defined(VGO_freebsd)
1720 PTH_FUNC(int, pthreadZucondZuinit
, // pthread_cond_init@*
1721 pthread_cond_t
* cond
, pthread_condattr_t
* cond_attr
) {
1722 return pthread_cond_init_WRK(cond
, cond_attr
);
1724 #elif defined(VGO_darwin)
1725 PTH_FUNC(int, pthreadZucondZuinit
, // pthread_cond_init
1726 pthread_cond_t
* cond
, pthread_condattr_t
* cond_attr
) {
1727 return pthread_cond_init_WRK(cond
, cond_attr
);
1730 # error "Unsupported OS"
1733 #else /* VGO_solaris */
1734 __attribute__((noinline
))
1735 PTH_FUNC(int, condZuinit
, // cond_init
1736 cond_t
*cond
, int type
, void *arg
)
1740 VALGRIND_GET_ORIG_FN(fn
);
1742 if (TRACE_PTH_FNS
) {
1743 fprintf(stderr
, "<< cond_init %p", cond
); fflush(stderr
);
1746 CALL_FN_W_WWW(ret
, fn
, cond
, type
, arg
);
1749 /* Luckily evh__HG_PTHREAD_COND_INIT_POST() ignores cond_attr.
1750 See also comment for pthread_cond_init_WRK(). */
1751 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_INIT_POST
,
1752 cond_t
*, cond
, void *, NULL
);
1754 DO_PthAPIerror("cond_init", ret
);
1757 if (TRACE_PTH_FNS
) {
1758 fprintf(stderr
, " cond_init -> %d >>\n", ret
);
1763 #endif /* VGO_solaris */
1766 //-----------------------------------------------------------
1767 // glibc: pthread_cond_destroy@@GLIBC_2.3.2
1768 // glibc: pthread_cond_destroy@GLIBC_2.2.5
1769 // glibc: pthread_cond_destroy@GLIBC_2.0
1770 // darwin: pthread_cond_destroy
1771 // Solaris: cond_destroy (pthread_cond_destroy is a weak alias)
1772 // FreeBSD: pthread_cond_destroy
1774 __attribute__((noinline
))
1775 static int pthread_cond_destroy_WRK(pthread_cond_t
* cond
)
1778 unsigned long cond_is_init
;
1781 VALGRIND_GET_ORIG_FN(fn
);
1783 if (TRACE_PTH_FNS
) {
1784 fprintf(stderr
, "<< pthread_cond_destroy %p", cond
);
1789 const pthread_cond_t cond_init
= PTHREAD_COND_INITIALIZER
;
1790 VALGRIND_HG_DISABLE_CHECKING(cond
, sizeof(*cond
));
1791 cond_is_init
= my_memcmp(cond
, &cond_init
, sizeof(*cond
)) == 0;
1792 VALGRIND_HG_ENABLE_CHECKING(cond
, sizeof(*cond
));
1797 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_DESTROY_PRE
,
1798 pthread_cond_t
*, cond
, unsigned long, cond_is_init
);
1800 CALL_FN_W_W(ret
, fn
, cond
);
1803 DO_PthAPIerror( "pthread_cond_destroy", ret
);
1806 if (TRACE_PTH_FNS
) {
1807 fprintf(stderr
, " codestr -> %d >>\n", ret
);
1812 #if defined(VGO_linux)
1813 PTH_FUNC(int, pthreadZucondZudestroyZAZa
, // pthread_cond_destroy@*
1814 pthread_cond_t
* cond
) {
1815 return pthread_cond_destroy_WRK(cond
);
1817 #elif defined(VGO_freebsd)
1818 PTH_FUNC(int, pthreadZucondZudestroy
, // pthread_cond_destroy@*
1819 pthread_cond_t
* cond
) {
1820 return pthread_cond_destroy_WRK(cond
);
1822 #elif defined(VGO_darwin)
1823 PTH_FUNC(int, pthreadZucondZudestroy
, // pthread_cond_destroy
1824 pthread_cond_t
* cond
) {
1825 return pthread_cond_destroy_WRK(cond
);
1827 #elif defined(VGO_solaris)
1828 PTH_FUNC(int, condZudestroy
, // cond_destroy
1829 pthread_cond_t
*cond
) {
1830 return pthread_cond_destroy_WRK(cond
);
1833 # error "Unsupported OS"
1837 /*----------------------------------------------------------------*/
1838 /*--- pthread_barrier_t functions ---*/
1839 /*----------------------------------------------------------------*/
1841 #if defined(HAVE_PTHREAD_BARRIER_INIT)
1843 /* Handled: pthread_barrier_init
1844 pthread_barrier_wait
1845 pthread_barrier_destroy
1847 Unhandled: pthread_barrierattr_destroy
1848 pthread_barrierattr_getpshared
1849 pthread_barrierattr_init
1850 pthread_barrierattr_setpshared
1851 -- are these important?
1854 //-----------------------------------------------------------
1855 // glibc: pthread_barrier_init
1856 // darwin: (doesn't appear to exist)
1857 // Solaris: pthread_barrier_init
1858 // FreeBSD: pthread_barrier_init
1859 PTH_FUNC(int, pthreadZubarrierZuinit
, // pthread_barrier_init
1860 pthread_barrier_t
* bar
,
1861 pthread_barrierattr_t
* attr
, unsigned long count
)
1865 VALGRIND_GET_ORIG_FN(fn
);
1867 if (TRACE_PTH_FNS
) {
1868 fprintf(stderr
, "<< pthread_barrier_init %p %p %lu",
1873 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_BARRIER_INIT_PRE
,
1874 pthread_barrier_t
*, bar
,
1875 unsigned long, count
,
1876 unsigned long, 0/*!resizable*/);
1878 CALL_FN_W_WWW(ret
, fn
, bar
,attr
,count
);
1881 DO_PthAPIerror( "pthread_barrier_init", ret
);
1884 if (TRACE_PTH_FNS
) {
1885 fprintf(stderr
, " pthread_barrier_init -> %d >>\n", ret
);
1892 //-----------------------------------------------------------
1893 // glibc: pthread_barrier_wait
1894 // darwin: (doesn't appear to exist)
1895 // Solaris: pthread_barrier_wait
1896 // FreeBSD: pthread_barrier_wait
1897 PTH_FUNC(int, pthreadZubarrierZuwait
, // pthread_barrier_wait
1898 pthread_barrier_t
* bar
)
1902 VALGRIND_GET_ORIG_FN(fn
);
1904 if (TRACE_PTH_FNS
) {
1905 fprintf(stderr
, "<< pthread_barrier_wait %p", bar
);
1909 /* That this works correctly, and doesn't screw up when a thread
1910 leaving the barrier races round to the front and re-enters while
1911 other threads are still leaving it, is quite subtle. See
1912 comments in the handler for PTHREAD_BARRIER_WAIT_PRE in
1914 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_WAIT_PRE
,
1915 pthread_barrier_t
*,bar
);
1917 CALL_FN_W_W(ret
, fn
, bar
);
1919 if (ret
!= 0 && ret
!= PTHREAD_BARRIER_SERIAL_THREAD
) {
1920 DO_PthAPIerror( "pthread_barrier_wait", ret
);
1923 if (TRACE_PTH_FNS
) {
1924 fprintf(stderr
, " pthread_barrier_wait -> %d >>\n", ret
);
1931 //-----------------------------------------------------------
1932 // glibc: pthread_barrier_destroy
1933 // darwin: (doesn't appear to exist)
1934 // Solaris: pthread_barrier_destroy
1935 // FreeBSD: pthread_barrier_destroy
1936 PTH_FUNC(int, pthreadZubarrierZudestroy
, // pthread_barrier_destroy
1937 pthread_barrier_t
* bar
)
1941 VALGRIND_GET_ORIG_FN(fn
);
1943 if (TRACE_PTH_FNS
) {
1944 fprintf(stderr
, "<< pthread_barrier_destroy %p", bar
);
1948 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_DESTROY_PRE
,
1949 pthread_barrier_t
*,bar
);
1951 CALL_FN_W_W(ret
, fn
, bar
);
1954 DO_PthAPIerror( "pthread_barrier_destroy", ret
);
1957 if (TRACE_PTH_FNS
) {
1958 fprintf(stderr
, " pthread_barrier_destroy -> %d >>\n", ret
);
1964 #endif // defined(HAVE_PTHREAD_BARRIER_INIT)
1967 /*----------------------------------------------------------------*/
1968 /*--- pthread_spinlock_t functions ---*/
1969 /*----------------------------------------------------------------*/
1971 #if defined(HAVE_PTHREAD_SPIN_LOCK) \
1972 && !defined(DISABLE_PTHREAD_SPINLOCK_INTERCEPT)
1974 /* Handled: pthread_spin_init pthread_spin_destroy
1975 pthread_spin_lock pthread_spin_trylock
1981 /* This is a nasty kludge, in that glibc "knows" that initialising a
1982 spin lock unlocks it, and pthread_spin_{init,unlock} are names for
1983 the same function. Hence we have to have a wrapper which does both
1984 things, without knowing which the user intended to happen.
1985 Solaris has distinct functions for init/unlock but client requests
1986 are immutable in helgrind.h so follow the glibc lead. */
1988 //-----------------------------------------------------------
1989 // glibc: pthread_spin_init
1990 // glibc: pthread_spin_unlock
1991 // darwin: (doesn't appear to exist)
1992 // Solaris: pthread_spin_init
1993 // Solaris: pthread_spin_unlock
1994 // FreeBSD: pthread_spin_init
1995 // FreeBSD: pthread_spin_unlock
1996 __attribute__((noinline
))
1997 static int pthread_spin_init_or_unlock_WRK(pthread_spinlock_t
* lock
,
2001 VALGRIND_GET_ORIG_FN(fn
);
2002 if (TRACE_PTH_FNS
) {
2003 fprintf(stderr
, "<< pthread_spin_iORu %p", lock
); fflush(stderr
);
2006 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE
,
2007 pthread_spinlock_t
*, lock
);
2009 CALL_FN_W_WW(ret
, fn
, lock
,pshared
);
2011 if (ret
== 0 /*success*/) {
2012 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST
,
2013 pthread_spinlock_t
*,lock
);
2015 DO_PthAPIerror( "pthread_spinlock_{init,unlock}", ret
);
2018 if (TRACE_PTH_FNS
) {
2019 fprintf(stderr
, " :: spiniORu -> %d >>\n", ret
);
2023 #if defined(VGO_linux)
2024 PTH_FUNC(int, pthreadZuspinZuinit
, // pthread_spin_init
2025 pthread_spinlock_t
* lock
, int pshared
) {
2026 return pthread_spin_init_or_unlock_WRK(lock
, pshared
);
2028 PTH_FUNC(int, pthreadZuspinZuunlock
, // pthread_spin_unlock
2029 pthread_spinlock_t
* lock
) {
2030 /* this is never actually called */
2031 return pthread_spin_init_or_unlock_WRK(lock
, 0/*pshared*/);
2033 #elif defined(VGO_freebsd)
2034 PTH_FUNC(int, pthreadZuspinZuinit
, // pthread_spin_init
2035 pthread_spinlock_t
* lock
, int pshared
) {
2036 return pthread_spin_init_or_unlock_WRK(lock
, pshared
);
2038 PTH_FUNC(int, pthreadZuspinZuunlock
, // pthread_spin_unlock@*
2039 pthread_spinlock_t
* lock
) {
2040 /* this is never actually called */
2041 return pthread_spin_init_or_unlock_WRK(lock
, 0/*pshared*/);
2043 #elif defined(VGO_darwin)
2044 #elif defined(VGO_solaris)
2045 PTH_FUNC(int, pthreadZuspinZuinit
, // pthread_spin_init
2046 pthread_spinlock_t
*lock
, int pshared
) {
2047 return pthread_spin_init_or_unlock_WRK(lock
, pshared
);
2049 PTH_FUNC(int, pthreadZuspinZuunlock
, // pthread_spin_unlock
2050 pthread_spinlock_t
*lock
) {
2051 return pthread_spin_init_or_unlock_WRK(lock
, 0/*pshared*/);
2054 # error "Unsupported OS"
2058 //-----------------------------------------------------------
2059 // glibc: pthread_spin_destroy
2060 // darwin: (doesn't appear to exist)
2061 // Solaris: pthread_spin_destroy
2062 // FreeBSD: pthread_spin_destroy
2063 __attribute__((noinline
))
2064 static int pthread_spin_destroy_WRK(pthread_spinlock_t
*lock
)
2068 VALGRIND_GET_ORIG_FN(fn
);
2069 if (TRACE_PTH_FNS
) {
2070 fprintf(stderr
, "<< pthread_spin_destroy %p", lock
);
2074 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_DESTROY_PRE
,
2075 pthread_spinlock_t
*,lock
);
2077 CALL_FN_W_W(ret
, fn
, lock
);
2080 DO_PthAPIerror( "pthread_spin_destroy", ret
);
2083 if (TRACE_PTH_FNS
) {
2084 fprintf(stderr
, " :: spindestroy -> %d >>\n", ret
);
2088 #if defined(VGO_linux) || defined(VGO_freebsd)
2089 PTH_FUNC(int, pthreadZuspinZudestroy
, // pthread_spin_destroy
2090 pthread_spinlock_t
*lock
) {
2091 return pthread_spin_destroy_WRK(lock
);
2093 #elif defined(VGO_darwin)
2094 #elif defined(VGO_solaris)
2095 PTH_FUNC(int, pthreadZuspinZudestroy
, // pthread_spin_destroy
2096 pthread_spinlock_t
*lock
) {
2097 return pthread_spin_destroy_WRK(lock
);
2100 # error "Unsupported OS"
2104 //-----------------------------------------------------------
2105 // glibc: pthread_spin_lock
2106 // darwin: (doesn't appear to exist)
2107 // Solaris: pthread_spin_lock
2108 // FreeBSD: pthread_spin_lock
2109 __attribute__((noinline
))
2110 static int pthread_spin_lock_WRK(pthread_spinlock_t
*lock
)
2114 VALGRIND_GET_ORIG_FN(fn
);
2115 if (TRACE_PTH_FNS
) {
2116 fprintf(stderr
, "<< pthread_spinlock %p", lock
);
2120 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE
,
2121 pthread_spinlock_t
*,lock
, long,0/*!isTryLock*/);
2123 CALL_FN_W_W(ret
, fn
, lock
);
2125 /* There's a hole here: libpthread now knows the lock is locked,
2126 but the tool doesn't, so some other thread could run and detect
2127 that the lock has been acquired by someone (this thread). Does
2128 this matter? Not sure, but I don't think so. */
2130 if (ret
== 0 /*success*/) {
2131 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST
,
2132 pthread_spinlock_t
*,lock
);
2134 DO_PthAPIerror( "pthread_spin_lock", ret
);
2137 if (TRACE_PTH_FNS
) {
2138 fprintf(stderr
, " :: spinlock -> %d >>\n", ret
);
2142 #if defined(VGO_linux) || defined(VGO_freebsd)
2143 PTH_FUNC(int, pthreadZuspinZulock
, // pthread_spin_lock
2144 pthread_spinlock_t
*lock
) {
2145 return pthread_spin_lock_WRK(lock
);
2147 #elif defined(VGO_darwin)
2148 #elif defined(VGO_solaris)
2149 PTH_FUNC(int, pthreadZuspinZulock
, // pthread_spin_lock
2150 pthread_spinlock_t
*lock
) {
2151 return pthread_spin_lock_WRK(lock
);
2154 # error "Unsupported OS"
2158 //-----------------------------------------------------------
2159 // glibc: pthread_spin_trylock
2160 // darwin: (doesn't appear to exist)
2161 // Solaris: pthread_spin_trylock
2162 // FreeBSD: pthread_spin_trylock
2163 __attribute__((noinline
))
2164 static int pthread_spin_trylock_WRK(pthread_spinlock_t
*lock
)
2168 VALGRIND_GET_ORIG_FN(fn
);
2169 if (TRACE_PTH_FNS
) {
2170 fprintf(stderr
, "<< pthread_spin_trylock %p", lock
);
2174 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE
,
2175 pthread_spinlock_t
*,lock
, long,1/*isTryLock*/);
2177 CALL_FN_W_W(ret
, fn
, lock
);
2179 /* There's a hole here: libpthread now knows the lock is locked,
2180 but the tool doesn't, so some other thread could run and detect
2181 that the lock has been acquired by someone (this thread). Does
2182 this matter? Not sure, but I don't think so. */
2184 if (ret
== 0 /*success*/) {
2185 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST
,
2186 pthread_spinlock_t
*,lock
);
2189 DO_PthAPIerror( "pthread_spin_trylock", ret
);
2192 if (TRACE_PTH_FNS
) {
2193 fprintf(stderr
, " :: spin_trylock -> %d >>\n", ret
);
2197 #if defined(VGO_linux) || defined(VGO_freebsd)
2198 PTH_FUNC(int, pthreadZuspinZutrylock
, // pthread_spin_trylock
2199 pthread_spinlock_t
*lock
) {
2200 return pthread_spin_trylock_WRK(lock
);
2202 #elif defined(VGO_darwin)
2203 #elif defined(VGO_solaris)
2204 PTH_FUNC(int, pthreadZuspinZutrylock
, // pthread_spin_trylock
2205 pthread_spinlock_t
*lock
) {
2206 return pthread_spin_trylock_WRK(lock
);
2209 # error "Unsupported OS"
2212 #endif // defined(HAVE_PTHREAD_SPIN_LOCK)
2215 /*----------------------------------------------------------------*/
2216 /*--- pthread_rwlock_t functions ---*/
2217 /*----------------------------------------------------------------*/
2219 /* Android's pthread.h doesn't say anything about rwlocks, hence these
2220 functions have to be conditionally compiled. */
2221 #if defined(HAVE_PTHREAD_RWLOCK_T)
2223 /* Handled: pthread_rwlock_init pthread_rwlock_destroy
2224 pthread_rwlock_rdlock
2225 pthread_rwlock_wrlock
2226 pthread_rwlock_unlock
2227 pthread_rwlock_tryrdlock
2228 pthread_rwlock_trywrlock
2231 //-----------------------------------------------------------
2232 // glibc: pthread_rwlock_init
2233 // darwin: pthread_rwlock_init
2234 // darwin: pthread_rwlock_init$UNIX2003
2235 // Solaris: rwlock_init (pthread_rwlock_init is built atop of rwlock_init)
2236 // FreeBSD: pthread_rwlock_init
2237 __attribute__((noinline
))
2238 static int pthread_rwlock_init_WRK(pthread_rwlock_t
*rwl
,
2239 pthread_rwlockattr_t
* attr
)
2243 VALGRIND_GET_ORIG_FN(fn
);
2244 if (TRACE_PTH_FNS
) {
2245 fprintf(stderr
, "<< pthread_rwl_init %p", rwl
); fflush(stderr
);
2248 CALL_FN_W_WW(ret
, fn
, rwl
,attr
);
2250 if (ret
== 0 /*success*/) {
2251 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST
,
2252 pthread_rwlock_t
*,rwl
);
2254 DO_PthAPIerror( "pthread_rwlock_init", ret
);
2257 if (TRACE_PTH_FNS
) {
2258 fprintf(stderr
, " :: rwl_init -> %d >>\n", ret
);
2262 #if defined(VGO_linux)
2263 PTH_FUNC(int, pthreadZurwlockZuinit
, // pthread_rwlock_init
2264 pthread_rwlock_t
*rwl
,
2265 pthread_rwlockattr_t
* attr
) {
2266 return pthread_rwlock_init_WRK(rwl
, attr
);
2268 #elif defined(VGO_freebsd)
2269 PTH_FUNC(int, pthreadZurwlockZuinit
, // pthread_rwlock_init
2270 pthread_rwlock_t
*rwl
,
2271 pthread_rwlockattr_t
* attr
) {
2272 return pthread_rwlock_init_WRK(rwl
, attr
);
2274 #elif defined(VGO_darwin)
2275 PTH_FUNC(int, pthreadZurwlockZuinitZa
, // pthread_rwlock_init*
2276 pthread_rwlock_t
*rwl
,
2277 pthread_rwlockattr_t
* attr
) {
2278 return pthread_rwlock_init_WRK(rwl
, attr
);
2280 #elif defined(VGO_solaris)
2281 static int pthread_rwlock_init_WRK(pthread_rwlock_t
*rwl
,
2282 pthread_rwlockattr_t
* attr
)
2283 __attribute__((unused
));
2285 # error "Unsupported OS"
2288 #if defined(VGO_solaris)
2289 PTH_FUNC(int, rwlockZuinit
, // rwlock_init
2296 VALGRIND_GET_ORIG_FN(fn
);
2297 if (TRACE_PTH_FNS
) {
2298 fprintf(stderr
, "<< rwl_init %p", rwlock
); fflush(stderr
);
2301 CALL_FN_W_WWW(ret
, fn
, rwlock
, type
, arg
);
2303 if (ret
== 0 /*success*/) {
2304 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST
,
2305 rwlock_t
*, rwlock
);
2307 DO_PthAPIerror("rwlock_init", ret
);
2310 if (TRACE_PTH_FNS
) {
2311 fprintf(stderr
, " :: rwl_init -> %d >>\n", ret
);
2315 #endif /* VGO_solaris */
2318 //-----------------------------------------------------------
2319 // glibc: pthread_rwlock_destroy
2320 // darwin: pthread_rwlock_destroy
2321 // darwin: pthread_rwlock_destroy$UNIX2003
2322 // Solaris: rwlock_destroy (pthread_rwlock_destroy is a weak alias)
2323 // FreeBSD: pthread_rwlock_destroy
2325 __attribute__((noinline
))
2326 static int pthread_rwlock_destroy_WRK(pthread_rwlock_t
* rwl
)
2330 VALGRIND_GET_ORIG_FN(fn
);
2331 if (TRACE_PTH_FNS
) {
2332 fprintf(stderr
, "<< pthread_rwl_destroy %p", rwl
); fflush(stderr
);
2335 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE
,
2336 pthread_rwlock_t
*,rwl
);
2338 CALL_FN_W_W(ret
, fn
, rwl
);
2341 DO_PthAPIerror( "pthread_rwlock_destroy", ret
);
2344 if (TRACE_PTH_FNS
) {
2345 fprintf(stderr
, " :: rwl_destroy -> %d >>\n", ret
);
2349 #if defined(VGO_linux)
2350 PTH_FUNC(int, pthreadZurwlockZudestroy
, // pthread_rwlock_destroy
2351 pthread_rwlock_t
*rwl
) {
2352 return pthread_rwlock_destroy_WRK(rwl
);
2354 #elif defined(VGO_freebsd)
2355 PTH_FUNC(int, pthreadZurwlockZudestroy
, // pthread_rwlock_destroy
2356 pthread_rwlock_t
*rwl
) {
2357 return pthread_rwlock_destroy_WRK(rwl
);
2359 #elif defined(VGO_darwin)
2360 PTH_FUNC(int, pthreadZurwlockZudestroyZa
, // pthread_rwlock_destroy*
2361 pthread_rwlock_t
*rwl
) {
2362 return pthread_rwlock_destroy_WRK(rwl
);
2364 #elif defined(VGO_solaris)
2365 PTH_FUNC(int, rwlockZudestroy
, // rwlock_destroy
2366 pthread_rwlock_t
*rwl
) {
2367 return pthread_rwlock_destroy_WRK(rwl
);
2370 # error "Unsupported OS"
2374 //-----------------------------------------------------------
2375 // glibc: pthread_rwlock_wrlock
2376 // darwin: pthread_rwlock_wrlock
2377 // darwin: pthread_rwlock_wrlock$UNIX2003
2378 // Solaris: rw_wrlock (pthread_rwlock_wrlock is a weak alias)
2379 // FreeBSD: pthread_rwlock_wrlock
2381 __attribute__((noinline
))
2382 static int pthread_rwlock_wrlock_WRK(pthread_rwlock_t
* rwlock
)
2386 VALGRIND_GET_ORIG_FN(fn
);
2387 if (TRACE_PTH_FNS
) {
2388 fprintf(stderr
, "<< pthread_rwl_wlk %p", rwlock
); fflush(stderr
);
2391 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE
,
2392 pthread_rwlock_t
*,rwlock
,
2393 long,1/*isW*/, long,0/*!isTryLock*/);
2395 CALL_FN_W_W(ret
, fn
, rwlock
);
2397 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST
,
2398 pthread_rwlock_t
*,rwlock
, long,1/*isW*/,
2399 long, (ret
== 0) ? True
: False
);
2401 DO_PthAPIerror( "pthread_rwlock_wrlock", ret
);
2404 if (TRACE_PTH_FNS
) {
2405 fprintf(stderr
, " :: rwl_wlk -> %d >>\n", ret
);
2409 #if defined(VGO_linux)
2410 PTH_FUNC(int, pthreadZurwlockZuwrlock
, // pthread_rwlock_wrlock
2411 pthread_rwlock_t
* rwlock
) {
2412 return pthread_rwlock_wrlock_WRK(rwlock
);
2414 #elif defined(VGO_freebsd)
2415 PTH_FUNC(int, pthreadZurwlockZuwrlock
, // pthread_rwlock_wrlock
2416 pthread_rwlock_t
* rwlock
) {
2417 return pthread_rwlock_wrlock_WRK(rwlock
);
2419 #elif defined(VGO_darwin)
2420 PTH_FUNC(int, pthreadZurwlockZuwrlockZa
, // pthread_rwlock_wrlock*
2421 pthread_rwlock_t
* rwlock
) {
2422 return pthread_rwlock_wrlock_WRK(rwlock
);
2424 #elif defined(VGO_solaris)
2425 PTH_FUNC(int, rwZuwrlock
, // rw_wrlock
2426 pthread_rwlock_t
*rwlock
) {
2427 return pthread_rwlock_wrlock_WRK(rwlock
);
2430 # error "Unsupported OS"
2433 #if defined(VGO_solaris)
2434 /* Internal to libc. */
2435 PTH_FUNC(void, lrwZuwrlock
, // lrw_wrlock
2439 VALGRIND_GET_ORIG_FN(fn
);
2440 if (TRACE_PTH_FNS
) {
2441 fprintf(stderr
, "<< lrw_wlk %p", rwlock
); fflush(stderr
);
2444 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE
,
2445 pthread_rwlock_t
*, rwlock
,
2446 long, 1/*isW*/, long, 0/*!isTryLock*/);
2448 CALL_FN_v_W(fn
, rwlock
);
2450 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST
,
2451 pthread_rwlock_t
*, rwlock
, long, 1/*isW*/, long, True
);
2453 if (TRACE_PTH_FNS
) {
2454 fprintf(stderr
, " :: lrw_wlk >>\n");
2457 #endif /* VGO_solaris */
2460 //-----------------------------------------------------------
2461 // glibc: pthread_rwlock_rdlock
2462 // darwin: pthread_rwlock_rdlock
2463 // darwin: pthread_rwlock_rdlock$UNIX2003
2464 // Solaris: rw_rdlock (pthread_rwlock_rdlock is a weak alias)
2465 // FreeBSD: pthread_rwlock_rdlock
2467 __attribute__((noinline
))
2468 static int pthread_rwlock_rdlock_WRK(pthread_rwlock_t
* rwlock
)
2472 VALGRIND_GET_ORIG_FN(fn
);
2473 if (TRACE_PTH_FNS
) {
2474 fprintf(stderr
, "<< pthread_rwl_rlk %p", rwlock
); fflush(stderr
);
2477 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE
,
2478 pthread_rwlock_t
*,rwlock
,
2479 long,0/*!isW*/, long,0/*!isTryLock*/);
2481 CALL_FN_W_W(ret
, fn
, rwlock
);
2483 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST
,
2484 pthread_rwlock_t
*,rwlock
, long,0/*!isW*/,
2485 long, (ret
== 0) ? True
: False
);
2487 DO_PthAPIerror( "pthread_rwlock_rdlock", ret
);
2490 if (TRACE_PTH_FNS
) {
2491 fprintf(stderr
, " :: rwl_rlk -> %d >>\n", ret
);
2495 #if defined(VGO_linux)
2496 PTH_FUNC(int, pthreadZurwlockZurdlock
, // pthread_rwlock_rdlock
2497 pthread_rwlock_t
* rwlock
) {
2498 return pthread_rwlock_rdlock_WRK(rwlock
);
2500 #elif defined(VGO_freebsd)
2501 PTH_FUNC(int, pthreadZurwlockZurdlock
, // pthread_rwlock_rdlock
2502 pthread_rwlock_t
* rwlock
) {
2503 return pthread_rwlock_rdlock_WRK(rwlock
);
2505 #elif defined(VGO_darwin)
2506 PTH_FUNC(int, pthreadZurwlockZurdlockZa
, // pthread_rwlock_rdlock*
2507 pthread_rwlock_t
* rwlock
) {
2508 return pthread_rwlock_rdlock_WRK(rwlock
);
2510 #elif defined(VGO_solaris)
2511 PTH_FUNC(int, rwZurdlock
, // rw_rdlock
2512 pthread_rwlock_t
*rwlock
) {
2513 return pthread_rwlock_rdlock_WRK(rwlock
);
2516 # error "Unsupported OS"
2519 #if defined(VGO_solaris)
2520 /* Internal to libc. */
2521 PTH_FUNC(void, lrwZurdlock
, // lrw_rdlock
2525 VALGRIND_GET_ORIG_FN(fn
);
2526 if (TRACE_PTH_FNS
) {
2527 fprintf(stderr
, "<< lrw_rlk %p", rwlock
); fflush(stderr
);
2530 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE
,
2531 pthread_rwlock_t
*, rwlock
,
2532 long, 0/*!isW*/, long, 0/*!isTryLock*/);
2534 CALL_FN_v_W(fn
, rwlock
);
2536 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST
,
2537 pthread_rwlock_t
*, rwlock
, long, 0/*!isW*/, long, True
);
2539 if (TRACE_PTH_FNS
) {
2540 fprintf(stderr
, " :: lrw_rlk ->>\n");
2543 #endif /* VGO_solaris */
2546 //-----------------------------------------------------------
2547 // glibc: pthread_rwlock_trywrlock
2548 // darwin: pthread_rwlock_trywrlock
2549 // darwin: pthread_rwlock_trywrlock$UNIX2003
2550 // Solaris: rw_trywrlock (pthread_rwlock_trywrlock is a weak alias)
2551 // FreeBSD: pthread_rwlock_trywrlock
2553 __attribute__((noinline
))
2554 static int pthread_rwlock_trywrlock_WRK(pthread_rwlock_t
* rwlock
)
2558 VALGRIND_GET_ORIG_FN(fn
);
2559 if (TRACE_PTH_FNS
) {
2560 fprintf(stderr
, "<< pthread_rwl_trywlk %p", rwlock
); fflush(stderr
);
2563 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE
,
2564 pthread_rwlock_t
*,rwlock
,
2565 long,1/*isW*/, long,1/*isTryLock*/);
2567 CALL_FN_W_W(ret
, fn
, rwlock
);
2569 /* There's a hole here: libpthread now knows the lock is locked,
2570 but the tool doesn't, so some other thread could run and detect
2571 that the lock has been acquired by someone (this thread). Does
2572 this matter? Not sure, but I don't think so. */
2574 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST
,
2575 pthread_rwlock_t
*,rwlock
, long,1/*isW*/,
2576 long, (ret
== 0) ? True
: False
);
2579 DO_PthAPIerror( "pthread_rwlock_trywrlock", ret
);
2582 if (TRACE_PTH_FNS
) {
2583 fprintf(stderr
, " :: rwl_trywlk -> %d >>\n", ret
);
2587 #if defined(VGO_linux)
2588 PTH_FUNC(int, pthreadZurwlockZutrywrlock
, // pthread_rwlock_trywrlock
2589 pthread_rwlock_t
* rwlock
) {
2590 return pthread_rwlock_trywrlock_WRK(rwlock
);
2592 #elif defined(VGO_freebsd)
2593 PTH_FUNC(int, pthreadZurwlockZutrywrlock
, // pthread_rwlock_trywrlock
2594 pthread_rwlock_t
* rwlock
) {
2595 return pthread_rwlock_trywrlock_WRK(rwlock
);
2597 #elif defined(VGO_darwin)
2598 PTH_FUNC(int, pthreadZurwlockZutrywrlockZa
, // pthread_rwlock_trywrlock*
2599 pthread_rwlock_t
* rwlock
) {
2600 return pthread_rwlock_trywrlock_WRK(rwlock
);
2602 #elif defined(VGO_solaris)
2603 PTH_FUNC(int, rwZutrywrlock
, // rw_trywrlock
2604 pthread_rwlock_t
*rwlock
) {
2605 return pthread_rwlock_trywrlock_WRK(rwlock
);
2608 # error "Unsupported OS"
2612 //-----------------------------------------------------------
2613 // glibc: pthread_rwlock_tryrdlock
2614 // darwin: pthread_rwlock_tryrdlock
2615 // darwin: pthread_rwlock_tryrdlock$UNIX2003
2616 // Solaris: rw_tryrdlock (pthread_rwlock_tryrdlock is a weak alias)
2617 // FreeBSD: pthread_rwlock_tryrdlock
2619 __attribute__((noinline
))
2620 static int pthread_rwlock_tryrdlock_WRK(pthread_rwlock_t
* rwlock
)
2624 VALGRIND_GET_ORIG_FN(fn
);
2625 if (TRACE_PTH_FNS
) {
2626 fprintf(stderr
, "<< pthread_rwl_tryrlk %p", rwlock
); fflush(stderr
);
2629 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE
,
2630 pthread_rwlock_t
*,rwlock
,
2631 long,0/*!isW*/, long,1/*isTryLock*/);
2633 CALL_FN_W_W(ret
, fn
, rwlock
);
2635 /* There's a hole here: libpthread now knows the lock is locked,
2636 but the tool doesn't, so some other thread could run and detect
2637 that the lock has been acquired by someone (this thread). Does
2638 this matter? Not sure, but I don't think so. */
2640 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST
,
2641 pthread_rwlock_t
*,rwlock
, long,0/*!isW*/,
2642 long, (ret
== 0) ? True
: False
);
2646 DO_PthAPIerror( "pthread_rwlock_tryrdlock", ret
);
2649 if (TRACE_PTH_FNS
) {
2650 fprintf(stderr
, " :: rwl_tryrlk -> %d >>\n", ret
);
2654 #if defined(VGO_linux)
2655 PTH_FUNC(int, pthreadZurwlockZutryrdlock
, // pthread_rwlock_tryrdlock
2656 pthread_rwlock_t
* rwlock
) {
2657 return pthread_rwlock_tryrdlock_WRK(rwlock
);
2659 #elif defined(VGO_freebsd)
2660 PTH_FUNC(int, pthreadZurwlockZutryrdlock
, // pthread_rwlock_tryrdlock
2661 pthread_rwlock_t
* rwlock
) {
2662 return pthread_rwlock_tryrdlock_WRK(rwlock
);
2664 #elif defined(VGO_darwin)
2665 PTH_FUNC(int, pthreadZurwlockZutryrdlockZa
, // pthread_rwlock_tryrdlock*
2666 pthread_rwlock_t
* rwlock
) {
2667 return pthread_rwlock_tryrdlock_WRK(rwlock
);
2669 #elif defined(VGO_solaris)
2670 PTH_FUNC(int, rwZutryrdlock
, // rw_tryrdlock
2671 pthread_rwlock_t
*rwlock
) {
2672 return pthread_rwlock_tryrdlock_WRK(rwlock
);
2675 # error "Unsupported OS"
2679 //-----------------------------------------------------------
2680 // glibc: pthread_rwlock_timedrdlock
2681 // darwin: Unhandled
2682 // Solaris: pthread_rwlock_timedrdlock
2683 // Solaris: pthread_rwlock_reltimedrdlock_np
2684 // FreeBSD: pthread_rwlock_timedrdlock
2686 __attribute__((noinline
)) __attribute__((unused
))
2687 static int pthread_rwlock_timedrdlock_WRK(pthread_rwlock_t
*rwlock
,
2688 const struct timespec
*timeout
)
2692 VALGRIND_GET_ORIG_FN(fn
);
2693 if (TRACE_PTH_FNS
) {
2694 fprintf(stderr
, "<< pthread_rwl_timedrdl %p", rwlock
); fflush(stderr
);
2697 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE
,
2698 pthread_rwlock_t
*, rwlock
,
2699 long, 0/*isW*/, long, 0/*isTryLock*/);
2701 CALL_FN_W_WW(ret
, fn
, rwlock
, timeout
);
2703 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST
,
2704 pthread_rwlock_t
*, rwlock
, long, 0/*isW*/,
2705 long, (ret
== 0) ? True
: False
);
2707 DO_PthAPIerror("pthread_rwlock_timedrdlock", ret
);
2710 if (TRACE_PTH_FNS
) {
2711 fprintf(stderr
, " :: rwl_timedrdl -> %d >>\n", ret
);
2715 #if defined(VGO_linux)
2716 PTH_FUNC(int, pthreadZurwlockZutimedrdlock
, // pthread_rwlock_timedrdlock
2717 pthread_rwlock_t
*rwlock
,
2718 const struct timespec
*timeout
) {
2719 return pthread_rwlock_timedrdlock_WRK(rwlock
, timeout
);
2721 #elif defined(VGO_darwin)
2722 #elif defined(VGO_freebsd)
2723 PTH_FUNC(int, pthreadZurwlockZutimedrdlock
, // pthread_rwlock_timedrdlock
2724 pthread_rwlock_t
*rwlock
,
2725 const struct timespec
*timeout
) {
2726 return pthread_rwlock_timedrdlock_WRK(rwlock
, timeout
);
2728 #elif defined(VGO_solaris)
2729 PTH_FUNC(int, pthreadZurwlockZutimedrdlock
, // pthread_rwlock_timedrdlock
2730 pthread_rwlock_t
*rwlock
,
2731 const struct timespec
*timeout
) {
2732 return pthread_rwlock_timedrdlock_WRK(rwlock
, timeout
);
2734 PTH_FUNC(int, pthreadZurwlockZureltimedrdlockZunp
, // pthread_rwlock_timedrdlock_np
2735 pthread_rwlock_t
*rwlock
,
2736 const struct timespec
*timeout
) {
2737 return pthread_rwlock_timedrdlock_WRK(rwlock
, timeout
);
2740 # error "Unsupported OS"
2743 #if defined(VGO_linux)
2744 //-----------------------------------------------------------
2745 // glibc: pthread_rwlock_clockrdlock
2747 __attribute__((noinline
)) __attribute__((unused
))
2748 static int pthread_rwlock_clockrdlock_WRK(pthread_rwlock_t
*rwlock
,
2750 const struct timespec
*timeout
)
2754 VALGRIND_GET_ORIG_FN(fn
);
2755 if (TRACE_PTH_FNS
) {
2756 fprintf(stderr
, "<< pthread_rwl_clockrdl %p", rwlock
); fflush(stderr
);
2759 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE
,
2760 pthread_rwlock_t
*, rwlock
,
2761 long, 0/*isW*/, long, 0/*isTryLock*/);
2763 CALL_FN_W_WWW(ret
, fn
, rwlock
, clockid
, timeout
);
2765 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST
,
2766 pthread_rwlock_t
*, rwlock
, long, 0/*isW*/,
2767 long, (ret
== 0) ? True
: False
);
2769 DO_PthAPIerror("pthread_rwlock_clockrdlock", ret
);
2772 if (TRACE_PTH_FNS
) {
2773 fprintf(stderr
, " :: rwl_clockrdl -> %d >>\n", ret
);
2778 PTH_FUNC(int, pthreadZurwlockZuclockrdlock
, // pthread_rwlock_clockrdlock
2779 pthread_rwlock_t
*rwlock
,
2781 const struct timespec
*timeout
) {
2782 return pthread_rwlock_clockrdlock_WRK(rwlock
, clockid
, timeout
);
2787 //-----------------------------------------------------------
2788 // glibc: pthread_rwlock_timedwrlock
2789 // Solaris: pthread_rwlock_timedwrlock
2790 // Solaris: pthread_rwlock_reltimedwrlock_np
2791 // FreeBSD: pthread_rwlock_timedwrlock
2793 __attribute__((noinline
)) __attribute__((unused
))
2794 static int pthread_rwlock_timedwrlock_WRK(pthread_rwlock_t
*rwlock
,
2795 const struct timespec
*timeout
)
2799 VALGRIND_GET_ORIG_FN(fn
);
2800 if (TRACE_PTH_FNS
) {
2801 fprintf(stderr
, "<< pthread_rwl_timedwrl %p", rwlock
); fflush(stderr
);
2804 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE
,
2805 pthread_rwlock_t
*, rwlock
,
2806 long, 1/*isW*/, long, 0/*isTryLock*/);
2808 CALL_FN_W_WW(ret
, fn
, rwlock
, timeout
);
2810 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST
,
2811 pthread_rwlock_t
*, rwlock
, long, 1/*isW*/,
2812 long, (ret
== 0) ? True
: False
);
2814 DO_PthAPIerror("pthread_rwlock_timedwrlock", ret
);
2817 if (TRACE_PTH_FNS
) {
2818 fprintf(stderr
, " :: rwl_timedwrl -> %d >>\n", ret
);
2822 #if defined(VGO_linux)
2823 PTH_FUNC(int, pthreadZurwlockZutimedwrlock
, // pthread_rwlock_timedwrlock
2824 pthread_rwlock_t
*rwlock
,
2825 const struct timespec
*timeout
) {
2826 return pthread_rwlock_timedwrlock_WRK(rwlock
, timeout
);
2828 #elif defined(VGO_darwin)
2829 #elif defined(VGO_freebsd)
2830 PTH_FUNC(int, pthreadZurwlockZutimedwrlock
, // pthread_rwlock_timedwrlock
2831 pthread_rwlock_t
*rwlock
,
2832 const struct timespec
*timeout
) {
2833 return pthread_rwlock_timedwrlock_WRK(rwlock
, timeout
);
2835 #elif defined(VGO_solaris)
2836 PTH_FUNC(int, pthreadZurwlockZutimedwrlock
, // pthread_rwlock_timedwrlock
2837 pthread_rwlock_t
*rwlock
,
2838 const struct timespec
*timeout
) {
2839 return pthread_rwlock_timedwrlock_WRK(rwlock
, timeout
);
2841 PTH_FUNC(int, pthreadZurwlockZureltimedwrlockZunp
, // pthread_rwlock_timedwrlock_np
2842 pthread_rwlock_t
*rwlock
,
2843 const struct timespec
*timeout
) {
2844 return pthread_rwlock_timedwrlock_WRK(rwlock
, timeout
);
2847 # error "Unsupported OS"
2850 #if defined(VGO_linux)
2851 //-----------------------------------------------------------
2852 // glibc: pthread_rwlock_clockwrlock
2854 __attribute__((noinline
)) __attribute__((unused
))
2855 static int pthread_rwlock_clockwrlock_WRK(pthread_rwlock_t
*rwlock
,
2857 const struct timespec
*timeout
)
2861 VALGRIND_GET_ORIG_FN(fn
);
2862 if (TRACE_PTH_FNS
) {
2863 fprintf(stderr
, "<< pthread_rwl_clockwrl %p", rwlock
); fflush(stderr
);
2866 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE
,
2867 pthread_rwlock_t
*, rwlock
,
2868 long, 1/*isW*/, long, 0/*isTryLock*/);
2870 CALL_FN_W_WWW(ret
, fn
, rwlock
, clockid
, timeout
);
2872 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST
,
2873 pthread_rwlock_t
*, rwlock
, long, 1/*isW*/,
2874 long, (ret
== 0) ? True
: False
);
2876 DO_PthAPIerror("pthread_rwlock_clockwrlock", ret
);
2879 if (TRACE_PTH_FNS
) {
2880 fprintf(stderr
, " :: rwl_clockwrl -> %d >>\n", ret
);
2885 PTH_FUNC(int, pthreadZurwlockZuclockwrlock
, // pthread_rwlock_clockwrlock
2886 pthread_rwlock_t
*rwlock
,
2888 const struct timespec
*timeout
) {
2889 return pthread_rwlock_clockwrlock_WRK(rwlock
, clockid
, timeout
);
2894 //-----------------------------------------------------------
2895 // glibc: pthread_rwlock_unlock
2896 // darwin: pthread_rwlock_unlock
2897 // darwin: pthread_rwlock_unlock$UNIX2003
2898 // Solaris: rw_unlock (pthread_rwlock_unlock is a weak alias)
2899 // FreeBSD: pthread_rwlock_unlock
2900 __attribute__((noinline
))
2901 static int pthread_rwlock_unlock_WRK(pthread_rwlock_t
* rwlock
)
2905 VALGRIND_GET_ORIG_FN(fn
);
2906 if (TRACE_PTH_FNS
) {
2907 fprintf(stderr
, "<< pthread_rwl_unlk %p", rwlock
); fflush(stderr
);
2910 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE
,
2911 pthread_rwlock_t
*,rwlock
);
2913 CALL_FN_W_W(ret
, fn
, rwlock
);
2915 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST
,
2916 pthread_rwlock_t
*,rwlock
);
2918 DO_PthAPIerror( "pthread_rwlock_unlock", ret
);
2921 if (TRACE_PTH_FNS
) {
2922 fprintf(stderr
, " :: rwl_unlk -> %d >>\n", ret
);
2926 #if defined(VGO_linux)
2927 PTH_FUNC(int, pthreadZurwlockZuunlock
, // pthread_rwlock_unlock
2928 pthread_rwlock_t
* rwlock
) {
2929 return pthread_rwlock_unlock_WRK(rwlock
);
2931 #elif defined(VGO_freebsd)
2932 PTH_FUNC(int, pthreadZurwlockZuunlock
, // pthread_rwlock_unlock
2933 pthread_rwlock_t
* rwlock
) {
2934 return pthread_rwlock_unlock_WRK(rwlock
);
2936 #elif defined(VGO_darwin)
2937 PTH_FUNC(int, pthreadZurwlockZuunlockZa
, // pthread_rwlock_unlock*
2938 pthread_rwlock_t
* rwlock
) {
2939 return pthread_rwlock_unlock_WRK(rwlock
);
2941 #elif defined(VGO_solaris)
2942 PTH_FUNC(int, rwZuunlock
, // rw_unlock
2943 pthread_rwlock_t
*rwlock
) {
2944 return pthread_rwlock_unlock_WRK(rwlock
);
2947 # error "Unsupported OS"
2950 #endif /* defined(HAVE_PTHREAD_RWLOCK_T) */
2953 /*----------------------------------------------------------------*/
2954 /*--- POSIX semaphores ---*/
2955 /*----------------------------------------------------------------*/
2957 #include <semaphore.h>
2958 #include <fcntl.h> /* O_CREAT */
2960 #define TRACE_SEM_FNS 0
2963 int sem_init(sem_t *sem, int pshared, unsigned value);
2964 int sem_destroy(sem_t *sem);
2965 int sem_wait(sem_t *sem);
2966 int sem_post(sem_t *sem);
2967 sem_t* sem_open(const char *name, int oflag,
2968 ... [mode_t mode, unsigned value]);
2969 [complete with its idiotic semantics]
2970 int sem_close(sem_t* sem);
2973 int sem_trywait(sem_t *sem);
2974 int sem_timedwait(sem_t *restrict sem,
2975 const struct timespec *restrict abs_timeout);
2978 //-----------------------------------------------------------
2979 // glibc: sem_init@@GLIBC_2.2.5
2980 // glibc: sem_init@@GLIBC_2.1
2981 // glibc: sem_init@GLIBC_2.0
2983 // Solaris: sema_init (sem_init is built on top of sem_init)
2984 // FreeBSD: sem_init (libc)
2986 #if !defined(VGO_solaris)
2987 __attribute__((noinline
))
2988 static int sem_init_WRK(sem_t
* sem
, int pshared
, unsigned long value
)
2992 VALGRIND_GET_ORIG_FN(fn
);
2994 if (TRACE_SEM_FNS
) {
2995 fprintf(stderr
, "<< sem_init(%p,%d,%lu) ", sem
,pshared
,value
);
2999 CALL_FN_W_WWW(ret
, fn
, sem
,pshared
,value
);
3002 DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST
,
3003 sem_t
*, sem
, unsigned long, value
);
3005 DO_PthAPIerror( "sem_init", errno
);
3008 if (TRACE_SEM_FNS
) {
3009 fprintf(stderr
, " sem_init -> %d >>\n", ret
);
3015 #if defined(VGO_linux)
3016 PTH_FUNC(int, semZuinitZAZa
, // sem_init@*
3017 sem_t
* sem
, int pshared
, unsigned long value
) {
3018 return sem_init_WRK(sem
, pshared
, value
);
3020 #elif defined(VGO_darwin)
3021 PTH_FUNC(int, semZuinit
, // sem_init
3022 sem_t
* sem
, int pshared
, unsigned long value
) {
3023 return sem_init_WRK(sem
, pshared
, value
);
3025 #elif defined(VGO_freebsd)
3026 LIBC_FUNC(int, semZuinit
, // sem_init
3027 sem_t
* sem
, int pshared
, unsigned long value
) {
3028 return sem_init_WRK(sem
, pshared
, value
);
3031 # error "Unsupported OS"
3034 #else /* VGO_solaris */
3035 PTH_FUNC(int, semaZuinit
, // sema_init
3043 VALGRIND_GET_ORIG_FN(fn
);
3045 if (TRACE_SEM_FNS
) {
3046 fprintf(stderr
, "<< sema_init(%p, %d, %u) ", sem
, type
, value
);
3050 CALL_FN_W_WWWW(ret
, fn
, sem
, value
, type
, arg
);
3053 DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST
,
3054 sema_t
*, sem
, Word
, value
);
3056 DO_PthAPIerror("sema_init", ret
);
3059 if (TRACE_SEM_FNS
) {
3060 fprintf(stderr
, " sema_init -> %d >>\n", ret
);
3066 #endif /* VGO_solaris */
3069 //-----------------------------------------------------------
3070 // glibc: sem_destroy@GLIBC_2.0
3071 // glibc: sem_destroy@@GLIBC_2.1
3072 // glibc: sem_destroy@@GLIBC_2.2.5
3073 // darwin: sem_destroy
3074 // Solaris: sema_destroy (sem_destroy is built on top of sema_destroy)
3075 // FreeBSD: sem_destroy (libc)
3076 __attribute__((noinline
))
3077 static int sem_destroy_WRK(sem_t
* sem
)
3081 VALGRIND_GET_ORIG_FN(fn
);
3083 if (TRACE_SEM_FNS
) {
3084 fprintf(stderr
, "<< sem_destroy(%p) ", sem
);
3088 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE
, sem_t
*, sem
);
3090 CALL_FN_W_W(ret
, fn
, sem
);
3093 DO_PthAPIerror( "sem_destroy", SEM_ERROR
);
3096 if (TRACE_SEM_FNS
) {
3097 fprintf(stderr
, " sem_destroy -> %d >>\n", ret
);
3103 #if defined(VGO_linux)
3104 PTH_FUNC(int, semZudestroyZAZa
, // sem_destroy*
3106 return sem_destroy_WRK(sem
);
3108 #elif defined(VGO_darwin)
3109 PTH_FUNC(int, semZudestroy
, // sem_destroy
3111 return sem_destroy_WRK(sem
);
3113 #elif defined(VGO_freebsd)
3114 LIBC_FUNC(int, semZudestroy
, // sem_destroy
3116 return sem_destroy_WRK(sem
);
3118 #elif defined(VGO_solaris)
3119 PTH_FUNC(int, semaZudestroy
, // sema_destroy
3121 return sem_destroy_WRK(sem
);
3124 # error "Unsupported OS"
3128 //-----------------------------------------------------------
3130 // glibc: sem_wait@GLIBC_2.0
3131 // glibc: sem_wait@@GLIBC_2.1
3133 // darwin: sem_wait$NOCANCEL$UNIX2003
3134 // darwin: sem_wait$UNIX2003
3135 // Solaris: sema_wait (sem_wait is built on top of sema_wait)
3136 // FreeBSD: sem_wait (libc)
3138 /* wait: decrement semaphore - acquire lockage */
3139 __attribute__((noinline
))
3140 static int sem_wait_WRK(sem_t
* sem
)
3144 VALGRIND_GET_ORIG_FN(fn
);
3146 if (TRACE_SEM_FNS
) {
3147 fprintf(stderr
, "<< sem_wait(%p) ", sem
);
3151 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_WAIT_PRE
, sem_t
*,sem
);
3153 CALL_FN_W_W(ret
, fn
, sem
);
3155 DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_WAIT_POST
, sem_t
*,sem
,
3156 long, (ret
== 0) ? True
: False
);
3159 DO_PthAPIerror( "sem_wait", SEM_ERROR
);
3162 if (TRACE_SEM_FNS
) {
3163 fprintf(stderr
, " sem_wait -> %d >>\n", ret
);
3169 #if defined(VGO_linux)
3170 PTH_FUNC(int, semZuwait
, sem_t
* sem
) { /* sem_wait */
3171 return sem_wait_WRK(sem
);
3173 PTH_FUNC(int, semZuwaitZAZa
, sem_t
* sem
) { /* sem_wait@* */
3174 return sem_wait_WRK(sem
);
3176 #elif defined(VGO_darwin)
3177 PTH_FUNC(int, semZuwait
, sem_t
* sem
) { /* sem_wait */
3178 return sem_wait_WRK(sem
);
3180 PTH_FUNC(int, semZuwaitZDZa
, sem_t
* sem
) { /* sem_wait$* */
3181 return sem_wait_WRK(sem
);
3183 #elif defined(VGO_freebsd)
3184 LIBC_FUNC(int, semZuwait
, sem_t
* sem
) { /* sem_wait */
3185 return sem_wait_WRK(sem
);
3187 #elif defined(VGO_solaris)
3188 PTH_FUNC(int, semaZuwait
, sem_t
*sem
) { /* sema_wait */
3189 return sem_wait_WRK(sem
);
3192 # error "Unsupported OS"
3195 //-----------------------------------------------------------
3196 // glibc: sem_trywait
3197 // glibc: sem_trywait@GLIBC_2.0
3198 // glibc: sem_trywait@@GLIBC_2.1
3199 // darwin: sem_trywait
3200 // Solaris: sema_trywait (sem_teywait is built on top of sema_trywait)
3201 // FreeBSD: sem_trywait (libc)
3203 /* trywait: decrement semaphore if non-zero otherwise return error */
3204 __attribute__((noinline
))
3205 static int sem_trywait_WRK(sem_t
* sem
)
3209 VALGRIND_GET_ORIG_FN(fn
);
3211 if (TRACE_SEM_FNS
) {
3212 fprintf(stderr
, "<< sem_trywait(%p) ", sem
);
3216 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_WAIT_PRE
, sem_t
*,sem
);
3218 CALL_FN_W_W(ret
, fn
, sem
);
3220 DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_WAIT_POST
, sem_t
*,sem
,
3221 long, (ret
== 0) ? True
: False
);
3224 DO_PthAPIerror( "sem_trywait", SEM_ERROR
);
3227 if (TRACE_SEM_FNS
) {
3228 fprintf(stderr
, " sem_trywait -> %d >>\n", ret
);
3235 #if defined(VGO_linux)
3236 PTH_FUNC(int, semZutrywait
, sem_t
* sem
) { /* sem_trywait */
3237 return sem_trywait_WRK(sem
);
3239 PTH_FUNC(int, semZutrywaitZAZa
, sem_t
* sem
) { /* sem_trywait@* */
3240 return sem_trywait_WRK(sem
);
3242 #elif defined(VGO_darwin)
3243 PTH_FUNC(int, semZutrywait
, sem_t
* sem
) { /* sem_trywait */
3244 return sem_wait_WRK(sem
);
3246 #elif defined(VGO_freebsd)
3247 LIBC_FUNC(int, semZutrywait
, sem_t
* sem
) { /* sem_trywait */
3248 return sem_trywait_WRK(sem
);
3250 #elif defined(VGO_solaris)
3251 PTH_FUNC(int, semaZutrywait
, sem_t
*sem
) { /* sema_trywait */
3252 return sem_trywait_WRK(sem
);
3255 # error "Unsupported OS"
3258 //-----------------------------------------------------------
3259 // glibc: sem_timedwait
3260 // glibc: sem_timedwait@GLIBC_2.0
3261 // glibc: sem_timedwait@@GLIBC_2.1
3262 // darwin: does not exist
3263 // Solaris: sema_timedwait (sem_timedwait is built on top of sema_timedwait)
3264 // FreeBSD: sem_timedwait (libc)
3266 #if !defined(VGO_darwin)
3267 /* timedwait: decrement semaphore if non-zero otherwise wait for specified
3268 time then return an error */
3269 __attribute__((noinline
))
3270 static int sem_timedwait_WRK(sem_t
* sem
, const struct timespec
* abs_timeout
)
3274 VALGRIND_GET_ORIG_FN(fn
);
3276 if (TRACE_SEM_FNS
) {
3277 fprintf(stderr
, "<< sem_timedwait(%p, %p) ", sem
, abs_timeout
);
3281 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_WAIT_PRE
, sem_t
*,sem
);
3283 CALL_FN_W_WW(ret
, fn
, sem
, abs_timeout
);
3285 DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_WAIT_POST
, sem_t
*,sem
,
3286 long, (ret
== 0) ? True
: False
);
3289 DO_PthAPIerror( "sem_timedwait", SEM_ERROR
);
3292 if (TRACE_SEM_FNS
) {
3293 fprintf(stderr
, " sem_timedwait -> %d >>\n", ret
);
3300 #if defined(VGO_linux)
3301 PTH_FUNC(int, semZutimedwait
, sem_t
* sem
, const struct timespec
* abs_timeout
) { /* sem_timedwait */
3302 return sem_timedwait_WRK(sem
, abs_timeout
);
3304 PTH_FUNC(int, semZutimedwaitZAZa
, sem_t
* sem
, const struct timespec
* abs_timeout
) { /* sem_timedwait@* */
3305 return sem_timedwait_WRK(sem
, abs_timeout
);
3307 #elif defined(VGO_freebsd)
3308 LIBC_FUNC(int, semZutimedwait
, sem_t
* sem
, const struct timespec
* abs_timeout
) { /* sem_timedwait */
3309 return sem_timedwait_WRK(sem
, abs_timeout
);
3311 #elif defined(VGO_solaris)
3312 PTH_FUNC(int, semaZutimedwait
, sem_t
*sem
, const struct timespec
* abs_timeout
) { /* sema_timedwait */
3313 return sem_timedwait_WRK(sem
, abs_timeout
);
3316 # error "Unsupported OS"
3318 #endif // not VGO_darwin
3320 //-----------------------------------------------------------
3321 // glibc: does not exist
3322 // darwin: does not exist
3323 // Solaris: does not exist
3324 // FreeBSD: sem_clockwait_np (libc)
3326 /* clockwait_np: decrement semaphore if non-zero otherwise wait for specified
3327 time then return an error with a flag to select the kind of clock and
3328 a timespec for the remaining time */
3329 #if defined (VGO_freebsd)
3330 __attribute__((noinline
))
3331 static int sem_clockwait_np_WRK(sem_t
* sem
, clockid_t clock_id
, int flags
,
3332 const struct timespec
* rqtp
, struct timespec
* rmtp
)
3336 VALGRIND_GET_ORIG_FN(fn
);
3338 if (TRACE_SEM_FNS
) {
3339 fprintf(stderr
, "<< sem_clockwait_np(%p, %d, %d, %p, %p) ", sem
, clock_id
, flags
, rqtp
, rmtp
);
3343 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_WAIT_PRE
, sem_t
*,sem
);
3345 CALL_FN_W_5W(ret
, fn
, sem
, clock_id
, flags
, rqtp
, rmtp
);
3347 DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_WAIT_POST
, sem_t
*,sem
,
3348 long, (ret
== 0) ? True
: False
);
3351 DO_PthAPIerror( "sem_clockwait_np", SEM_ERROR
);
3354 if (TRACE_SEM_FNS
) {
3355 fprintf(stderr
, " sem_clockwait_np -> %d >>\n", ret
);
3362 LIBC_FUNC(int, semZuclockwaitZunp
, sem_t
* sem
, clockid_t clock_id
, int flags
,
3363 const struct timespec
* rqtp
, struct timespec
* rmtp
) { /* sem_clockwait_np */
3364 return sem_clockwait_np_WRK(sem
, clock_id
, flags
, rqtp
, rmtp
);
3368 //-----------------------------------------------------------
3370 // glibc: sem_post@GLIBC_2.0
3371 // glibc: sem_post@@GLIBC_2.1
3373 // Solaris: sema_post (sem_post is built on top of sema_post)
3374 // FreeBSD: sem_post (libc)
3376 /* post: increment semaphore - release lockage */
3377 __attribute__((noinline
))
3378 static int sem_post_WRK(sem_t
* sem
)
3383 VALGRIND_GET_ORIG_FN(fn
);
3385 if (TRACE_SEM_FNS
) {
3386 fprintf(stderr
, "<< sem_post(%p) ", sem
);
3390 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_POST_PRE
, sem_t
*,sem
);
3392 CALL_FN_W_W(ret
, fn
, sem
);
3394 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_POST_POST
, sem_t
*,sem
);
3397 DO_PthAPIerror( "sem_post", SEM_ERROR
);
3400 if (TRACE_SEM_FNS
) {
3401 fprintf(stderr
, " sem_post -> %d >>\n", ret
);
3407 #if defined(VGO_linux)
3408 PTH_FUNC(int, semZupost
, sem_t
* sem
) { /* sem_post */
3409 return sem_post_WRK(sem
);
3411 PTH_FUNC(int, semZupostZAZa
, sem_t
* sem
) { /* sem_post@* */
3412 return sem_post_WRK(sem
);
3414 #elif defined(VGO_darwin)
3415 PTH_FUNC(int, semZupost
, sem_t
* sem
) { /* sem_post */
3416 return sem_post_WRK(sem
);
3418 #elif defined(VGO_freebsd)
3419 LIBC_FUNC(int, semZupost
, sem_t
* sem
) { /* sem_post */
3420 return sem_post_WRK(sem
);
3422 #elif defined(VGO_solaris)
3423 PTH_FUNC(int, semaZupost
, sem_t
*sem
) { /* sema_post */
3424 return sem_post_WRK(sem
);
3427 # error "Unsupported OS"
3431 //-----------------------------------------------------------
3434 // Solaris: sem_open
3435 // FreeBSD: sem_open
3437 #if defined(VGO_freebsd)
3438 LIBC_FUNC(sem_t
*, semZuopen
,
3439 const char* name
, long oflag
,
3440 long mode
, unsigned long value
)
3442 PTH_FUNC(sem_t
*, semZuopen
,
3443 const char* name
, long oflag
,
3444 long mode
, unsigned long value
)
3447 /* A copy of sem_init_WRK (more or less). Is this correct? */
3450 VALGRIND_GET_ORIG_FN(fn
);
3452 if (TRACE_SEM_FNS
) {
3453 fprintf(stderr
, "<< sem_open(\"%s\",%ld,%lx,%lu) ",
3454 name
,oflag
,mode
,value
);
3458 CALL_FN_W_WWWW(ret
, fn
, name
,oflag
,mode
,value
);
3460 if (ret
!= SEM_FAILED
&& (oflag
& O_CREAT
)) {
3461 DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST
,
3462 sem_t
*, ret
, unsigned long, value
);
3464 if (ret
== SEM_FAILED
) {
3465 DO_PthAPIerror( "sem_open", errno
);
3468 if (TRACE_SEM_FNS
) {
3469 fprintf(stderr
, " sem_open -> %p >>\n", ret
);
3477 //-----------------------------------------------------------
3479 // darwin: sem_close
3480 // Solaris: sem_close
3481 // FreeBSD: sem_close
3482 #if defined (VGO_freebsd)
3483 LIBC_FUNC(int, sem_close
, sem_t
* sem
)
3485 PTH_FUNC(int, sem_close
, sem_t
* sem
)
3490 VALGRIND_GET_ORIG_FN(fn
);
3492 if (TRACE_SEM_FNS
) {
3493 fprintf(stderr
, "<< sem_close(%p) ", sem
);
3497 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE
, sem_t
*, sem
);
3499 CALL_FN_W_W(ret
, fn
, sem
);
3502 DO_PthAPIerror( "sem_close", errno
);
3505 if (TRACE_SEM_FNS
) {
3506 fprintf(stderr
, " close -> %d >>\n", ret
);
3514 /*----------------------------------------------------------------*/
3515 /*--- Qt 4 threading functions (w/ GNU name mangling) ---*/
3516 /*----------------------------------------------------------------*/
3522 QMutex::tryLock(int)
3524 QMutex::QMutex(QMutex::RecursionMode) _ZN6QMutexC1ENS_13RecursionModeE
3525 QMutex::QMutex(QMutex::RecursionMode) _ZN6QMutexC2ENS_13RecursionModeE
3526 QMutex::~QMutex() _ZN6QMutexD1Ev
3527 QMutex::~QMutex() _ZN6QMutexD2Ev
3530 QReadWriteLock::lockForRead()
3531 QReadWriteLock::lockForWrite()
3532 QReadWriteLock::unlock()
3533 QReadWriteLock::tryLockForRead(int)
3534 QReadWriteLock::tryLockForRead()
3535 QReadWriteLock::tryLockForWrite(int)
3536 QReadWriteLock::tryLockForWrite()
3538 QWaitCondition::wait(QMutex*, unsigned long)
3539 QWaitCondition::wakeAll()
3540 QWaitCondition::wakeOne()
3544 /* More comments, 19 Nov 08, based on assessment of qt-4.5.0TP1,
3547 It's apparently only necessary to intercept QMutex, since that is
3548 not implemented using pthread_mutex_t; instead Qt4 has its own
3549 implementation based on atomics (to check the non-contended case)
3550 and pthread_cond_wait (to wait in the contended case).
3552 QReadWriteLock is built on top of QMutex, counters, and a wait
3553 queue. So we don't need to handle it specially once QMutex
3554 handling is correct -- presumably the dependencies through QMutex
3555 are sufficient to avoid any false race reports. On the other hand,
3556 it is an open question whether too many dependencies are observed
3557 -- in which case we may miss races (false negatives). I suspect
3558 this is likely to be the case, unfortunately.
3560 QWaitCondition is built on pthread_cond_t, pthread_mutex_t, QMutex
3561 and QReadWriteLock. Same compositional-correctness justificiation
3562 and limitations as fro QReadWriteLock.
3564 Ditto QSemaphore (from cursory examination).
3566 Does it matter that only QMutex is handled directly? Open
3567 question. From testing with drd/tests/qt4_* and with KDE4 apps, it
3568 appears that no false errors are reported; however it is not clear
3569 if this is causing false negatives.
3571 Another problem with Qt4 is thread exiting. Threads are created
3572 with pthread_create (fine); but they detach and simply exit when
3573 done. There is no use of pthread_join, and the provided
3574 wait-for-a-thread-to-exit mechanism (QThread::wait, I believe)
3575 relies on a system of mutexes and flags. I suspect this also
3576 causes too many dependencies to appear. Consequently H sometimes
3577 fails to detect races at exit in some very short-lived racy
3578 programs, because it appears that a thread can exit _and_ have an
3579 observed dependency edge back to the main thread (presumably)
3580 before the main thread reaps the child (that is, calls
3583 This theory is supported by the observation that if all threads are
3584 made to wait at a pthread_barrier_t immediately before they exit,
3585 then H's detection of races in such programs becomes reliable;
3586 without the barrier, it is varies from run to run, depending
3587 (according to investigation) on whether aforementioned
3588 exit-before-reaping behaviour happens or not.
3590 Finally, why is it necessary to intercept the QMutex constructors
3591 and destructors? The constructors are intercepted only as a matter
3592 of convenience, so H can print accurate "first observed at"
3593 clauses. However, it is actually necessary to intercept the
3594 destructors (as it is with pthread_mutex_destroy) in order that
3595 locks get removed from LAOG when they are destroyed.
3598 // soname is libQtCore.so.4 ; match against libQtCore.so*
3599 #define QT4_FUNC(ret_ty, f, args...) \
3600 ret_ty I_WRAP_SONAME_FNNAME_ZU(libQtCoreZdsoZa,f)(args); \
3601 ret_ty I_WRAP_SONAME_FNNAME_ZU(libQtCoreZdsoZa,f)(args)
3603 // soname is libQt5Core.so.4 ; match against libQt5Core.so*
3604 #define QT5_FUNC(ret_ty, f, args...) \
3605 ret_ty I_WRAP_SONAME_FNNAME_ZU(libQt5CoreZdsoZa,f)(args); \
3606 ret_ty I_WRAP_SONAME_FNNAME_ZU(libQt5CoreZdsoZa,f)(args)
3608 //-----------------------------------------------------------
3610 __attribute__((noinline
))
3611 static void QMutex_lock_WRK(void* self
)
3614 VALGRIND_GET_ORIG_FN(fn
);
3615 if (TRACE_QT4_FNS
) {
3616 fprintf(stderr
, "<< QMutex::lock %p", self
); fflush(stderr
);
3619 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE
,
3620 void*,self
, long,0/*!isTryLock*/);
3622 CALL_FN_v_W(fn
, self
);
3624 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST
,
3625 void *, self
, long, True
);
3627 if (TRACE_QT4_FNS
) {
3628 fprintf(stderr
, " :: Q::lock done >>\n");
3632 QT4_FUNC(void, _ZN6QMutex4lockEv
, void* self
) {
3633 QMutex_lock_WRK(self
);
3635 QT5_FUNC(void, _ZN6QMutex4lockEv
, void* self
) {
3636 QMutex_lock_WRK(self
);
3639 //-----------------------------------------------------------
3641 __attribute__((noinline
))
3642 static void QMutex_unlock_WRK(void* self
)
3645 VALGRIND_GET_ORIG_FN(fn
);
3647 if (TRACE_QT4_FNS
) {
3648 fprintf(stderr
, "<< QMutex::unlock %p", self
); fflush(stderr
);
3651 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE
,
3654 CALL_FN_v_W(fn
, self
);
3656 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST
,
3659 if (TRACE_QT4_FNS
) {
3660 fprintf(stderr
, " Q::unlock done >>\n");
3664 QT4_FUNC(void, _ZN6QMutex6unlockEv
, void* self
) {
3665 QMutex_unlock_WRK(self
);
3667 QT5_FUNC(void, _ZN6QMutex6unlockEv
, void* self
) {
3668 QMutex_unlock_WRK(self
);
3671 //-----------------------------------------------------------
3672 // bool QMutex::tryLock()
3673 // using 'long' to mimic C++ 'bool'
3674 __attribute__((noinline
))
3675 static long QMutex_tryLock_WRK(void* self
)
3679 VALGRIND_GET_ORIG_FN(fn
);
3680 if (TRACE_QT4_FNS
) {
3681 fprintf(stderr
, "<< QMutex::tryLock %p", self
); fflush(stderr
);
3684 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE
,
3685 void*,self
, long,1/*isTryLock*/);
3687 CALL_FN_W_W(ret
, fn
, self
);
3689 // assumes that only the low 8 bits of the 'bool' are significant
3690 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST
,
3691 void *, self
, long, (ret
& 0xFF) ? True
: False
);
3693 if (TRACE_QT4_FNS
) {
3694 fprintf(stderr
, " :: Q::tryLock -> %lu >>\n", ret
);
3700 QT4_FUNC(long, _ZN6QMutex7tryLockEv
, void* self
) {
3701 return QMutex_tryLock_WRK(self
);
3703 QT5_FUNC(long, _ZN6QMutex7tryLockEv
, void* self
) {
3704 return QMutex_tryLock_WRK(self
);
3707 //-----------------------------------------------------------
3708 // bool QMutex::tryLock(int)
3709 // using 'long' to mimic C++ 'bool'
3710 __attribute__((noinline
))
3711 static long QMutex_tryLock_int_WRK(void* self
, long arg2
)
3715 VALGRIND_GET_ORIG_FN(fn
);
3716 if (TRACE_QT4_FNS
) {
3717 fprintf(stderr
, "<< QMutex::tryLock(int) %p %d", self
, (int)arg2
);
3721 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE
,
3722 void*,self
, long,1/*isTryLock*/);
3724 CALL_FN_W_WW(ret
, fn
, self
,arg2
);
3726 // assumes that only the low 8 bits of the 'bool' are significant
3727 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST
,
3728 void *, self
, long, (ret
& 0xFF) ? True
: False
);
3730 if (TRACE_QT4_FNS
) {
3731 fprintf(stderr
, " :: Q::tryLock(int) -> %lu >>\n", ret
);
3737 QT4_FUNC(long, _ZN6QMutex7tryLockEi
, void* self
, long arg2
) {
3738 return QMutex_tryLock_int_WRK(self
, arg2
);
3740 QT5_FUNC(long, _ZN6QMutex7tryLockEi
, void* self
, long arg2
) {
3741 return QMutex_tryLock_int_WRK(self
, arg2
);
3744 //-----------------------------------------------------------
3745 // It's not really very clear what the args are here. But from
3746 // a bit of dataflow analysis of the generated machine code of
3747 // the original function, it appears this takes two args, and
3748 // returns nothing. Nevertheless preserve return value just in
3749 // case. A bit of debug printing indicates that the first arg
3750 // is that of the mutex and the second is either zero or one,
3751 // probably being the recursion mode, therefore.
3752 // QMutex::QMutex(QMutex::RecursionMode) ("C1ENS" variant)
3753 __attribute__((noinline
))
3754 static void* QMutex_constructor_WRK(void* mutex
, long recmode
)
3758 VALGRIND_GET_ORIG_FN(fn
);
3759 CALL_FN_W_WW(ret
, fn
, mutex
, recmode
);
3760 // fprintf(stderr, "QMutex constructor 1: %p <- %p %p\n", ret, arg1, arg2);
3761 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST
,
3762 void*,mutex
, long,1/*mbRec*/);
3766 QT4_FUNC(void*, _ZN6QMutexC1ENS_13RecursionModeE
, void* self
, long recmode
) {
3767 return QMutex_constructor_WRK(self
, recmode
);
3769 QT5_FUNC(void*, _ZN6QMutexC1ENS_13RecursionModeE
, void* self
, long recmode
) {
3770 return QMutex_constructor_WRK(self
, recmode
);
3773 //-----------------------------------------------------------
3774 // QMutex::~QMutex() ("D1Ev" variant)
3775 __attribute__((noinline
))
3776 static void* QMutex_destructor_WRK(void* mutex
)
3780 VALGRIND_GET_ORIG_FN(fn
);
3781 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE
,
3783 CALL_FN_W_W(ret
, fn
, mutex
);
3787 QT4_FUNC(void*, _ZN6QMutexD1Ev
, void* self
) {
3788 return QMutex_destructor_WRK(self
);
3790 QT5_FUNC(void*, _ZN6QMutexD1Ev
, void* self
) {
3791 return QMutex_destructor_WRK(self
);
3794 //-----------------------------------------------------------
3795 // QMutex::QMutex(QMutex::RecursionMode) ("C2ENS" variant)
3796 QT4_FUNC(void*, _ZN6QMutexC2ENS_13RecursionModeE
,
3802 /* Android's gcc behaves like it doesn't know that assert(0)
3803 never returns. Hence: */
3807 QT5_FUNC(void*, _ZN6QMutexC2ENS_13RecursionModeE
, void* self
, long recmode
)
3814 //-----------------------------------------------------------
3815 // QMutex::~QMutex() ("D2Ev" variant)
3816 QT4_FUNC(void*, _ZN6QMutexD2Ev
, void* mutex
)
3819 /* Android's gcc behaves like it doesn't know that assert(0)
3820 never returns. Hence: */
3824 QT5_FUNC(void*, _ZN6QMutexD2Ev
, void* self
)
3831 // QReadWriteLock is not intercepted directly. See comments
3834 //// QReadWriteLock::lockForRead()
3835 //// _ZN14QReadWriteLock11lockForReadEv == QReadWriteLock::lockForRead()
3836 //QT4_FUNC(void, ZuZZN14QReadWriteLock11lockForReadEv,
3837 // // _ZN14QReadWriteLock11lockForReadEv
3841 // VALGRIND_GET_ORIG_FN(fn);
3842 // if (TRACE_QT4_FNS) {
3843 // fprintf(stderr, "<< QReadWriteLock::lockForRead %p", self);
3847 // DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
3849 // long,0/*!isW*/, long,0/*!isTryLock*/);
3851 // CALL_FN_v_W(fn, self);
3853 // DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
3854 // void*,self, long,0/*!isW*/, long, True);
3856 // if (TRACE_QT4_FNS) {
3857 // fprintf(stderr, " :: Q::lockForRead :: done >>\n");
3861 //// QReadWriteLock::lockForWrite()
3862 //// _ZN14QReadWriteLock12lockForWriteEv == QReadWriteLock::lockForWrite()
3863 //QT4_FUNC(void, ZuZZN14QReadWriteLock12lockForWriteEv,
3864 // // _ZN14QReadWriteLock12lockForWriteEv
3868 // VALGRIND_GET_ORIG_FN(fn);
3869 // if (TRACE_QT4_FNS) {
3870 // fprintf(stderr, "<< QReadWriteLock::lockForWrite %p", self);
3874 // DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
3876 // long,1/*isW*/, long,0/*!isTryLock*/);
3878 // CALL_FN_v_W(fn, self);
3880 // DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
3881 // void*,self, long,1/*isW*/, long, True);
3883 // if (TRACE_QT4_FNS) {
3884 // fprintf(stderr, " :: Q::lockForWrite :: done >>\n");
3888 //// QReadWriteLock::unlock()
3889 //// _ZN14QReadWriteLock6unlockEv == QReadWriteLock::unlock()
3890 //QT4_FUNC(void, ZuZZN14QReadWriteLock6unlockEv,
3891 // // _ZN14QReadWriteLock6unlockEv
3895 // VALGRIND_GET_ORIG_FN(fn);
3896 // if (TRACE_QT4_FNS) {
3897 // fprintf(stderr, "<< QReadWriteLock::unlock %p", self);
3901 // DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE,
3904 // CALL_FN_v_W(fn, self);
3906 // DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST,
3909 // if (TRACE_QT4_FNS) {
3910 // fprintf(stderr, " :: Q::unlock :: done >>\n");
3915 /*----------------------------------------------------------------*/
3916 /*--- Replacements for basic string functions, that don't ---*/
3917 /*--- overrun the input arrays. ---*/
3918 /*----------------------------------------------------------------*/
3920 #include "../shared/vg_replace_strmem.c"
3922 /*--------------------------------------------------------------------*/
3923 /*--- end hg_intercepts.c ---*/
3924 /*--------------------------------------------------------------------*/