Check some known PATHs for mpicc in configure.
[valgrind.git] / drd / drd_pthread_intercepts.c
bloba3119deaf15d87f2b55c4f3fcbd070998317e16e
1 /*--------------------------------------------------------------------*/
2 /*--- Client-space code for DRD. drd_pthread_intercepts.c ---*/
3 /*--------------------------------------------------------------------*/
5 /*
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
23 02111-1307, USA.
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).
45 #ifndef _GNU_SOURCE
46 #define _GNU_SOURCE
47 #endif
49 #include <assert.h> /* assert() */
50 #include <errno.h>
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
63 #endif
64 #endif
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
80 * detected.
83 /**
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.
91 #ifdef VGO_darwin
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 \
96 { \
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. */ \
100 if (never_true) \
101 fflush(stdout); \
102 return pth_func_result; \
104 #else
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; }
109 #endif
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))
132 #else
133 #define __always_inline __inline__
134 #endif
136 /* Local data structures. */
138 typedef struct {
139 pthread_mutex_t mutex;
140 int counter;
141 int waiters;
142 } DrdSema;
144 typedef struct
146 void* (*start)(void*);
147 void* arg;
148 int detachstate;
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,
185 mutex, 0, 0, 0, 0);
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);
193 sema->counter = 0;
194 sema->waiters = 0;
197 static void DRD_(sema_destroy)(DrdSema* sema)
199 pthread_mutex_destroy(&sema->mutex);
202 static void DRD_(sema_down)(DrdSema* sema)
204 int res = ENOSYS;
206 pthread_mutex_lock(&sema->mutex);
207 if (sema->counter == 0) {
208 sema->waiters++;
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)
214 res = 0;
215 else
216 res = errno;
217 #endif
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)
225 sched_yield();
226 pthread_mutex_lock(&sema->mutex);
228 sema->waiters--;
230 sema->counter--;
231 pthread_mutex_unlock(&sema->mutex);
234 static void DRD_(sema_up)(DrdSema* sema)
236 pthread_mutex_lock(&sema->mutex);
237 sema->counter++;
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);
242 #endif
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
251 * value.
253 static MutexT DRD_(pthread_to_drd_mutex_type)(int kind)
256 * See also PTHREAD_MUTEX_KIND_MASK_NP in glibc source file
257 * <nptl/pthreadP.h>.
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;
273 #endif
274 else
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
282 * implementation.
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)
303 /* glibc + NPTL. */
304 if (IS_ALIGNED(&mutex->__data.__kind))
306 const int kind = mutex->__data.__kind & 3;
307 return DRD_(pthread_to_drd_mutex_type)(kind);
309 #else
311 * Another POSIX threads implementation. The mutex type won't be printed
312 * when enabling --trace-mutex=yes.
314 #endif
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,
332 0, 0, 0, 0, 0);
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,
339 0, 0, 0, 0, 0);
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;
352 arg_copy = *arg_ptr;
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)
379 #if defined(linux)
380 #if defined(_CS_GNU_LIBPTHREAD_VERSION)
381 /* Linux with a recent glibc. */
382 HChar buffer[256];
383 unsigned len;
384 len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
385 assert(len <= sizeof(buffer));
386 return len > 0 && buffer[0] == 'l';
387 #else
388 /* Linux without _CS_GNU_LIBPTHREAD_VERSION: most likely LinuxThreads. */
389 return 1;
390 #endif
391 #else
392 /* Another OS than Linux, hence no LinuxThreads. */
393 return 0;
394 #endif
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"))
407 fprintf(stderr,
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"
413 else
415 fprintf(stderr,
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"
419 "Giving up.\n"
422 abort();
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
439 * in Linux:
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)
459 int ret;
460 OrigFn fn;
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;
476 if (attr)
478 if (pthread_attr_getdetachstate(attr, &thread_args.detachstate) != 0)
479 assert(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)();
488 if (ret == 0) {
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);
498 return ret;
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)
509 int ret;
510 OrigFn fn;
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);
519 if (ret == 0)
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();
525 return ret;
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)
535 int ret;
536 OrigFn fn;
538 VALGRIND_GET_ORIG_FN(fn);
539 CALL_FN_W_W(ret, fn, pt_thread);
540 DRD_(set_joinable)(pt_thread, 0);
542 return ret;
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)
554 int ret;
555 OrigFn fn;
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);
562 return ret;
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))
572 int ret;
573 OrigFn fn;
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);
585 return ret;
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)
596 int ret;
597 OrigFn fn;
598 int mt;
599 VALGRIND_GET_ORIG_FN(fn);
600 mt = PTHREAD_MUTEX_DEFAULT;
601 if (attr)
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),
605 0, 0, 0);
606 CALL_FN_W_WW(ret, fn, mutex, attr);
607 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_INIT,
608 mutex, 0, 0, 0, 0);
609 return ret;
612 PTH_FUNCS(int, pthreadZumutexZuinit, pthread_mutex_init_intercept,
613 (pthread_mutex_t *mutex, const pthread_mutexattr_t* attr),
614 (mutex, attr));
616 static __always_inline
617 int pthread_mutex_destroy_intercept(pthread_mutex_t* mutex)
619 int ret;
620 OrigFn fn;
621 VALGRIND_GET_ORIG_FN(fn);
622 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_DESTROY,
623 mutex, 0, 0, 0, 0);
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);
627 return ret;
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)
636 int ret;
637 OrigFn fn;
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);
644 return ret;
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)
653 int ret;
654 OrigFn fn;
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);
661 return ret;
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)
671 int ret;
672 OrigFn fn;
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);
679 return ret;
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)
689 int ret;
690 OrigFn fn;
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,
696 mutex, 0, 0, 0, 0);
697 return ret;
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)
707 int ret;
708 OrigFn fn;
709 VALGRIND_GET_ORIG_FN(fn);
710 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_INIT,
711 cond, 0, 0, 0, 0);
712 CALL_FN_W_WW(ret, fn, cond, attr);
713 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_INIT,
714 cond, 0, 0, 0, 0);
715 return ret;
718 PTH_FUNCS(int, pthreadZucondZuinit, pthread_cond_init_intercept,
719 (pthread_cond_t* cond, const pthread_condattr_t* attr),
720 (cond, attr));
722 static __always_inline
723 int pthread_cond_destroy_intercept(pthread_cond_t* cond)
725 int ret;
726 OrigFn fn;
727 VALGRIND_GET_ORIG_FN(fn);
728 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_DESTROY,
729 cond, 0, 0, 0, 0);
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);
733 return ret;
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)
742 int ret;
743 OrigFn fn;
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);
750 return ret;
753 PTH_FUNCS(int, pthreadZucondZuwait, pthread_cond_wait_intercept,
754 (pthread_cond_t *cond, pthread_mutex_t *mutex),
755 (cond, 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)
762 int ret;
763 OrigFn fn;
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);
770 return ret;
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)
787 int ret;
788 OrigFn fn;
789 VALGRIND_GET_ORIG_FN(fn);
790 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_SIGNAL,
791 cond, 0, 0, 0, 0);
792 CALL_FN_W_W(ret, fn, cond);
793 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_SIGNAL,
794 cond, 0, 0, 0, 0);
795 return ret;
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)
804 int ret;
805 OrigFn fn;
806 VALGRIND_GET_ORIG_FN(fn);
807 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_BROADCAST,
808 cond, 0, 0, 0, 0);
809 CALL_FN_W_W(ret, fn, cond);
810 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_BROADCAST,
811 cond, 0, 0, 0, 0);
812 return ret;
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)
823 int ret;
824 OrigFn fn;
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);
831 return ret;
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)
840 int ret;
841 OrigFn fn;
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);
848 return ret;
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)
857 int ret;
858 OrigFn fn;
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);
865 return ret;
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)
874 int ret;
875 OrigFn fn;
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);
882 return ret;
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)
891 int ret;
892 OrigFn fn;
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);
899 return ret;
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,
911 unsigned count)
913 int ret;
914 OrigFn fn;
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);
921 return ret;
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)
931 int ret;
932 OrigFn fn;
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);
939 return ret;
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)
948 int ret;
949 OrigFn fn;
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);
958 return ret;
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)
969 int ret;
970 OrigFn fn;
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,
976 sem, 0, 0, 0, 0);
977 return ret;
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)
986 int ret;
987 OrigFn fn;
988 VALGRIND_GET_ORIG_FN(fn);
989 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_DESTROY,
990 sem, 0, 0, 0, 0);
991 CALL_FN_W_W(ret, fn, sem);
992 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_DESTROY,
993 sem, 0, 0, 0, 0);
994 return ret;
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,
1001 unsigned int value)
1003 sem_t *ret;
1004 OrigFn fn;
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);
1012 return ret;
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)
1021 int ret;
1022 OrigFn fn;
1023 VALGRIND_GET_ORIG_FN(fn);
1024 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_CLOSE,
1025 sem, 0, 0, 0, 0);
1026 CALL_FN_W_W(ret, fn, sem);
1027 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_CLOSE,
1028 sem, 0, 0, 0, 0);
1029 return ret;
1032 PTH_FUNCS(int, semZuclose, sem_close_intercept, (sem_t *sem), (sem));
1034 static __always_inline int sem_wait_intercept(sem_t *sem)
1036 int ret;
1037 OrigFn fn;
1038 VALGRIND_GET_ORIG_FN(fn);
1039 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_WAIT,
1040 sem, 0, 0, 0, 0);
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);
1044 return ret;
1047 PTH_FUNCS(int, semZuwait, sem_wait_intercept, (sem_t *sem), (sem));
1049 static __always_inline int sem_trywait_intercept(sem_t *sem)
1051 int ret;
1052 OrigFn fn;
1053 VALGRIND_GET_ORIG_FN(fn);
1054 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_WAIT,
1055 sem, 0, 0, 0, 0);
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);
1059 return ret;
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)
1067 int ret;
1068 OrigFn fn;
1069 VALGRIND_GET_ORIG_FN(fn);
1070 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_WAIT,
1071 sem, 0, 0, 0, 0);
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);
1075 return ret;
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)
1084 int ret;
1085 OrigFn fn;
1086 VALGRIND_GET_ORIG_FN(fn);
1087 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_POST,
1088 sem, 0, 0, 0, 0);
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);
1092 return ret;
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)
1105 int ret;
1106 OrigFn fn;
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);
1113 return ret;
1116 PTH_FUNCS(int,
1117 pthreadZurwlockZuinit, pthread_rwlock_init_intercept,
1118 (pthread_rwlock_t* rwlock, const pthread_rwlockattr_t* attr),
1119 (rwlock, attr));
1121 static __always_inline
1122 int pthread_rwlock_destroy_intercept(pthread_rwlock_t* rwlock)
1124 int ret;
1125 OrigFn fn;
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);
1132 return ret;
1135 PTH_FUNCS(int,
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)
1142 int ret;
1143 OrigFn fn;
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);
1150 return ret;
1153 PTH_FUNCS(int,
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)
1160 int ret;
1161 OrigFn fn;
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);
1168 return ret;
1171 PTH_FUNCS(int,
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)
1179 int ret;
1180 OrigFn fn;
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);
1187 return ret;
1190 PTH_FUNCS(int,
1191 pthreadZurwlockZutimedrdlock, pthread_rwlock_timedrdlock_intercept,
1192 (pthread_rwlock_t* rwlock, const struct timespec *timeout),
1193 (rwlock, timeout));
1195 static __always_inline
1196 int pthread_rwlock_timedwrlock_intercept(pthread_rwlock_t* rwlock,
1197 const struct timespec *timeout)
1199 int ret;
1200 OrigFn fn;
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);
1207 return ret;
1210 PTH_FUNCS(int,
1211 pthreadZurwlockZutimedwrlock, pthread_rwlock_timedwrlock_intercept,
1212 (pthread_rwlock_t* rwlock, const struct timespec *timeout),
1213 (rwlock, timeout));
1215 static __always_inline
1216 int pthread_rwlock_tryrdlock_intercept(pthread_rwlock_t* rwlock)
1218 int ret;
1219 OrigFn fn;
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);
1226 return ret;
1229 PTH_FUNCS(int,
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)
1236 int ret;
1237 OrigFn fn;
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);
1244 return ret;
1247 PTH_FUNCS(int,
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)
1254 int ret;
1255 OrigFn fn;
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);
1262 return ret;
1265 PTH_FUNCS(int,
1266 pthreadZurwlockZuunlock, pthread_rwlock_unlock_intercept,
1267 (pthread_rwlock_t* rwlock), (rwlock));
1269 #endif /* defined(HAVE_PTHREAD_RWLOCK_T) */