1 /*--------------------------------------------------------------------*/
2 /*--- Client-space code for DRD. drd_pthread_intercepts.c ---*/
3 /*--------------------------------------------------------------------*/
6 This file is part of DRD, a thread error detector.
8 Copyright (C) 2006-2013 Bart Van Assche <bvanassche@acm.org>.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2 of the
13 License, or (at your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 The GNU General Public License is contained in the file COPYING.
28 /* ---------------------------------------------------------------------
29 ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU.
31 These functions are not called directly - they're the targets of code
32 redirection or load notifications (see pub_core_redir.h for info).
33 They're named weirdly so that the intercept code can find them when the
34 shared object is initially loaded.
36 Note that this filename has the "drd_" prefix because it can appear
37 in stack traces, and the "drd_" makes it a little clearer that it
38 originates from Valgrind.
39 ------------------------------------------------------------------ */
42 * Define _GNU_SOURCE to make sure that pthread_spinlock_t is available when
43 * compiling with older glibc versions (2.3 or before).
49 #include <assert.h> /* assert() */
51 #include <pthread.h> /* pthread_mutex_t */
52 #include <semaphore.h> /* sem_t */
53 #include <stdint.h> /* uintptr_t */
54 #include <stdio.h> /* fprintf() */
55 #include <stdlib.h> /* malloc(), free() */
56 #include <unistd.h> /* confstr() */
57 #include "config.h" /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP etc. */
58 #ifdef HAVE_USABLE_LINUX_FUTEX_H
59 #include <asm/unistd.h> /* __NR_futex */
60 #include <linux/futex.h> /* FUTEX_WAIT */
61 #ifndef FUTEX_PRIVATE_FLAG
62 #define FUTEX_PRIVATE_FLAG 0
65 #include "drd_basics.h" /* DRD_() */
66 #include "drd_clientreq.h"
67 #include "pub_tool_redir.h" /* VG_WRAP_FUNCTION_ZZ() */
71 * Notes regarding thread creation:
72 * - sg_init() runs on the context of the created thread and copies the vector
73 * clock of the creator thread. This only works reliably if the creator
74 * thread waits until this copy has been performed.
75 * - DRD_(thread_compute_minimum_vc)() does not take the vector clocks into
76 * account that are involved in thread creation and for which the
77 * corresponding thread has not yet been created. So not waiting until the
78 * created thread has been started would make it possible that segments get
79 * discarded that should not yet be discarded. Or: some data races are not
84 * Macro for generating a Valgrind interception function.
85 * @param[in] ret_ty Return type of the function to be generated.
86 * @param[in] zf Z-encoded name of the interception function.
87 * @param[in] implf Name of the function that implements the intercept.
88 * @param[in] arg_decl Argument declaration list enclosed in parentheses.
89 * @param[in] argl Argument list enclosed in parentheses.
92 static int never_true
;
93 #define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl) \
94 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl; \
95 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl \
97 ret_ty pth_func_result = implf argl; \
98 /* Apparently inserting a function call in wrapper functions */ \
99 /* is sufficient to avoid misaligned stack errors. */ \
102 return pth_func_result; \
105 #define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl) \
106 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl; \
107 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl \
108 { return implf argl; }
112 * Macro for generating three Valgrind interception functions: one with the
113 * Z-encoded name zf, one with ZAZa ("@*") appended to the name zf and one
114 * with ZDZa ("$*") appended to the name zf. The second generated interception
115 * function will intercept versioned symbols on Linux, and the third will
116 * intercept versioned symbols on Darwin.
118 #define PTH_FUNCS(ret_ty, zf, implf, argl_decl, argl) \
119 PTH_FUNC(ret_ty, zf, implf, argl_decl, argl); \
120 PTH_FUNC(ret_ty, zf ## ZAZa, implf, argl_decl, argl); \
121 PTH_FUNC(ret_ty, zf ## ZDZa, implf, argl_decl, argl);
124 * Not inlining one of the intercept functions will cause the regression
125 * tests to fail because this would cause an additional stackfram to appear
126 * in the output. The __always_inline macro guarantees that inlining will
127 * happen, even when compiling with optimization disabled.
129 #undef __always_inline /* since already defined in <cdefs.h> */
130 #if __GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 2
131 #define __always_inline __inline__ __attribute__((always_inline))
133 #define __always_inline __inline__
136 /* Local data structures. */
139 pthread_mutex_t mutex
;
146 void* (*start
)(void*);
149 DrdSema
* wrapper_started
;
150 } DrdPosixThreadArgs
;
153 /* Local function declarations. */
155 static void DRD_(init
)(void) __attribute__((constructor
));
156 static void DRD_(check_threading_library
)(void);
157 static void DRD_(set_main_thread_state
)(void);
158 static void DRD_(sema_init
)(DrdSema
* sema
);
159 static void DRD_(sema_destroy
)(DrdSema
* sema
);
160 static void DRD_(sema_down
)(DrdSema
* sema
);
161 static void DRD_(sema_up
)(DrdSema
* sema
);
164 /* Function definitions. */
167 * Shared library initialization function. The function init() is called after
168 * dlopen() has loaded the shared library with DRD client intercepts because
169 * the constructor attribute was specified in the declaration of this function.
170 * Note: do specify the -nostdlib option to gcc when linking this code into a
171 * shared library because doing so would cancel the effect of the constructor
172 * attribute ! Using the gcc option -nodefaultlibs is fine because this last
173 * option preserves the shared library initialization code that calls
174 * constructor and destructor functions.
176 static void DRD_(init
)(void)
178 DRD_(check_threading_library
)();
179 DRD_(set_main_thread_state
)();
182 static __always_inline
void DRD_(ignore_mutex_ordering
)(pthread_mutex_t
*mutex
)
184 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_IGNORE_MUTEX_ORDERING
,
188 static void DRD_(sema_init
)(DrdSema
* sema
)
190 DRD_IGNORE_VAR(*sema
);
191 pthread_mutex_init(&sema
->mutex
, NULL
);
192 DRD_(ignore_mutex_ordering
)(&sema
->mutex
);
197 static void DRD_(sema_destroy
)(DrdSema
* sema
)
199 pthread_mutex_destroy(&sema
->mutex
);
202 static void DRD_(sema_down
)(DrdSema
* sema
)
206 pthread_mutex_lock(&sema
->mutex
);
207 if (sema
->counter
== 0) {
209 while (sema
->counter
== 0) {
210 pthread_mutex_unlock(&sema
->mutex
);
211 #ifdef HAVE_USABLE_LINUX_FUTEX_H
212 if (syscall(__NR_futex
, (UWord
)&sema
->counter
,
213 FUTEX_WAIT
| FUTEX_PRIVATE_FLAG
, 0) == 0)
219 * Invoke sched_yield() on non-Linux systems, if the futex syscall has
220 * not been invoked or if this code has been built on a Linux system
221 * where __NR_futex is defined and is run on a Linux system that does
222 * not support the futex syscall.
224 if (res
!= 0 && res
!= EWOULDBLOCK
)
226 pthread_mutex_lock(&sema
->mutex
);
231 pthread_mutex_unlock(&sema
->mutex
);
234 static void DRD_(sema_up
)(DrdSema
* sema
)
236 pthread_mutex_lock(&sema
->mutex
);
238 #ifdef HAVE_USABLE_LINUX_FUTEX_H
239 if (sema
->waiters
> 0)
240 syscall(__NR_futex
, (UWord
)&sema
->counter
,
241 FUTEX_WAKE
| FUTEX_PRIVATE_FLAG
, 1);
243 pthread_mutex_unlock(&sema
->mutex
);
247 * POSIX threads and DRD each have their own mutex type identification.
248 * Convert POSIX threads' mutex type to DRD's mutex type. In the code below
249 * if-statements are used to test the value of 'kind' instead of a switch
250 * statement because some of the PTHREAD_MUTEX_ macro's may have the same
253 static MutexT
DRD_(pthread_to_drd_mutex_type
)(int kind
)
256 * See also PTHREAD_MUTEX_KIND_MASK_NP in glibc source file
259 kind
&= PTHREAD_MUTEX_RECURSIVE
| PTHREAD_MUTEX_ERRORCHECK
|
260 PTHREAD_MUTEX_NORMAL
| PTHREAD_MUTEX_DEFAULT
;
262 if (kind
== PTHREAD_MUTEX_RECURSIVE
)
263 return mutex_type_recursive_mutex
;
264 else if (kind
== PTHREAD_MUTEX_ERRORCHECK
)
265 return mutex_type_errorcheck_mutex
;
266 else if (kind
== PTHREAD_MUTEX_NORMAL
)
267 return mutex_type_default_mutex
;
268 else if (kind
== PTHREAD_MUTEX_DEFAULT
)
269 return mutex_type_default_mutex
;
270 #if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP)
271 else if (kind
== PTHREAD_MUTEX_ADAPTIVE_NP
)
272 return mutex_type_default_mutex
;
275 return mutex_type_invalid_mutex
;
278 #define IS_ALIGNED(p) (((uintptr_t)(p) & (sizeof(*(p)) - 1)) == 0)
281 * Read the mutex type stored in the client memory used for the mutex
284 * @note This function depends on the implementation of the POSIX threads
285 * library -- the POSIX standard does not define the name of the member in
286 * which the mutex type is stored.
287 * @note The function mutex_type() has been declared inline in order
288 * to avoid that it shows up in call stacks (drd/tests/...exp* files).
289 * @note glibc stores the mutex type in the lowest two bits, and uses the
290 * higher bits for flags like PTHREAD_MUTEXATTR_FLAG_ROBUST and
291 * PTHREAD_MUTEXATTR_FLAG_PSHARED.
293 static __always_inline MutexT
DRD_(mutex_type
)(pthread_mutex_t
* mutex
)
295 #if defined(HAVE_PTHREAD_MUTEX_T__M_KIND)
296 /* glibc + LinuxThreads. */
297 if (IS_ALIGNED(&mutex
->__m_kind
))
299 const int kind
= mutex
->__m_kind
& 3;
300 return DRD_(pthread_to_drd_mutex_type
)(kind
);
302 #elif defined(HAVE_PTHREAD_MUTEX_T__DATA__KIND)
304 if (IS_ALIGNED(&mutex
->__data
.__kind
))
306 const int kind
= mutex
->__data
.__kind
& 3;
307 return DRD_(pthread_to_drd_mutex_type
)(kind
);
311 * Another POSIX threads implementation. The mutex type won't be printed
312 * when enabling --trace-mutex=yes.
315 return mutex_type_unknown
;
319 * Tell DRD whether 'tid' is a joinable thread or a detached thread.
321 static void DRD_(set_joinable
)(const pthread_t tid
, const int joinable
)
323 assert(joinable
== 0 || joinable
== 1);
324 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__SET_JOINABLE
,
325 tid
, joinable
, 0, 0, 0);
328 /** Tell DRD that the calling thread is about to enter pthread_create(). */
329 static __always_inline
void DRD_(entering_pthread_create
)(void)
331 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__ENTERING_PTHREAD_CREATE
,
335 /** Tell DRD that the calling thread has left pthread_create(). */
336 static __always_inline
void DRD_(left_pthread_create
)(void)
338 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LEFT_PTHREAD_CREATE
,
343 * Entry point for newly created threads. This function is called from the
344 * thread created by pthread_create().
346 static void* DRD_(thread_wrapper
)(void* arg
)
348 DrdPosixThreadArgs
* arg_ptr
;
349 DrdPosixThreadArgs arg_copy
;
351 arg_ptr
= (DrdPosixThreadArgs
*)arg
;
354 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__SET_PTHREADID
,
355 pthread_self(), 0, 0, 0, 0);
357 DRD_(set_joinable
)(pthread_self(),
358 arg_copy
.detachstate
== PTHREAD_CREATE_JOINABLE
);
361 * Only set 'wrapper_started' after VG_USERREQ__SET_PTHREADID and
362 * DRD_(set_joinable)() have been invoked to avoid a race with
363 * a pthread_detach() invocation for this thread from another thread.
365 DRD_(sema_up
)(arg_copy
.wrapper_started
);
367 return (arg_copy
.start
)(arg_copy
.arg
);
371 * Return 1 if the LinuxThreads implementation of POSIX Threads has been
372 * detected, and 0 otherwise.
374 * @see For more information about the confstr() function, see also
375 * http://www.opengroup.org/onlinepubs/009695399/functions/confstr.html
377 static int DRD_(detected_linuxthreads
)(void)
380 #if defined(_CS_GNU_LIBPTHREAD_VERSION)
381 /* Linux with a recent glibc. */
384 len
= confstr(_CS_GNU_LIBPTHREAD_VERSION
, buffer
, sizeof(buffer
));
385 assert(len
<= sizeof(buffer
));
386 return len
> 0 && buffer
[0] == 'l';
388 /* Linux without _CS_GNU_LIBPTHREAD_VERSION: most likely LinuxThreads. */
392 /* Another OS than Linux, hence no LinuxThreads. */
398 * Stop and print an error message in case a non-supported threading
399 * library implementation (LinuxThreads) has been detected.
401 static void DRD_(check_threading_library
)(void)
403 if (DRD_(detected_linuxthreads
)())
405 if (getenv("LD_ASSUME_KERNEL"))
408 "Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
409 "the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
410 "after having unset the environment variable LD_ASSUME_KERNEL. Giving up.\n"
416 "Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
417 "the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
418 "after having upgraded to a newer version of your Linux distribution.\n"
427 * The main thread is the only thread not created by pthread_create().
428 * Update DRD's state information about the main thread.
430 static void DRD_(set_main_thread_state
)(void)
432 // Make sure that DRD knows about the main thread's POSIX thread ID.
433 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__SET_PTHREADID
,
434 pthread_self(), 0, 0, 0, 0);
438 * Note: as of today there exist three different versions of pthread_create
440 * - pthread_create@GLIBC_2.0
441 * - pthread_create@@GLIBC_2.1
442 * - pthread_create@@GLIBC_2.2.5
443 * As an example, in libpthread-2.3.4 both pthread_create@GLIBC_2.0 and
444 * pthread_create@@GLIBC_2.1 are defined, while in libpthread-2.9 all three
445 * versions have been implemented. In any glibc version where more than one
446 * pthread_create function has been implemented, older versions call the
447 * newer versions. Or: the pthread_create* wrapper defined below can be
448 * called recursively. Any code in this wrapper should take this in account.
449 * As an example, it is not safe to invoke the DRD_STOP_RECORDING
450 * / DRD_START_RECORDING client requests from the pthread_create wrapper.
451 * See also the implementation of pthread_create@GLIBC_2.0 in
452 * glibc-2.9/nptl/pthread_create.c.
455 static __always_inline
456 int pthread_create_intercept(pthread_t
* thread
, const pthread_attr_t
* attr
,
457 void* (*start
)(void*), void* arg
)
461 DrdSema wrapper_started
;
462 DrdPosixThreadArgs thread_args
;
464 VALGRIND_GET_ORIG_FN(fn
);
466 DRD_(sema_init
)(&wrapper_started
);
467 thread_args
.start
= start
;
468 thread_args
.arg
= arg
;
469 thread_args
.wrapper_started
= &wrapper_started
;
471 * Find out whether the thread will be started as a joinable thread
472 * or as a detached thread. If no thread attributes have been specified,
473 * this means that the new thread will be started as a joinable thread.
475 thread_args
.detachstate
= PTHREAD_CREATE_JOINABLE
;
478 if (pthread_attr_getdetachstate(attr
, &thread_args
.detachstate
) != 0)
481 assert(thread_args
.detachstate
== PTHREAD_CREATE_JOINABLE
482 || thread_args
.detachstate
== PTHREAD_CREATE_DETACHED
);
484 DRD_(entering_pthread_create
)();
485 CALL_FN_W_WWWW(ret
, fn
, thread
, attr
, DRD_(thread_wrapper
), &thread_args
);
486 DRD_(left_pthread_create
)();
489 /* Wait until the thread wrapper started. */
490 DRD_(sema_down
)(&wrapper_started
);
493 DRD_(sema_destroy
)(&wrapper_started
);
495 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_START_NEW_SEGMENT
,
496 pthread_self(), 0, 0, 0, 0);
501 PTH_FUNCS(int, pthreadZucreate
, pthread_create_intercept
,
502 (pthread_t
*thread
, const pthread_attr_t
*attr
,
503 void *(*start
) (void *), void *arg
),
504 (thread
, attr
, start
, arg
));
506 static __always_inline
507 int pthread_join_intercept(pthread_t pt_joinee
, void **thread_return
)
512 VALGRIND_GET_ORIG_FN(fn
);
514 * Avoid that the sys_futex(td->tid) call invoked by the NPTL pthread_join()
515 * implementation triggers a (false positive) race report.
517 ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
518 CALL_FN_W_WW(ret
, fn
, pt_joinee
, thread_return
);
521 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_THREAD_JOIN
,
522 pt_joinee
, 0, 0, 0, 0);
524 ANNOTATE_IGNORE_READS_AND_WRITES_END();
528 PTH_FUNCS(int, pthreadZujoin
, pthread_join_intercept
,
529 (pthread_t pt_joinee
, void **thread_return
),
530 (pt_joinee
, thread_return
));
532 static __always_inline
533 int pthread_detach_intercept(pthread_t pt_thread
)
538 VALGRIND_GET_ORIG_FN(fn
);
539 CALL_FN_W_W(ret
, fn
, pt_thread
);
540 DRD_(set_joinable
)(pt_thread
, 0);
545 PTH_FUNCS(int, pthreadZudetach
, pthread_detach_intercept
,
546 (pthread_t thread
), (thread
));
548 // NOTE: be careful to intercept only pthread_cancel() and not
549 // pthread_cancel_init() on Linux.
551 static __always_inline
552 int pthread_cancel_intercept(pthread_t pt_thread
)
556 VALGRIND_GET_ORIG_FN(fn
);
557 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_THREAD_CANCEL
,
558 pt_thread
, 0, 0, 0, 0);
559 CALL_FN_W_W(ret
, fn
, pt_thread
);
560 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_THREAD_CANCEL
,
561 pt_thread
, ret
==0, 0, 0, 0);
565 PTH_FUNCS(int, pthreadZucancel
, pthread_cancel_intercept
,
566 (pthread_t thread
), (thread
))
568 static __always_inline
569 int pthread_once_intercept(pthread_once_t
*once_control
,
570 void (*init_routine
)(void))
574 VALGRIND_GET_ORIG_FN(fn
);
576 * Ignore any data races triggered by the implementation of pthread_once().
577 * Necessary for Darwin. This is not necessary for Linux but doesn't have
578 * any known adverse effects.
580 DRD_IGNORE_VAR(*once_control
);
581 ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
582 CALL_FN_W_WW(ret
, fn
, once_control
, init_routine
);
583 ANNOTATE_IGNORE_READS_AND_WRITES_END();
584 DRD_STOP_IGNORING_VAR(*once_control
);
588 PTH_FUNCS(int, pthreadZuonce
, pthread_once_intercept
,
589 (pthread_once_t
*once_control
, void (*init_routine
)(void)),
590 (once_control
, init_routine
));
592 static __always_inline
593 int pthread_mutex_init_intercept(pthread_mutex_t
*mutex
,
594 const pthread_mutexattr_t
* attr
)
599 VALGRIND_GET_ORIG_FN(fn
);
600 mt
= PTHREAD_MUTEX_DEFAULT
;
602 pthread_mutexattr_gettype(attr
, &mt
);
603 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_INIT
,
604 mutex
, DRD_(pthread_to_drd_mutex_type
)(mt
),
606 CALL_FN_W_WW(ret
, fn
, mutex
, attr
);
607 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_INIT
,
612 PTH_FUNCS(int, pthreadZumutexZuinit
, pthread_mutex_init_intercept
,
613 (pthread_mutex_t
*mutex
, const pthread_mutexattr_t
* attr
),
616 static __always_inline
617 int pthread_mutex_destroy_intercept(pthread_mutex_t
* mutex
)
621 VALGRIND_GET_ORIG_FN(fn
);
622 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_DESTROY
,
624 CALL_FN_W_W(ret
, fn
, mutex
);
625 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_DESTROY
,
626 mutex
, DRD_(mutex_type
)(mutex
), 0, 0, 0);
630 PTH_FUNCS(int, pthreadZumutexZudestroy
, pthread_mutex_destroy_intercept
,
631 (pthread_mutex_t
*mutex
), (mutex
));
633 static __always_inline
634 int pthread_mutex_lock_intercept(pthread_mutex_t
* mutex
)
638 VALGRIND_GET_ORIG_FN(fn
);
639 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK
,
640 mutex
, DRD_(mutex_type
)(mutex
), 0, 0, 0);
641 CALL_FN_W_W(ret
, fn
, mutex
);
642 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK
,
643 mutex
, ret
== 0, 0, 0, 0);
647 PTH_FUNCS(int, pthreadZumutexZulock
, pthread_mutex_lock_intercept
,
648 (pthread_mutex_t
*mutex
), (mutex
));
650 static __always_inline
651 int pthread_mutex_trylock_intercept(pthread_mutex_t
* mutex
)
655 VALGRIND_GET_ORIG_FN(fn
);
656 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK
,
657 mutex
, DRD_(mutex_type
)(mutex
), 1, 0, 0);
658 CALL_FN_W_W(ret
, fn
, mutex
);
659 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK
,
660 mutex
, ret
== 0, 0, 0, 0);
664 PTH_FUNCS(int, pthreadZumutexZutrylock
, pthread_mutex_trylock_intercept
,
665 (pthread_mutex_t
*mutex
), (mutex
));
667 static __always_inline
668 int pthread_mutex_timedlock_intercept(pthread_mutex_t
*mutex
,
669 const struct timespec
*abs_timeout
)
673 VALGRIND_GET_ORIG_FN(fn
);
674 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK
,
675 mutex
, DRD_(mutex_type
)(mutex
), 0, 0, 0);
676 CALL_FN_W_WW(ret
, fn
, mutex
, abs_timeout
);
677 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK
,
678 mutex
, ret
== 0, 0, 0, 0);
682 PTH_FUNCS(int, pthreadZumutexZutimedlock
, pthread_mutex_timedlock_intercept
,
683 (pthread_mutex_t
*mutex
, const struct timespec
*abs_timeout
),
684 (mutex
, abs_timeout
));
686 static __always_inline
687 int pthread_mutex_unlock_intercept(pthread_mutex_t
*mutex
)
691 VALGRIND_GET_ORIG_FN(fn
);
692 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_UNLOCK
,
693 mutex
, DRD_(mutex_type
)(mutex
), 0, 0, 0);
694 CALL_FN_W_W(ret
, fn
, mutex
);
695 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_UNLOCK
,
700 PTH_FUNCS(int, pthreadZumutexZuunlock
, pthread_mutex_unlock_intercept
,
701 (pthread_mutex_t
*mutex
), (mutex
));
703 static __always_inline
704 int pthread_cond_init_intercept(pthread_cond_t
* cond
,
705 const pthread_condattr_t
* attr
)
709 VALGRIND_GET_ORIG_FN(fn
);
710 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_INIT
,
712 CALL_FN_W_WW(ret
, fn
, cond
, attr
);
713 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_INIT
,
718 PTH_FUNCS(int, pthreadZucondZuinit
, pthread_cond_init_intercept
,
719 (pthread_cond_t
* cond
, const pthread_condattr_t
* attr
),
722 static __always_inline
723 int pthread_cond_destroy_intercept(pthread_cond_t
* cond
)
727 VALGRIND_GET_ORIG_FN(fn
);
728 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_DESTROY
,
730 CALL_FN_W_W(ret
, fn
, cond
);
731 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_DESTROY
,
732 cond
, ret
==0, 0, 0, 0);
736 PTH_FUNCS(int, pthreadZucondZudestroy
, pthread_cond_destroy_intercept
,
737 (pthread_cond_t
* cond
), (cond
));
739 static __always_inline
740 int pthread_cond_wait_intercept(pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
744 VALGRIND_GET_ORIG_FN(fn
);
745 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_WAIT
,
746 cond
, mutex
, DRD_(mutex_type
)(mutex
), 0, 0);
747 CALL_FN_W_WW(ret
, fn
, cond
, mutex
);
748 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_WAIT
,
749 cond
, mutex
, 1, 0, 0);
753 PTH_FUNCS(int, pthreadZucondZuwait
, pthread_cond_wait_intercept
,
754 (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
),
757 static __always_inline
758 int pthread_cond_timedwait_intercept(pthread_cond_t
*cond
,
759 pthread_mutex_t
*mutex
,
760 const struct timespec
* abstime
)
764 VALGRIND_GET_ORIG_FN(fn
);
765 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_WAIT
,
766 cond
, mutex
, DRD_(mutex_type
)(mutex
), 0, 0);
767 CALL_FN_W_WWW(ret
, fn
, cond
, mutex
, abstime
);
768 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_WAIT
,
769 cond
, mutex
, 1, 0, 0);
773 PTH_FUNCS(int, pthreadZucondZutimedwait
, pthread_cond_timedwait_intercept
,
774 (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
775 const struct timespec
* abstime
),
776 (cond
, mutex
, abstime
));
778 // NOTE: be careful to intercept only pthread_cond_signal() and not Darwin's
779 // pthread_cond_signal_thread_np(). The former accepts one argument; the latter
780 // two. Intercepting all pthread_cond_signal* functions will cause only one
781 // argument to be passed to pthread_cond_signal_np() and hence will cause this
782 // last function to crash.
784 static __always_inline
785 int pthread_cond_signal_intercept(pthread_cond_t
* cond
)
789 VALGRIND_GET_ORIG_FN(fn
);
790 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_SIGNAL
,
792 CALL_FN_W_W(ret
, fn
, cond
);
793 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_SIGNAL
,
798 PTH_FUNCS(int, pthreadZucondZusignal
, pthread_cond_signal_intercept
,
799 (pthread_cond_t
* cond
), (cond
));
801 static __always_inline
802 int pthread_cond_broadcast_intercept(pthread_cond_t
* cond
)
806 VALGRIND_GET_ORIG_FN(fn
);
807 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_BROADCAST
,
809 CALL_FN_W_W(ret
, fn
, cond
);
810 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_BROADCAST
,
815 PTH_FUNCS(int, pthreadZucondZubroadcast
, pthread_cond_broadcast_intercept
,
816 (pthread_cond_t
* cond
), (cond
));
818 #if defined(HAVE_PTHREAD_SPIN_LOCK) \
819 && !defined(DISABLE_PTHREAD_SPINLOCK_INTERCEPT)
820 static __always_inline
821 int pthread_spin_init_intercept(pthread_spinlock_t
*spinlock
, int pshared
)
825 VALGRIND_GET_ORIG_FN(fn
);
826 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK
,
827 spinlock
, 0, 0, 0, 0);
828 CALL_FN_W_WW(ret
, fn
, spinlock
, pshared
);
829 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK
,
830 spinlock
, 0, 0, 0, 0);
834 PTH_FUNCS(int, pthreadZuspinZuinit
, pthread_spin_init_intercept
,
835 (pthread_spinlock_t
*spinlock
, int pshared
), (spinlock
, pshared
));
837 static __always_inline
838 int pthread_spin_destroy_intercept(pthread_spinlock_t
*spinlock
)
842 VALGRIND_GET_ORIG_FN(fn
);
843 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_DESTROY
,
844 spinlock
, 0, 0, 0, 0);
845 CALL_FN_W_W(ret
, fn
, spinlock
);
846 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_DESTROY
,
847 spinlock
, mutex_type_spinlock
, 0, 0, 0);
851 PTH_FUNCS(int, pthreadZuspinZudestroy
, pthread_spin_destroy_intercept
,
852 (pthread_spinlock_t
*spinlock
), (spinlock
));
854 static __always_inline
855 int pthread_spin_lock_intercept(pthread_spinlock_t
*spinlock
)
859 VALGRIND_GET_ORIG_FN(fn
);
860 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK
,
861 spinlock
, mutex_type_spinlock
, 0, 0, 0);
862 CALL_FN_W_W(ret
, fn
, spinlock
);
863 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK
,
864 spinlock
, ret
== 0, 0, 0, 0);
868 PTH_FUNCS(int, pthreadZuspinZulock
, pthread_spin_lock_intercept
,
869 (pthread_spinlock_t
*spinlock
), (spinlock
));
871 static __always_inline
872 int pthread_spin_trylock_intercept(pthread_spinlock_t
*spinlock
)
876 VALGRIND_GET_ORIG_FN(fn
);
877 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK
,
878 spinlock
, mutex_type_spinlock
, 0, 0, 0);
879 CALL_FN_W_W(ret
, fn
, spinlock
);
880 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK
,
881 spinlock
, ret
== 0, 0, 0, 0);
885 PTH_FUNCS(int, pthreadZuspinZutrylock
, pthread_spin_trylock_intercept
,
886 (pthread_spinlock_t
*spinlock
), (spinlock
));
888 static __always_inline
889 int pthread_spin_unlock_intercept(pthread_spinlock_t
*spinlock
)
893 VALGRIND_GET_ORIG_FN(fn
);
894 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK
,
895 spinlock
, mutex_type_spinlock
, 0, 0, 0);
896 CALL_FN_W_W(ret
, fn
, spinlock
);
897 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK
,
898 spinlock
, 0, 0, 0, 0);
902 PTH_FUNCS(int, pthreadZuspinZuunlock
, pthread_spin_unlock_intercept
,
903 (pthread_spinlock_t
*spinlock
), (spinlock
));
904 #endif // HAVE_PTHREAD_SPIN_LOCK
907 #if defined(HAVE_PTHREAD_BARRIER_INIT)
908 static __always_inline
909 int pthread_barrier_init_intercept(pthread_barrier_t
* barrier
,
910 const pthread_barrierattr_t
* attr
,
915 VALGRIND_GET_ORIG_FN(fn
);
916 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_BARRIER_INIT
,
917 barrier
, pthread_barrier
, count
, 0, 0);
918 CALL_FN_W_WWW(ret
, fn
, barrier
, attr
, count
);
919 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_BARRIER_INIT
,
920 barrier
, pthread_barrier
, 0, 0, 0);
924 PTH_FUNCS(int, pthreadZubarrierZuinit
, pthread_barrier_init_intercept
,
925 (pthread_barrier_t
* barrier
, const pthread_barrierattr_t
* attr
,
926 unsigned count
), (barrier
, attr
, count
));
928 static __always_inline
929 int pthread_barrier_destroy_intercept(pthread_barrier_t
* barrier
)
933 VALGRIND_GET_ORIG_FN(fn
);
934 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_BARRIER_DESTROY
,
935 barrier
, pthread_barrier
, 0, 0, 0);
936 CALL_FN_W_W(ret
, fn
, barrier
);
937 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_BARRIER_DESTROY
,
938 barrier
, pthread_barrier
, 0, 0, 0);
942 PTH_FUNCS(int, pthreadZubarrierZudestroy
, pthread_barrier_destroy_intercept
,
943 (pthread_barrier_t
* barrier
), (barrier
));
945 static __always_inline
946 int pthread_barrier_wait_intercept(pthread_barrier_t
* barrier
)
950 VALGRIND_GET_ORIG_FN(fn
);
951 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_BARRIER_WAIT
,
952 barrier
, pthread_barrier
, 0, 0, 0);
953 CALL_FN_W_W(ret
, fn
, barrier
);
954 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_BARRIER_WAIT
,
955 barrier
, pthread_barrier
,
956 ret
== 0 || ret
== PTHREAD_BARRIER_SERIAL_THREAD
,
957 ret
== PTHREAD_BARRIER_SERIAL_THREAD
, 0);
961 PTH_FUNCS(int, pthreadZubarrierZuwait
, pthread_barrier_wait_intercept
,
962 (pthread_barrier_t
* barrier
), (barrier
));
963 #endif // HAVE_PTHREAD_BARRIER_INIT
966 static __always_inline
967 int sem_init_intercept(sem_t
*sem
, int pshared
, unsigned int value
)
971 VALGRIND_GET_ORIG_FN(fn
);
972 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_INIT
,
973 sem
, pshared
, value
, 0, 0);
974 CALL_FN_W_WWW(ret
, fn
, sem
, pshared
, value
);
975 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_INIT
,
980 PTH_FUNCS(int, semZuinit
, sem_init_intercept
,
981 (sem_t
*sem
, int pshared
, unsigned int value
), (sem
, pshared
, value
));
983 static __always_inline
984 int sem_destroy_intercept(sem_t
*sem
)
988 VALGRIND_GET_ORIG_FN(fn
);
989 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_DESTROY
,
991 CALL_FN_W_W(ret
, fn
, sem
);
992 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_DESTROY
,
997 PTH_FUNCS(int, semZudestroy
, sem_destroy_intercept
, (sem_t
*sem
), (sem
));
999 static __always_inline
1000 sem_t
* sem_open_intercept(const char *name
, int oflag
, mode_t mode
,
1005 VALGRIND_GET_ORIG_FN(fn
);
1006 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_OPEN
,
1007 name
, oflag
, mode
, value
, 0);
1008 CALL_FN_W_WWWW(ret
, fn
, name
, oflag
, mode
, value
);
1009 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_OPEN
,
1010 ret
!= SEM_FAILED
? ret
: 0,
1011 name
, oflag
, mode
, value
);
1015 PTH_FUNCS(sem_t
*, semZuopen
, sem_open_intercept
,
1016 (const char *name
, int oflag
, mode_t mode
, unsigned int value
),
1017 (name
, oflag
, mode
, value
));
1019 static __always_inline
int sem_close_intercept(sem_t
*sem
)
1023 VALGRIND_GET_ORIG_FN(fn
);
1024 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_CLOSE
,
1026 CALL_FN_W_W(ret
, fn
, sem
);
1027 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_CLOSE
,
1032 PTH_FUNCS(int, semZuclose
, sem_close_intercept
, (sem_t
*sem
), (sem
));
1034 static __always_inline
int sem_wait_intercept(sem_t
*sem
)
1038 VALGRIND_GET_ORIG_FN(fn
);
1039 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_WAIT
,
1041 CALL_FN_W_W(ret
, fn
, sem
);
1042 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_WAIT
,
1043 sem
, ret
== 0, 0, 0, 0);
1047 PTH_FUNCS(int, semZuwait
, sem_wait_intercept
, (sem_t
*sem
), (sem
));
1049 static __always_inline
int sem_trywait_intercept(sem_t
*sem
)
1053 VALGRIND_GET_ORIG_FN(fn
);
1054 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_WAIT
,
1056 CALL_FN_W_W(ret
, fn
, sem
);
1057 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_WAIT
,
1058 sem
, ret
== 0, 0, 0, 0);
1062 PTH_FUNCS(int, semZutrywait
, sem_trywait_intercept
, (sem_t
*sem
), (sem
));
1064 static __always_inline
1065 int sem_timedwait_intercept(sem_t
*sem
, const struct timespec
*abs_timeout
)
1069 VALGRIND_GET_ORIG_FN(fn
);
1070 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_WAIT
,
1072 CALL_FN_W_WW(ret
, fn
, sem
, abs_timeout
);
1073 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_WAIT
,
1074 sem
, ret
== 0, 0, 0, 0);
1078 PTH_FUNCS(int, semZutimedwait
, sem_timedwait_intercept
,
1079 (sem_t
*sem
, const struct timespec
*abs_timeout
),
1080 (sem
, abs_timeout
));
1082 static __always_inline
int sem_post_intercept(sem_t
*sem
)
1086 VALGRIND_GET_ORIG_FN(fn
);
1087 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_POST
,
1089 CALL_FN_W_W(ret
, fn
, sem
);
1090 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_POST
,
1091 sem
, ret
== 0, 0, 0, 0);
1095 PTH_FUNCS(int, semZupost
, sem_post_intercept
, (sem_t
*sem
), (sem
));
1097 /* Android's pthread.h doesn't say anything about rwlocks, hence these
1098 functions have to be conditionally compiled. */
1099 #if defined(HAVE_PTHREAD_RWLOCK_T)
1101 static __always_inline
1102 int pthread_rwlock_init_intercept(pthread_rwlock_t
* rwlock
,
1103 const pthread_rwlockattr_t
* attr
)
1107 VALGRIND_GET_ORIG_FN(fn
);
1108 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_INIT
,
1109 rwlock
, 0, 0, 0, 0);
1110 CALL_FN_W_WW(ret
, fn
, rwlock
, attr
);
1111 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_INIT
,
1112 rwlock
, 0, 0, 0, 0);
1117 pthreadZurwlockZuinit
, pthread_rwlock_init_intercept
,
1118 (pthread_rwlock_t
* rwlock
, const pthread_rwlockattr_t
* attr
),
1121 static __always_inline
1122 int pthread_rwlock_destroy_intercept(pthread_rwlock_t
* rwlock
)
1126 VALGRIND_GET_ORIG_FN(fn
);
1127 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_DESTROY
,
1128 rwlock
, 0, 0, 0, 0);
1129 CALL_FN_W_W(ret
, fn
, rwlock
);
1130 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_DESTROY
,
1131 rwlock
, 0, 0, 0, 0);
1136 pthreadZurwlockZudestroy
, pthread_rwlock_destroy_intercept
,
1137 (pthread_rwlock_t
* rwlock
), (rwlock
));
1139 static __always_inline
1140 int pthread_rwlock_rdlock_intercept(pthread_rwlock_t
* rwlock
)
1144 VALGRIND_GET_ORIG_FN(fn
);
1145 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_RDLOCK
,
1146 rwlock
, 0, 0, 0, 0);
1147 CALL_FN_W_W(ret
, fn
, rwlock
);
1148 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_RDLOCK
,
1149 rwlock
, ret
== 0, 0, 0, 0);
1154 pthreadZurwlockZurdlock
, pthread_rwlock_rdlock_intercept
,
1155 (pthread_rwlock_t
* rwlock
), (rwlock
));
1157 static __always_inline
1158 int pthread_rwlock_wrlock_intercept(pthread_rwlock_t
* rwlock
)
1162 VALGRIND_GET_ORIG_FN(fn
);
1163 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_WRLOCK
,
1164 rwlock
, 0, 0, 0, 0);
1165 CALL_FN_W_W(ret
, fn
, rwlock
);
1166 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_WRLOCK
,
1167 rwlock
, ret
== 0, 0, 0, 0);
1172 pthreadZurwlockZuwrlock
, pthread_rwlock_wrlock_intercept
,
1173 (pthread_rwlock_t
* rwlock
), (rwlock
));
1175 static __always_inline
1176 int pthread_rwlock_timedrdlock_intercept(pthread_rwlock_t
* rwlock
,
1177 const struct timespec
*timeout
)
1181 VALGRIND_GET_ORIG_FN(fn
);
1182 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_RDLOCK
,
1183 rwlock
, 0, 0, 0, 0);
1184 CALL_FN_W_WW(ret
, fn
, rwlock
, timeout
);
1185 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_RDLOCK
,
1186 rwlock
, ret
== 0, 0, 0, 0);
1191 pthreadZurwlockZutimedrdlock
, pthread_rwlock_timedrdlock_intercept
,
1192 (pthread_rwlock_t
* rwlock
, const struct timespec
*timeout
),
1195 static __always_inline
1196 int pthread_rwlock_timedwrlock_intercept(pthread_rwlock_t
* rwlock
,
1197 const struct timespec
*timeout
)
1201 VALGRIND_GET_ORIG_FN(fn
);
1202 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_WRLOCK
,
1203 rwlock
, 0, 0, 0, 0);
1204 CALL_FN_W_WW(ret
, fn
, rwlock
, timeout
);
1205 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_WRLOCK
,
1206 rwlock
, ret
== 0, 0, 0, 0);
1211 pthreadZurwlockZutimedwrlock
, pthread_rwlock_timedwrlock_intercept
,
1212 (pthread_rwlock_t
* rwlock
, const struct timespec
*timeout
),
1215 static __always_inline
1216 int pthread_rwlock_tryrdlock_intercept(pthread_rwlock_t
* rwlock
)
1220 VALGRIND_GET_ORIG_FN(fn
);
1221 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_RDLOCK
,
1222 rwlock
, 0, 0, 0, 0);
1223 CALL_FN_W_W(ret
, fn
, rwlock
);
1224 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_RDLOCK
,
1225 rwlock
, ret
== 0, 0, 0, 0);
1230 pthreadZurwlockZutryrdlock
, pthread_rwlock_tryrdlock_intercept
,
1231 (pthread_rwlock_t
* rwlock
), (rwlock
));
1233 static __always_inline
1234 int pthread_rwlock_trywrlock_intercept(pthread_rwlock_t
* rwlock
)
1238 VALGRIND_GET_ORIG_FN(fn
);
1239 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_WRLOCK
,
1240 rwlock
, 0, 0, 0, 0);
1241 CALL_FN_W_W(ret
, fn
, rwlock
);
1242 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_WRLOCK
,
1243 rwlock
, ret
== 0, 0, 0, 0);
1248 pthreadZurwlockZutrywrlock
, pthread_rwlock_trywrlock_intercept
,
1249 (pthread_rwlock_t
* rwlock
), (rwlock
));
1251 static __always_inline
1252 int pthread_rwlock_unlock_intercept(pthread_rwlock_t
* rwlock
)
1256 VALGRIND_GET_ORIG_FN(fn
);
1257 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_UNLOCK
,
1258 rwlock
, 0, 0, 0, 0);
1259 CALL_FN_W_W(ret
, fn
, rwlock
);
1260 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_UNLOCK
,
1261 rwlock
, ret
== 0, 0, 0, 0);
1266 pthreadZurwlockZuunlock
, pthread_rwlock_unlock_intercept
,
1267 (pthread_rwlock_t
* rwlock
), (rwlock
));
1269 #endif /* defined(HAVE_PTHREAD_RWLOCK_T) */