blob: d6abd43681f29642500431caa050ea204a6953ef [file] [log] [blame]
sewardjaf44c822007-11-25 14:01:38 +00001/*--------------------------------------------------------------------*/
bart227c6592009-02-14 12:12:57 +00002/*--- Client-space code for DRD. drd_pthread_intercepts.c ---*/
sewardjaf44c822007-11-25 14:01:38 +00003/*--------------------------------------------------------------------*/
4
5/*
bart86562bd2009-02-16 19:43:56 +00006 This file is part of DRD, a thread error detector.
sewardjaf44c822007-11-25 14:01:38 +00007
Elliott Hughesed398002017-06-21 14:41:24 -07008 Copyright (C) 2006-2017 Bart Van Assche <bvanassche@acm.org>.
sewardjaf44c822007-11-25 14:01:38 +00009
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.
14
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.
19
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.
24
25 The GNU General Public License is contained in the file COPYING.
26*/
27
28/* ---------------------------------------------------------------------
bart31b983d2010-02-21 14:52:59 +000029 ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU.
sewardjaf44c822007-11-25 14:01:38 +000030
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.
35
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 ------------------------------------------------------------------ */
40
bart227c6592009-02-14 12:12:57 +000041/*
barta764b372009-02-15 10:40:44 +000042 * Define _GNU_SOURCE to make sure that pthread_spinlock_t is available when
43 * compiling with older glibc versions (2.3 or before).
44 */
sewardjaf44c822007-11-25 14:01:38 +000045#ifndef _GNU_SOURCE
46#define _GNU_SOURCE
47#endif
48
bart227c6592009-02-14 12:12:57 +000049#include <assert.h> /* assert() */
bartd1a5cd62011-07-28 15:04:08 +000050#include <errno.h>
bart227c6592009-02-14 12:12:57 +000051#include <pthread.h> /* pthread_mutex_t */
52#include <semaphore.h> /* sem_t */
bart33f76c12010-09-19 11:14:31 +000053#include <stdint.h> /* uintptr_t */
bart227c6592009-02-14 12:12:57 +000054#include <stdio.h> /* fprintf() */
55#include <stdlib.h> /* malloc(), free() */
56#include <unistd.h> /* confstr() */
bart818f17e2011-09-17 06:24:49 +000057#include "config.h" /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP etc. */
bart227c6592009-02-14 12:12:57 +000058#include "drd_basics.h" /* DRD_() */
sewardjaf44c822007-11-25 14:01:38 +000059#include "drd_clientreq.h"
bart227c6592009-02-14 12:12:57 +000060#include "pub_tool_redir.h" /* VG_WRAP_FUNCTION_ZZ() */
sewardjaf44c822007-11-25 14:01:38 +000061
sewardj8eb8bab2015-07-21 14:44:28 +000062#if defined(VGO_solaris)
63/*
64 * Solaris usually provides pthread_* functions on top of Solaris threading
65 * and synchronization functions. Usually both need to be intercepted because
66 * pthread_* ones might not call the Solaris ones (see for example sem_wait()).
67 * Such approach is required to correctly report misuse of the POSIX threads
68 * API.
69 * Therefore DRD intercepts and instruments all such functions but due to
70 * DRD_(thread_enter_synchr)() and DRD_(thread_leave_synchr)() guards in
71 * handle_client_request(), only the top-most function is handled.
72 * So the right thing(TM) happens, as expected.
73 * The only exception is when pthread_* function is a weak alias to the Solaris
74 * threading/synchronization function. In such case only one needs to be
75 * intercepted to avoid redirection ambiguity.
76 *
77 * Intercepted functions rely on the fact that:
78 * - pthread_mutex_t == mutex_t
79 * - pthread_cond_t == cond_t
80 * - sem_t == sema_t
81 * - pthread_rwlock_t == rwlock_t
82 *
83 * It is necessary to intercept also internal libc synchronization functions
84 * for two reasons:
85 * - For read-write locks the unlocking function is shared
86 * - Functions lmutex_lock/lmutex_unlock guard many critical sections in libc
87 * which will be otherwise reported by DRD
88 */
89#include <synch.h>
90#include <thread.h>
91#include "pub_tool_vki.h"
92
93/*
94 * Solaris provides higher throughput, parallelism and scalability than other
95 * operating systems, at the cost of more fine-grained locking activity.
96 * This means for example that when a thread is created under Linux, just one
97 * big lock in glibc is used for all thread setup. Solaris libc uses several
98 * fine-grained locks and the creator thread resumes its activities as soon
99 * as possible, leaving for example stack and TLS setup activities to the
100 * created thread.
101 *
102 * This situation confuses DRD as it assumes there is some false ordering
103 * in place between creator and created thread; and therefore many types of
104 * race conditions in the application would not be reported. To prevent such
105 * false ordering, command line option --ignore-thread-creation is set to
106 * 'yes' by default on Solaris. All activity (loads, stores, client requests)
107 * is therefore ignored during:
108 * - pthread_create() call in the creator thread [libc.so]
109 * - thread creation phase (stack and TLS setup) in the created thread [libc.so]
110 *
111 * As explained in the comments for _ti_bind_guard(), whenever the runtime
112 * linker has to perform any activity (such as resolving a symbol), it protects
113 * its data structures by calling into rt_bind_guard() which in turn invokes
114 * _ti_bind_guard() in libc. Pointers to _ti_bind_guard() and _ti_bind_clear()
115 * are passed from libc to runtime linker in _ld_libc() call during libc_init().
116 * All activity is also ignored during:
117 * - runtime dynamic linker work between rt_bind_guard() and rt_bind_clear()
118 * calls [ld.so]
119 *
120 * This also means that DRD does not report race conditions in libc (when
121 * --ignore-thread-creation=yes) and runtime linker itself (unconditionally)
122 * during these ignored sequences.
123 */
124
125/*
126 * Original function pointers for _ti_bind_guard() and _ti_bind_clear()
127 * from libc. They are intercepted in function wrapper of _ld_libc().
128 */
129typedef int (*drd_rtld_guard_fn)(int flags);
130static drd_rtld_guard_fn DRD_(rtld_bind_guard) = NULL;
131static drd_rtld_guard_fn DRD_(rtld_bind_clear) = NULL;
132#endif
133
sewardjaf44c822007-11-25 14:01:38 +0000134
barta0b72222009-03-12 18:39:31 +0000135/*
bart82397422011-03-08 17:53:45 +0000136 * Notes regarding thread creation:
137 * - sg_init() runs on the context of the created thread and copies the vector
138 * clock of the creator thread. This only works reliably if the creator
139 * thread waits until this copy has been performed.
140 * - DRD_(thread_compute_minimum_vc)() does not take the vector clocks into
141 * account that are involved in thread creation and for which the
142 * corresponding thread has not yet been created. So not waiting until the
143 * created thread has been started would make it possible that segments get
144 * discarded that should not yet be discarded. Or: some data races are not
145 * detected.
barta0b72222009-03-12 18:39:31 +0000146 */
barta0b72222009-03-12 18:39:31 +0000147
bart791a0c62009-07-31 17:31:44 +0000148/**
149 * Macro for generating a Valgrind interception function.
150 * @param[in] ret_ty Return type of the function to be generated.
151 * @param[in] zf Z-encoded name of the interception function.
152 * @param[in] implf Name of the function that implements the intercept.
153 * @param[in] arg_decl Argument declaration list enclosed in parentheses.
154 * @param[in] argl Argument list enclosed in parentheses.
155 */
bart377d23f2011-03-05 14:51:24 +0000156#ifdef VGO_darwin
157static int never_true;
158#define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl) \
159 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl; \
160 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl \
161 { \
162 ret_ty pth_func_result = implf argl; \
163 /* Apparently inserting a function call in wrapper functions */ \
164 /* is sufficient to avoid misaligned stack errors. */ \
165 if (never_true) \
166 fflush(stdout); \
167 return pth_func_result; \
168 }
sewardj8eb8bab2015-07-21 14:44:28 +0000169#elif defined(VGO_solaris)
170/* On Solaris, libpthread is just a filter library on top of libc.
171 * Threading and synchronization functions in runtime linker are not
172 * intercepted.
173 */
174#define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl) \
175 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBC_SONAME,zf) argl_decl; \
176 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBC_SONAME,zf) argl_decl \
177 { return implf argl; }
bart377d23f2011-03-05 14:51:24 +0000178#else
bart791a0c62009-07-31 17:31:44 +0000179#define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl) \
180 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl; \
181 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl \
182 { return implf argl; }
bart377d23f2011-03-05 14:51:24 +0000183#endif
sewardjaf44c822007-11-25 14:01:38 +0000184
bart791a0c62009-07-31 17:31:44 +0000185/**
186 * Macro for generating three Valgrind interception functions: one with the
187 * Z-encoded name zf, one with ZAZa ("@*") appended to the name zf and one
188 * with ZDZa ("$*") appended to the name zf. The second generated interception
189 * function will intercept versioned symbols on Linux, and the third will
190 * intercept versioned symbols on Darwin.
191 */
192#define PTH_FUNCS(ret_ty, zf, implf, argl_decl, argl) \
193 PTH_FUNC(ret_ty, zf, implf, argl_decl, argl); \
194 PTH_FUNC(ret_ty, zf ## ZAZa, implf, argl_decl, argl); \
195 PTH_FUNC(ret_ty, zf ## ZDZa, implf, argl_decl, argl);
196
197/*
bartb2260b82011-02-13 07:55:36 +0000198 * Not inlining one of the intercept functions will cause the regression
199 * tests to fail because this would cause an additional stackfram to appear
200 * in the output. The __always_inline macro guarantees that inlining will
201 * happen, even when compiling with optimization disabled.
bart791a0c62009-07-31 17:31:44 +0000202 */
203#undef __always_inline /* since already defined in <cdefs.h> */
bart4f66a772009-07-31 17:59:28 +0000204#if __GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 2
bart791a0c62009-07-31 17:31:44 +0000205#define __always_inline __inline__ __attribute__((always_inline))
206#else
207#define __always_inline __inline__
208#endif
sewardjaf44c822007-11-25 14:01:38 +0000209
bart6f07b252008-04-04 16:45:20 +0000210/* Local data structures. */
sewardjaf44c822007-11-25 14:01:38 +0000211
bart651f56b2011-07-26 19:30:28 +0000212typedef struct {
barte5286972012-01-19 19:52:15 +0000213 pthread_mutex_t mutex;
bartf2253a42015-09-29 05:39:00 +0000214 pthread_cond_t cond;
barte5286972012-01-19 19:52:15 +0000215 int counter;
bart651f56b2011-07-26 19:30:28 +0000216} DrdSema;
217
sewardjaf44c822007-11-25 14:01:38 +0000218typedef struct
219{
bartbedfd232009-03-26 19:07:15 +0000220 void* (*start)(void*);
221 void* arg;
222 int detachstate;
barte57a9e22012-01-24 08:30:32 +0000223 DrdSema* wrapper_started;
barta764b372009-02-15 10:40:44 +0000224} DrdPosixThreadArgs;
sewardjaf44c822007-11-25 14:01:38 +0000225
226
bart227c6592009-02-14 12:12:57 +0000227/* Local function declarations. */
sewardjaf44c822007-11-25 14:01:38 +0000228
bart227c6592009-02-14 12:12:57 +0000229static void DRD_(init)(void) __attribute__((constructor));
230static void DRD_(check_threading_library)(void);
Elliott Hughesed398002017-06-21 14:41:24 -0700231static void DRD_(set_pthread_id)(void);
bart651f56b2011-07-26 19:30:28 +0000232static void DRD_(sema_init)(DrdSema* sema);
233static void DRD_(sema_destroy)(DrdSema* sema);
234static void DRD_(sema_down)(DrdSema* sema);
235static void DRD_(sema_up)(DrdSema* sema);
sewardjaf44c822007-11-25 14:01:38 +0000236
237
bart6f07b252008-04-04 16:45:20 +0000238/* Function definitions. */
239
bart227c6592009-02-14 12:12:57 +0000240/**
241 * Shared library initialization function. The function init() is called after
242 * dlopen() has loaded the shared library with DRD client intercepts because
243 * the constructor attribute was specified in the declaration of this function.
244 * Note: do specify the -nostdlib option to gcc when linking this code into a
245 * shared library because doing so would cancel the effect of the constructor
246 * attribute ! Using the gcc option -nodefaultlibs is fine because this last
247 * option preserves the shared library initialization code that calls
248 * constructor and destructor functions.
bart6f07b252008-04-04 16:45:20 +0000249 */
bart227c6592009-02-14 12:12:57 +0000250static void DRD_(init)(void)
bart6f07b252008-04-04 16:45:20 +0000251{
bartbedfd232009-03-26 19:07:15 +0000252 DRD_(check_threading_library)();
Elliott Hughesed398002017-06-21 14:41:24 -0700253 DRD_(set_pthread_id)();
sewardj8eb8bab2015-07-21 14:44:28 +0000254#if defined(VGO_solaris)
255 if ((DRD_(rtld_bind_guard) == NULL) || (DRD_(rtld_bind_clear) == NULL)) {
256 fprintf(stderr,
257"Bind guard functions for the runtime linker (ld.so.1) were not intercepted.\n"
258"This means the interface between libc and runtime linker changed and DRD\n"
259"needs to be ported properly. Giving up.\n");
260 abort();
261 }
262#endif
bart6f07b252008-04-04 16:45:20 +0000263}
sewardjaf44c822007-11-25 14:01:38 +0000264
bart3cc26202014-06-09 09:19:26 +0000265static __always_inline void DRD_(ignore_mutex_ordering)(pthread_mutex_t *mutex)
266{
267 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_IGNORE_MUTEX_ORDERING,
268 mutex, 0, 0, 0, 0);
269}
270
bart651f56b2011-07-26 19:30:28 +0000271static void DRD_(sema_init)(DrdSema* sema)
272{
bart3cc26202014-06-09 09:19:26 +0000273 DRD_IGNORE_VAR(*sema);
barte5286972012-01-19 19:52:15 +0000274 pthread_mutex_init(&sema->mutex, NULL);
bart3cc26202014-06-09 09:19:26 +0000275 DRD_(ignore_mutex_ordering)(&sema->mutex);
bartf2253a42015-09-29 05:39:00 +0000276 pthread_cond_init(&sema->cond, NULL);
bart651f56b2011-07-26 19:30:28 +0000277 sema->counter = 0;
278}
279
280static void DRD_(sema_destroy)(DrdSema* sema)
281{
barte5286972012-01-19 19:52:15 +0000282 pthread_mutex_destroy(&sema->mutex);
bartf2253a42015-09-29 05:39:00 +0000283 pthread_cond_destroy(&sema->cond);
bart651f56b2011-07-26 19:30:28 +0000284}
285
286static void DRD_(sema_down)(DrdSema* sema)
287{
barte5286972012-01-19 19:52:15 +0000288 pthread_mutex_lock(&sema->mutex);
bartf2253a42015-09-29 05:39:00 +0000289 while (sema->counter == 0)
290 pthread_cond_wait(&sema->cond, &sema->mutex);
bart651f56b2011-07-26 19:30:28 +0000291 sema->counter--;
barte5286972012-01-19 19:52:15 +0000292 pthread_mutex_unlock(&sema->mutex);
bart651f56b2011-07-26 19:30:28 +0000293}
294
295static void DRD_(sema_up)(DrdSema* sema)
296{
barte5286972012-01-19 19:52:15 +0000297 pthread_mutex_lock(&sema->mutex);
bart651f56b2011-07-26 19:30:28 +0000298 sema->counter++;
bartf2253a42015-09-29 05:39:00 +0000299 pthread_cond_signal(&sema->cond);
barte5286972012-01-19 19:52:15 +0000300 pthread_mutex_unlock(&sema->mutex);
bart651f56b2011-07-26 19:30:28 +0000301}
302
bart227c6592009-02-14 12:12:57 +0000303/**
304 * POSIX threads and DRD each have their own mutex type identification.
305 * Convert POSIX threads' mutex type to DRD's mutex type. In the code below
306 * if-statements are used to test the value of 'kind' instead of a switch
307 * statement because some of the PTHREAD_MUTEX_ macro's may have the same
308 * value.
309 */
bart9025fdb2014-02-08 10:55:08 +0000310static MutexT DRD_(pthread_to_drd_mutex_type)(int kind)
bart5357fcb2008-02-27 15:46:00 +0000311{
bart9025fdb2014-02-08 10:55:08 +0000312 /*
313 * See also PTHREAD_MUTEX_KIND_MASK_NP in glibc source file
314 * <nptl/pthreadP.h>.
315 */
bartfef90e02014-02-09 09:10:14 +0000316 kind &= PTHREAD_MUTEX_RECURSIVE | PTHREAD_MUTEX_ERRORCHECK |
317 PTHREAD_MUTEX_NORMAL | PTHREAD_MUTEX_DEFAULT;
bart9025fdb2014-02-08 10:55:08 +0000318
bartbedfd232009-03-26 19:07:15 +0000319 if (kind == PTHREAD_MUTEX_RECURSIVE)
320 return mutex_type_recursive_mutex;
321 else if (kind == PTHREAD_MUTEX_ERRORCHECK)
322 return mutex_type_errorcheck_mutex;
323 else if (kind == PTHREAD_MUTEX_NORMAL)
324 return mutex_type_default_mutex;
325 else if (kind == PTHREAD_MUTEX_DEFAULT)
326 return mutex_type_default_mutex;
bart227c6592009-02-14 12:12:57 +0000327#if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP)
bartbedfd232009-03-26 19:07:15 +0000328 else if (kind == PTHREAD_MUTEX_ADAPTIVE_NP)
329 return mutex_type_default_mutex;
bart227c6592009-02-14 12:12:57 +0000330#endif
bartbedfd232009-03-26 19:07:15 +0000331 else
bartbedfd232009-03-26 19:07:15 +0000332 return mutex_type_invalid_mutex;
bart5357fcb2008-02-27 15:46:00 +0000333}
334
sewardj8eb8bab2015-07-21 14:44:28 +0000335#if defined(VGO_solaris)
336/**
337 * Solaris threads and DRD each have their own mutex type identification.
338 * Convert Solaris threads' mutex type to DRD's mutex type.
339 */
340static MutexT DRD_(thread_to_drd_mutex_type)(int type)
341{
342 if (type & LOCK_RECURSIVE) {
343 return mutex_type_recursive_mutex;
344 } else if (type & LOCK_ERRORCHECK) {
345 return mutex_type_errorcheck_mutex;
346 } else {
347 return mutex_type_default_mutex;
348 }
349}
350#endif /* VGO_solaris */
351
bart33f76c12010-09-19 11:14:31 +0000352#define IS_ALIGNED(p) (((uintptr_t)(p) & (sizeof(*(p)) - 1)) == 0)
353
bart227c6592009-02-14 12:12:57 +0000354/**
355 * Read the mutex type stored in the client memory used for the mutex
356 * implementation.
357 *
358 * @note This function depends on the implementation of the POSIX threads
359 * library -- the POSIX standard does not define the name of the member in
360 * which the mutex type is stored.
361 * @note The function mutex_type() has been declared inline in order
362 * to avoid that it shows up in call stacks (drd/tests/...exp* files).
bart489de212009-03-13 17:32:52 +0000363 * @note glibc stores the mutex type in the lowest two bits, and uses the
364 * higher bits for flags like PTHREAD_MUTEXATTR_FLAG_ROBUST and
365 * PTHREAD_MUTEXATTR_FLAG_PSHARED.
bart2bc9c102008-09-27 12:40:57 +0000366 */
bart791a0c62009-07-31 17:31:44 +0000367static __always_inline MutexT DRD_(mutex_type)(pthread_mutex_t* mutex)
bart5357fcb2008-02-27 15:46:00 +0000368{
bart5e389f12008-04-05 12:53:15 +0000369#if defined(HAVE_PTHREAD_MUTEX_T__M_KIND)
bartbedfd232009-03-26 19:07:15 +0000370 /* glibc + LinuxThreads. */
bart33f76c12010-09-19 11:14:31 +0000371 if (IS_ALIGNED(&mutex->__m_kind))
372 {
373 const int kind = mutex->__m_kind & 3;
374 return DRD_(pthread_to_drd_mutex_type)(kind);
375 }
bart5e389f12008-04-05 12:53:15 +0000376#elif defined(HAVE_PTHREAD_MUTEX_T__DATA__KIND)
bartbedfd232009-03-26 19:07:15 +0000377 /* glibc + NPTL. */
bart33f76c12010-09-19 11:14:31 +0000378 if (IS_ALIGNED(&mutex->__data.__kind))
379 {
380 const int kind = mutex->__data.__kind & 3;
381 return DRD_(pthread_to_drd_mutex_type)(kind);
382 }
sewardj8eb8bab2015-07-21 14:44:28 +0000383#elif defined(VGO_solaris)
384 const int type = ((mutex_t *) mutex)->vki_mutex_type;
385 return DRD_(thread_to_drd_mutex_type)(type);
bartadb7a202009-07-21 12:39:25 +0000386#else
387 /*
388 * Another POSIX threads implementation. The mutex type won't be printed
389 * when enabling --trace-mutex=yes.
390 */
bartadb7a202009-07-21 12:39:25 +0000391#endif
bart33f76c12010-09-19 11:14:31 +0000392 return mutex_type_unknown;
bart5357fcb2008-02-27 15:46:00 +0000393}
394
bart227c6592009-02-14 12:12:57 +0000395/**
396 * Tell DRD whether 'tid' is a joinable thread or a detached thread.
397 */
398static void DRD_(set_joinable)(const pthread_t tid, const int joinable)
sewardjaf44c822007-11-25 14:01:38 +0000399{
bartbedfd232009-03-26 19:07:15 +0000400 assert(joinable == 0 || joinable == 1);
sewardj4b3a7422011-10-24 13:21:57 +0000401 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__SET_JOINABLE,
bart575ce8e2011-05-15 07:04:03 +0000402 tid, joinable, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000403}
404
bartdd75cdf2009-07-24 08:20:10 +0000405/** Tell DRD that the calling thread is about to enter pthread_create(). */
bart791a0c62009-07-31 17:31:44 +0000406static __always_inline void DRD_(entering_pthread_create)(void)
bartdd75cdf2009-07-24 08:20:10 +0000407{
sewardj4b3a7422011-10-24 13:21:57 +0000408 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__ENTERING_PTHREAD_CREATE,
bart575ce8e2011-05-15 07:04:03 +0000409 0, 0, 0, 0, 0);
bartdd75cdf2009-07-24 08:20:10 +0000410}
411
412/** Tell DRD that the calling thread has left pthread_create(). */
bart791a0c62009-07-31 17:31:44 +0000413static __always_inline void DRD_(left_pthread_create)(void)
bartdd75cdf2009-07-24 08:20:10 +0000414{
sewardj4b3a7422011-10-24 13:21:57 +0000415 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LEFT_PTHREAD_CREATE,
bart575ce8e2011-05-15 07:04:03 +0000416 0, 0, 0, 0, 0);
bartdd75cdf2009-07-24 08:20:10 +0000417}
418
bart227c6592009-02-14 12:12:57 +0000419/**
bartdd75cdf2009-07-24 08:20:10 +0000420 * Entry point for newly created threads. This function is called from the
421 * thread created by pthread_create().
bart227c6592009-02-14 12:12:57 +0000422 */
bart292c1e22009-02-14 11:54:42 +0000423static void* DRD_(thread_wrapper)(void* arg)
sewardjaf44c822007-11-25 14:01:38 +0000424{
bartbedfd232009-03-26 19:07:15 +0000425 DrdPosixThreadArgs* arg_ptr;
426 DrdPosixThreadArgs arg_copy;
bart0d063002008-03-01 07:25:13 +0000427
bartbedfd232009-03-26 19:07:15 +0000428 arg_ptr = (DrdPosixThreadArgs*)arg;
429 arg_copy = *arg_ptr;
sewardjaf44c822007-11-25 14:01:38 +0000430
sewardj4b3a7422011-10-24 13:21:57 +0000431 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__SET_PTHREADID,
bart575ce8e2011-05-15 07:04:03 +0000432 pthread_self(), 0, 0, 0, 0);
bart227c6592009-02-14 12:12:57 +0000433
bartbedfd232009-03-26 19:07:15 +0000434 DRD_(set_joinable)(pthread_self(),
435 arg_copy.detachstate == PTHREAD_CREATE_JOINABLE);
bart227c6592009-02-14 12:12:57 +0000436
bart8244b862011-03-08 18:34:44 +0000437 /*
438 * Only set 'wrapper_started' after VG_USERREQ__SET_PTHREADID and
439 * DRD_(set_joinable)() have been invoked to avoid a race with
440 * a pthread_detach() invocation for this thread from another thread.
441 */
barte57a9e22012-01-24 08:30:32 +0000442 DRD_(sema_up)(arg_copy.wrapper_started);
bart8244b862011-03-08 18:34:44 +0000443
bartbedfd232009-03-26 19:07:15 +0000444 return (arg_copy.start)(arg_copy.arg);
sewardjaf44c822007-11-25 14:01:38 +0000445}
446
bart227c6592009-02-14 12:12:57 +0000447/**
bartd2c5eae2009-02-21 15:27:04 +0000448 * Return 1 if the LinuxThreads implementation of POSIX Threads has been
449 * detected, and 0 otherwise.
450 *
451 * @see For more information about the confstr() function, see also
bart227c6592009-02-14 12:12:57 +0000452 * http://www.opengroup.org/onlinepubs/009695399/functions/confstr.html
453 */
454static int DRD_(detected_linuxthreads)(void)
bart4501d5c2008-03-04 18:36:23 +0000455{
456#if defined(linux)
457#if defined(_CS_GNU_LIBPTHREAD_VERSION)
bartbedfd232009-03-26 19:07:15 +0000458 /* Linux with a recent glibc. */
florian19f91bb2012-11-10 22:29:54 +0000459 HChar buffer[256];
bartbedfd232009-03-26 19:07:15 +0000460 unsigned len;
461 len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
462 assert(len <= sizeof(buffer));
463 return len > 0 && buffer[0] == 'l';
bart4501d5c2008-03-04 18:36:23 +0000464#else
bartbedfd232009-03-26 19:07:15 +0000465 /* Linux without _CS_GNU_LIBPTHREAD_VERSION: most likely LinuxThreads. */
466 return 1;
bart4501d5c2008-03-04 18:36:23 +0000467#endif
468#else
bartbedfd232009-03-26 19:07:15 +0000469 /* Another OS than Linux, hence no LinuxThreads. */
470 return 0;
bart4501d5c2008-03-04 18:36:23 +0000471#endif
472}
473
bart227c6592009-02-14 12:12:57 +0000474/**
475 * Stop and print an error message in case a non-supported threading
476 * library implementation (LinuxThreads) has been detected.
bart6f07b252008-04-04 16:45:20 +0000477 */
bart227c6592009-02-14 12:12:57 +0000478static void DRD_(check_threading_library)(void)
sewardjaf44c822007-11-25 14:01:38 +0000479{
bartbedfd232009-03-26 19:07:15 +0000480 if (DRD_(detected_linuxthreads)())
481 {
482 if (getenv("LD_ASSUME_KERNEL"))
483 {
484 fprintf(stderr,
bart227c6592009-02-14 12:12:57 +0000485"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
486"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
487"after having unset the environment variable LD_ASSUME_KERNEL. Giving up.\n"
bartbedfd232009-03-26 19:07:15 +0000488);
489 }
490 else
491 {
492 fprintf(stderr,
bart227c6592009-02-14 12:12:57 +0000493"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
494"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
495"after having upgraded to a newer version of your Linux distribution.\n"
496"Giving up.\n"
bartbedfd232009-03-26 19:07:15 +0000497);
498 }
499 abort();
500 }
bart6f07b252008-04-04 16:45:20 +0000501}
502
bart227c6592009-02-14 12:12:57 +0000503/**
Elliott Hughesed398002017-06-21 14:41:24 -0700504 * Update DRD's state information about the current thread.
bart227c6592009-02-14 12:12:57 +0000505 */
Elliott Hughesed398002017-06-21 14:41:24 -0700506static void DRD_(set_pthread_id)(void)
bart6f07b252008-04-04 16:45:20 +0000507{
sewardj4b3a7422011-10-24 13:21:57 +0000508 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__SET_PTHREADID,
bart575ce8e2011-05-15 07:04:03 +0000509 pthread_self(), 0, 0, 0, 0);
bart850f1992010-05-29 18:43:21 +0000510}
sewardjaf44c822007-11-25 14:01:38 +0000511
bartc39d1092009-04-22 18:59:50 +0000512/*
bartdd75cdf2009-07-24 08:20:10 +0000513 * Note: as of today there exist three different versions of pthread_create
514 * in Linux:
bartc39d1092009-04-22 18:59:50 +0000515 * - pthread_create@GLIBC_2.0
516 * - pthread_create@@GLIBC_2.1
517 * - pthread_create@@GLIBC_2.2.5
518 * As an example, in libpthread-2.3.4 both pthread_create@GLIBC_2.0 and
519 * pthread_create@@GLIBC_2.1 are defined, while in libpthread-2.9 all three
520 * versions have been implemented. In any glibc version where more than one
521 * pthread_create function has been implemented, older versions call the
522 * newer versions. Or: the pthread_create* wrapper defined below can be
523 * called recursively. Any code in this wrapper should take this in account.
524 * As an example, it is not safe to invoke the DRD_STOP_RECORDING
525 * / DRD_START_RECORDING client requests from the pthread_create wrapper.
526 * See also the implementation of pthread_create@GLIBC_2.0 in
527 * glibc-2.9/nptl/pthread_create.c.
528 */
529
bartb2260b82011-02-13 07:55:36 +0000530static __always_inline
bart791a0c62009-07-31 17:31:44 +0000531int pthread_create_intercept(pthread_t* thread, const pthread_attr_t* attr,
532 void* (*start)(void*), void* arg)
sewardjaf44c822007-11-25 14:01:38 +0000533{
bartbedfd232009-03-26 19:07:15 +0000534 int ret;
535 OrigFn fn;
barte57a9e22012-01-24 08:30:32 +0000536 DrdSema wrapper_started;
bartbedfd232009-03-26 19:07:15 +0000537 DrdPosixThreadArgs thread_args;
sewardjaf44c822007-11-25 14:01:38 +0000538
bartbedfd232009-03-26 19:07:15 +0000539 VALGRIND_GET_ORIG_FN(fn);
sewardjaf44c822007-11-25 14:01:38 +0000540
barte57a9e22012-01-24 08:30:32 +0000541 DRD_(sema_init)(&wrapper_started);
bartb957ab82011-03-12 11:01:06 +0000542 thread_args.start = start;
543 thread_args.arg = arg;
barte57a9e22012-01-24 08:30:32 +0000544 thread_args.wrapper_started = &wrapper_started;
bartbedfd232009-03-26 19:07:15 +0000545 /*
546 * Find out whether the thread will be started as a joinable thread
547 * or as a detached thread. If no thread attributes have been specified,
548 * this means that the new thread will be started as a joinable thread.
549 */
bartb957ab82011-03-12 11:01:06 +0000550 thread_args.detachstate = PTHREAD_CREATE_JOINABLE;
bartbedfd232009-03-26 19:07:15 +0000551 if (attr)
552 {
bartb957ab82011-03-12 11:01:06 +0000553 if (pthread_attr_getdetachstate(attr, &thread_args.detachstate) != 0)
bartbedfd232009-03-26 19:07:15 +0000554 assert(0);
bartbedfd232009-03-26 19:07:15 +0000555 }
bartb957ab82011-03-12 11:01:06 +0000556 assert(thread_args.detachstate == PTHREAD_CREATE_JOINABLE
557 || thread_args.detachstate == PTHREAD_CREATE_DETACHED);
bartdd75cdf2009-07-24 08:20:10 +0000558
Elliott Hughesed398002017-06-21 14:41:24 -0700559 /*
560 * The DRD_(set_pthread_id)() from DRD_(init)() may encounter that
561 * pthread_self() == 0, e.g. when the main program is not linked with the
562 * pthread library and when a pthread_create() call occurs from within a
563 * shared library. Hence call DRD_(set_pthread_id)() again to ensure that
564 * DRD knows the identity of the current thread. See also B.Z. 356374.
565 */
566 DRD_(set_pthread_id)();
bartdd75cdf2009-07-24 08:20:10 +0000567 DRD_(entering_pthread_create)();
bartb957ab82011-03-12 11:01:06 +0000568 CALL_FN_W_WWWW(ret, fn, thread, attr, DRD_(thread_wrapper), &thread_args);
bartdd75cdf2009-07-24 08:20:10 +0000569 DRD_(left_pthread_create)();
bart227c6592009-02-14 12:12:57 +0000570
barte57a9e22012-01-24 08:30:32 +0000571 if (ret == 0) {
barte476e922011-03-08 18:32:36 +0000572 /* Wait until the thread wrapper started. */
barte57a9e22012-01-24 08:30:32 +0000573 DRD_(sema_down)(&wrapper_started);
bartbedfd232009-03-26 19:07:15 +0000574 }
bart227c6592009-02-14 12:12:57 +0000575
barte57a9e22012-01-24 08:30:32 +0000576 DRD_(sema_destroy)(&wrapper_started);
bart651f56b2011-07-26 19:30:28 +0000577
sewardj4b3a7422011-10-24 13:21:57 +0000578 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_START_NEW_SEGMENT,
bart575ce8e2011-05-15 07:04:03 +0000579 pthread_self(), 0, 0, 0, 0);
barta0b72222009-03-12 18:39:31 +0000580
bartbedfd232009-03-26 19:07:15 +0000581 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000582}
583
bart791a0c62009-07-31 17:31:44 +0000584PTH_FUNCS(int, pthreadZucreate, pthread_create_intercept,
585 (pthread_t *thread, const pthread_attr_t *attr,
586 void *(*start) (void *), void *arg),
587 (thread, attr, start, arg));
588
sewardj8eb8bab2015-07-21 14:44:28 +0000589#if defined(VGO_solaris)
590/* Solaris also provides thr_create() in addition to pthread_create().
591 * Both pthread_create(3C) and thr_create(3C) are based on private
592 * _thrp_create().
593 */
594static __always_inline
595int thr_create_intercept(void *stk, size_t stksize, void *(*start)(void *),
596 void *arg, long flags, thread_t *new_thread)
597{
598 int ret;
599 OrigFn fn;
600 DrdSema wrapper_started;
601 DrdPosixThreadArgs thread_args;
602
603 VALGRIND_GET_ORIG_FN(fn);
604
605 DRD_(sema_init)(&wrapper_started);
606 thread_args.start = start;
607 thread_args.arg = arg;
608 thread_args.wrapper_started = &wrapper_started;
609 /*
610 * Find out whether the thread will be started as a joinable thread
611 * or as a detached thread.
612 */
613 if (flags & THR_DETACHED)
614 thread_args.detachstate = PTHREAD_CREATE_DETACHED;
615 else
616 thread_args.detachstate = PTHREAD_CREATE_JOINABLE;
617
618 DRD_(entering_pthread_create)();
619 CALL_FN_W_6W(ret, fn, stk, stksize, DRD_(thread_wrapper), &thread_args,
620 flags, new_thread);
621 DRD_(left_pthread_create)();
622
623 if (ret == 0) {
624 /* Wait until the thread wrapper started. */
625 DRD_(sema_down)(&wrapper_started);
626 }
627
628 DRD_(sema_destroy)(&wrapper_started);
629
630 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_START_NEW_SEGMENT,
631 pthread_self(), 0, 0, 0, 0);
632
633 return ret;
634}
635
636PTH_FUNCS(int, thrZucreate, thr_create_intercept,
637 (void *stk, size_t stksize, void *(*start)(void *), void *arg,
638 long flags, thread_t *new_thread),
639 (stk, stksize, start, arg, flags, new_thread));
640#endif /* VGO_solaris */
641
642#if defined(VGO_solaris)
643/*
644 * Intercepts for _ti_bind_guard() and _ti_bind_clear() functions from libc.
645 * These are intercepted during _ld_libc() call by identifying CI_BIND_GUARD
646 * and CI_BIND_CLEAR, to provide resilience against function renaming.
647 */
648static __always_inline
649int DRD_(_ti_bind_guard_intercept)(int flags) {
650 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RTLD_BIND_GUARD,
651 flags, 0, 0, 0, 0);
652 return DRD_(rtld_bind_guard)(flags);
653}
654
655static __always_inline
656int DRD_(_ti_bind_clear_intercept)(int flags) {
657 int ret = DRD_(rtld_bind_clear)(flags);
658 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RTLD_BIND_CLEAR,
659 flags, 0, 0, 0, 0);
660 return ret;
661}
662
663/*
664 * Wrapped _ld_libc() from the runtime linker ld.so.1.
665 */
666void VG_WRAP_FUNCTION_ZZ(VG_Z_LD_SO_1, ZuldZulibc)(vki_Lc_interface *ptr);
667void VG_WRAP_FUNCTION_ZZ(VG_Z_LD_SO_1, ZuldZulibc)(vki_Lc_interface *ptr)
668{
669 OrigFn fn;
670 int tag;
671
672 VALGRIND_GET_ORIG_FN(fn);
673
674 vki_Lc_interface *funcs = ptr;
675 for (tag = funcs->ci_tag; tag != 0; tag = (++funcs)->ci_tag) {
676 switch (tag) {
677 case VKI_CI_BIND_GUARD:
678 if (funcs->vki_ci_un.ci_func != DRD_(_ti_bind_guard_intercept)) {
679 DRD_(rtld_bind_guard) = funcs->vki_ci_un.ci_func;
680 funcs->vki_ci_un.ci_func = DRD_(_ti_bind_guard_intercept);
681 }
682 break;
683 case VKI_CI_BIND_CLEAR:
684 if (funcs->vki_ci_un.ci_func != DRD_(_ti_bind_clear_intercept)) {
685 DRD_(rtld_bind_clear) = funcs->vki_ci_un.ci_func;
686 funcs->vki_ci_un.ci_func = DRD_(_ti_bind_clear_intercept);
687 }
688 break;
689 }
690 }
691
692 CALL_FN_v_W(fn, ptr);
693}
694#endif /* VGO_solaris */
695
bartb2260b82011-02-13 07:55:36 +0000696static __always_inline
bart791a0c62009-07-31 17:31:44 +0000697int pthread_join_intercept(pthread_t pt_joinee, void **thread_return)
sewardjaf44c822007-11-25 14:01:38 +0000698{
bartbedfd232009-03-26 19:07:15 +0000699 int ret;
bartbedfd232009-03-26 19:07:15 +0000700 OrigFn fn;
sewardjaf44c822007-11-25 14:01:38 +0000701
bartbedfd232009-03-26 19:07:15 +0000702 VALGRIND_GET_ORIG_FN(fn);
bart5cbd26e2011-08-24 15:02:21 +0000703 /*
704 * Avoid that the sys_futex(td->tid) call invoked by the NPTL pthread_join()
705 * implementation triggers a (false positive) race report.
706 */
707 ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
bartbedfd232009-03-26 19:07:15 +0000708 CALL_FN_W_WW(ret, fn, pt_joinee, thread_return);
709 if (ret == 0)
710 {
sewardj4b3a7422011-10-24 13:21:57 +0000711 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_THREAD_JOIN,
bart575ce8e2011-05-15 07:04:03 +0000712 pt_joinee, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000713 }
bart5cbd26e2011-08-24 15:02:21 +0000714 ANNOTATE_IGNORE_READS_AND_WRITES_END();
bartbedfd232009-03-26 19:07:15 +0000715 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000716}
717
bart791a0c62009-07-31 17:31:44 +0000718PTH_FUNCS(int, pthreadZujoin, pthread_join_intercept,
719 (pthread_t pt_joinee, void **thread_return),
720 (pt_joinee, thread_return));
721
sewardj8eb8bab2015-07-21 14:44:28 +0000722#if defined(VGO_solaris)
723/* Solaris also provides thr_join() in addition to pthread_join().
724 * Both pthread_join(3C) and thr_join(3C) are based on private _thrp_join().
725 *
726 * :TODO: No functionality is currently provided for joinee == 0 and departed.
727 * This would require another client request, of course.
728 */
729static __always_inline
730int thr_join_intercept(thread_t joinee, thread_t *departed, void **thread_return)
731{
732 int ret;
733 OrigFn fn;
734
735 VALGRIND_GET_ORIG_FN(fn);
736 CALL_FN_W_WWW(ret, fn, joinee, departed, thread_return);
737 if (ret == 0)
738 {
739 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_THREAD_JOIN,
740 joinee, 0, 0, 0, 0);
741 }
742 return ret;
743}
744
745PTH_FUNCS(int, thrZujoin, thr_join_intercept,
746 (thread_t joinee, thread_t *departed, void **thread_return),
747 (joinee, departed, thread_return));
748#endif /* VGO_solaris */
749
bartb2260b82011-02-13 07:55:36 +0000750static __always_inline
bart791a0c62009-07-31 17:31:44 +0000751int pthread_detach_intercept(pthread_t pt_thread)
sewardjaf44c822007-11-25 14:01:38 +0000752{
bartbedfd232009-03-26 19:07:15 +0000753 int ret;
754 OrigFn fn;
bart5668d4e2011-03-09 17:53:28 +0000755
bartbedfd232009-03-26 19:07:15 +0000756 VALGRIND_GET_ORIG_FN(fn);
bart5668d4e2011-03-09 17:53:28 +0000757 CALL_FN_W_W(ret, fn, pt_thread);
758 DRD_(set_joinable)(pt_thread, 0);
759
bartbedfd232009-03-26 19:07:15 +0000760 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000761}
762
bart791a0c62009-07-31 17:31:44 +0000763PTH_FUNCS(int, pthreadZudetach, pthread_detach_intercept,
764 (pthread_t thread), (thread));
765
766// NOTE: be careful to intercept only pthread_cancel() and not
767// pthread_cancel_init() on Linux.
768
bartb2260b82011-02-13 07:55:36 +0000769static __always_inline
bart791a0c62009-07-31 17:31:44 +0000770int pthread_cancel_intercept(pthread_t pt_thread)
bart2bc9c102008-09-27 12:40:57 +0000771{
bartbedfd232009-03-26 19:07:15 +0000772 int ret;
773 OrigFn fn;
774 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000775 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_THREAD_CANCEL,
bart575ce8e2011-05-15 07:04:03 +0000776 pt_thread, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000777 CALL_FN_W_W(ret, fn, pt_thread);
sewardj4b3a7422011-10-24 13:21:57 +0000778 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_THREAD_CANCEL,
bart575ce8e2011-05-15 07:04:03 +0000779 pt_thread, ret==0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000780 return ret;
bart2bc9c102008-09-27 12:40:57 +0000781}
782
bart791a0c62009-07-31 17:31:44 +0000783PTH_FUNCS(int, pthreadZucancel, pthread_cancel_intercept,
784 (pthread_t thread), (thread))
785
bartb2260b82011-02-13 07:55:36 +0000786static __always_inline
bart791a0c62009-07-31 17:31:44 +0000787int pthread_once_intercept(pthread_once_t *once_control,
788 void (*init_routine)(void))
bart93a02742009-07-26 15:55:48 +0000789{
790 int ret;
791 OrigFn fn;
792 VALGRIND_GET_ORIG_FN(fn);
793 /*
794 * Ignore any data races triggered by the implementation of pthread_once().
795 * Necessary for Darwin. This is not necessary for Linux but doesn't have
796 * any known adverse effects.
797 */
bart554953f2009-07-26 16:21:00 +0000798 DRD_IGNORE_VAR(*once_control);
bart6d956dc2011-07-28 09:54:37 +0000799 ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
bart93a02742009-07-26 15:55:48 +0000800 CALL_FN_W_WW(ret, fn, once_control, init_routine);
bart6d956dc2011-07-28 09:54:37 +0000801 ANNOTATE_IGNORE_READS_AND_WRITES_END();
bart554953f2009-07-26 16:21:00 +0000802 DRD_STOP_IGNORING_VAR(*once_control);
bart93a02742009-07-26 15:55:48 +0000803 return ret;
804}
805
bart791a0c62009-07-31 17:31:44 +0000806PTH_FUNCS(int, pthreadZuonce, pthread_once_intercept,
807 (pthread_once_t *once_control, void (*init_routine)(void)),
808 (once_control, init_routine));
809
bartb2260b82011-02-13 07:55:36 +0000810static __always_inline
bart791a0c62009-07-31 17:31:44 +0000811int pthread_mutex_init_intercept(pthread_mutex_t *mutex,
812 const pthread_mutexattr_t* attr)
sewardjaf44c822007-11-25 14:01:38 +0000813{
bartbedfd232009-03-26 19:07:15 +0000814 int ret;
bartbedfd232009-03-26 19:07:15 +0000815 OrigFn fn;
816 int mt;
817 VALGRIND_GET_ORIG_FN(fn);
818 mt = PTHREAD_MUTEX_DEFAULT;
819 if (attr)
820 pthread_mutexattr_gettype(attr, &mt);
sewardj4b3a7422011-10-24 13:21:57 +0000821 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_INIT,
bart575ce8e2011-05-15 07:04:03 +0000822 mutex, DRD_(pthread_to_drd_mutex_type)(mt),
823 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000824 CALL_FN_W_WW(ret, fn, mutex, attr);
sewardj4b3a7422011-10-24 13:21:57 +0000825 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_INIT,
bart575ce8e2011-05-15 07:04:03 +0000826 mutex, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000827 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000828}
829
bart791a0c62009-07-31 17:31:44 +0000830PTH_FUNCS(int, pthreadZumutexZuinit, pthread_mutex_init_intercept,
831 (pthread_mutex_t *mutex, const pthread_mutexattr_t* attr),
832 (mutex, attr));
833
sewardj8eb8bab2015-07-21 14:44:28 +0000834#if defined(VGO_solaris)
835static __always_inline
836int mutex_init_intercept(mutex_t *mutex, int type, void *arg)
837{
838 int ret;
839 OrigFn fn;
840 VALGRIND_GET_ORIG_FN(fn);
841
842 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_INIT,
843 mutex, DRD_(thread_to_drd_mutex_type)(type),
844 0, 0, 0);
845 CALL_FN_W_WWW(ret, fn, mutex, type, arg);
846 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_INIT,
847 mutex, 0, 0, 0, 0);
848 return ret;
849}
850
851PTH_FUNCS(int, mutexZuinit, mutex_init_intercept,
852 (mutex_t *mutex, int type, void *arg),
853 (mutex, type, arg));
854#endif /* VGO_solaris */
855
bartb2260b82011-02-13 07:55:36 +0000856static __always_inline
bart791a0c62009-07-31 17:31:44 +0000857int pthread_mutex_destroy_intercept(pthread_mutex_t* mutex)
sewardjaf44c822007-11-25 14:01:38 +0000858{
bartbedfd232009-03-26 19:07:15 +0000859 int ret;
bartbedfd232009-03-26 19:07:15 +0000860 OrigFn fn;
861 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000862 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_DESTROY,
bart575ce8e2011-05-15 07:04:03 +0000863 mutex, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000864 CALL_FN_W_W(ret, fn, mutex);
sewardj4b3a7422011-10-24 13:21:57 +0000865 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_DESTROY,
bart575ce8e2011-05-15 07:04:03 +0000866 mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000867 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000868}
869
sewardj8eb8bab2015-07-21 14:44:28 +0000870#if defined(VGO_solaris)
871/* On Solaris, pthread_mutex_destroy is a weak alias to mutex_destroy. */
872PTH_FUNCS(int, mutexZudestroy, pthread_mutex_destroy_intercept,
873 (pthread_mutex_t *mutex), (mutex));
874#else
bart791a0c62009-07-31 17:31:44 +0000875PTH_FUNCS(int, pthreadZumutexZudestroy, pthread_mutex_destroy_intercept,
876 (pthread_mutex_t *mutex), (mutex));
sewardj8eb8bab2015-07-21 14:44:28 +0000877#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +0000878
bartb2260b82011-02-13 07:55:36 +0000879static __always_inline
bart791a0c62009-07-31 17:31:44 +0000880int pthread_mutex_lock_intercept(pthread_mutex_t* mutex)
sewardjaf44c822007-11-25 14:01:38 +0000881{
bartbedfd232009-03-26 19:07:15 +0000882 int ret;
bartbedfd232009-03-26 19:07:15 +0000883 OrigFn fn;
884 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000885 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +0000886 mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000887 CALL_FN_W_W(ret, fn, mutex);
sewardj4b3a7422011-10-24 13:21:57 +0000888 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +0000889 mutex, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000890 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000891}
892
sewardj8eb8bab2015-07-21 14:44:28 +0000893#if defined(VGO_solaris)
894/* On Solaris, pthread_mutex_lock is a weak alias to mutex_lock. */
895PTH_FUNCS(int, mutexZulock, pthread_mutex_lock_intercept,
896 (pthread_mutex_t *mutex), (mutex));
897#else
bart791a0c62009-07-31 17:31:44 +0000898PTH_FUNCS(int, pthreadZumutexZulock, pthread_mutex_lock_intercept,
899 (pthread_mutex_t *mutex), (mutex));
sewardj8eb8bab2015-07-21 14:44:28 +0000900#endif /* VGO_solaris */
901
902#if defined(VGO_solaris)
903/* Internal to libc. Mutex is usually initialized only implicitly,
904 * by zeroing mutex_t structure.
905 */
906static __always_inline
907void lmutex_lock_intercept(mutex_t *mutex)
908{
909 OrigFn fn;
910 VALGRIND_GET_ORIG_FN(fn);
911 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK,
912 mutex,
913 DRD_(mutex_type)((pthread_mutex_t *) mutex),
914 False /* try_lock */, 0, 0);
915 CALL_FN_v_W(fn, mutex);
916 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK,
917 mutex, True /* took_lock */, 0, 0, 0);
918}
919
920PTH_FUNCS(void, lmutexZulock, lmutex_lock_intercept,
921 (mutex_t *mutex), (mutex));
922#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +0000923
bartb2260b82011-02-13 07:55:36 +0000924static __always_inline
bart791a0c62009-07-31 17:31:44 +0000925int pthread_mutex_trylock_intercept(pthread_mutex_t* mutex)
sewardjaf44c822007-11-25 14:01:38 +0000926{
bartbedfd232009-03-26 19:07:15 +0000927 int ret;
bartbedfd232009-03-26 19:07:15 +0000928 OrigFn fn;
929 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000930 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +0000931 mutex, DRD_(mutex_type)(mutex), 1, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000932 CALL_FN_W_W(ret, fn, mutex);
sewardj4b3a7422011-10-24 13:21:57 +0000933 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +0000934 mutex, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000935 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000936}
937
sewardj8eb8bab2015-07-21 14:44:28 +0000938#if defined(VGO_solaris)
939/* On Solaris, pthread_mutex_trylock is a weak alias to mutex_trylock. */
940PTH_FUNCS(int, mutexZutrylock, pthread_mutex_trylock_intercept,
941 (pthread_mutex_t *mutex), (mutex));
942#else
bart791a0c62009-07-31 17:31:44 +0000943PTH_FUNCS(int, pthreadZumutexZutrylock, pthread_mutex_trylock_intercept,
944 (pthread_mutex_t *mutex), (mutex));
sewardj8eb8bab2015-07-21 14:44:28 +0000945#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +0000946
bartb2260b82011-02-13 07:55:36 +0000947static __always_inline
bart791a0c62009-07-31 17:31:44 +0000948int pthread_mutex_timedlock_intercept(pthread_mutex_t *mutex,
949 const struct timespec *abs_timeout)
sewardj85642922008-01-14 11:54:56 +0000950{
bartbedfd232009-03-26 19:07:15 +0000951 int ret;
bartbedfd232009-03-26 19:07:15 +0000952 OrigFn fn;
953 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000954 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +0000955 mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000956 CALL_FN_W_WW(ret, fn, mutex, abs_timeout);
sewardj4b3a7422011-10-24 13:21:57 +0000957 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +0000958 mutex, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000959 return ret;
sewardj85642922008-01-14 11:54:56 +0000960}
961
bart791a0c62009-07-31 17:31:44 +0000962PTH_FUNCS(int, pthreadZumutexZutimedlock, pthread_mutex_timedlock_intercept,
963 (pthread_mutex_t *mutex, const struct timespec *abs_timeout),
964 (mutex, abs_timeout));
sewardj8eb8bab2015-07-21 14:44:28 +0000965#if defined(VGO_solaris)
966PTH_FUNCS(int,
967 pthreadZumutexZureltimedlockZunp, pthread_mutex_timedlock_intercept,
968 (pthread_mutex_t *mutex, const struct timespec *timeout),
969 (mutex, timeout));
970#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +0000971
bartb2260b82011-02-13 07:55:36 +0000972static __always_inline
bart791a0c62009-07-31 17:31:44 +0000973int pthread_mutex_unlock_intercept(pthread_mutex_t *mutex)
sewardjaf44c822007-11-25 14:01:38 +0000974{
bartbedfd232009-03-26 19:07:15 +0000975 int ret;
bartbedfd232009-03-26 19:07:15 +0000976 OrigFn fn;
977 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000978 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_UNLOCK,
bart575ce8e2011-05-15 07:04:03 +0000979 mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000980 CALL_FN_W_W(ret, fn, mutex);
sewardj4b3a7422011-10-24 13:21:57 +0000981 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_UNLOCK,
bart575ce8e2011-05-15 07:04:03 +0000982 mutex, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000983 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000984}
985
sewardj8eb8bab2015-07-21 14:44:28 +0000986#if defined(VGO_solaris)
987/* On Solaris, pthread_mutex_unlock is a weak alias to mutex_unlock. */
988PTH_FUNCS(int, mutexZuunlock, pthread_mutex_unlock_intercept,
989 (pthread_mutex_t *mutex), (mutex));
990#else
bart791a0c62009-07-31 17:31:44 +0000991PTH_FUNCS(int, pthreadZumutexZuunlock, pthread_mutex_unlock_intercept,
992 (pthread_mutex_t *mutex), (mutex));
sewardj8eb8bab2015-07-21 14:44:28 +0000993#endif /* VGO_solaris */
994
995#if defined(VGO_solaris)
996/* Internal to libc. */
997static __always_inline
998void lmutex_unlock_intercept(mutex_t *mutex)
999{
1000 OrigFn fn;
1001 VALGRIND_GET_ORIG_FN(fn);
1002 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_UNLOCK,
1003 mutex,
1004 DRD_(mutex_type)((pthread_mutex_t *) mutex),
1005 0, 0, 0);
1006 CALL_FN_v_W(fn, mutex);
1007 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_UNLOCK,
1008 mutex, 0, 0, 0, 0);
1009}
1010
1011PTH_FUNCS(void, lmutexZuunlock, lmutex_unlock_intercept,
1012 (mutex_t *mutex), (mutex));
1013#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +00001014
bartb2260b82011-02-13 07:55:36 +00001015static __always_inline
bart791a0c62009-07-31 17:31:44 +00001016int pthread_cond_init_intercept(pthread_cond_t* cond,
1017 const pthread_condattr_t* attr)
sewardjaf44c822007-11-25 14:01:38 +00001018{
bartbedfd232009-03-26 19:07:15 +00001019 int ret;
bartbedfd232009-03-26 19:07:15 +00001020 OrigFn fn;
1021 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001022 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_INIT,
bart575ce8e2011-05-15 07:04:03 +00001023 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001024 CALL_FN_W_WW(ret, fn, cond, attr);
sewardj4b3a7422011-10-24 13:21:57 +00001025 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_INIT,
bart575ce8e2011-05-15 07:04:03 +00001026 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001027 return ret;
sewardjaf44c822007-11-25 14:01:38 +00001028}
1029
bart791a0c62009-07-31 17:31:44 +00001030PTH_FUNCS(int, pthreadZucondZuinit, pthread_cond_init_intercept,
1031 (pthread_cond_t* cond, const pthread_condattr_t* attr),
1032 (cond, attr));
1033
sewardj8eb8bab2015-07-21 14:44:28 +00001034#if defined(VGO_solaris)
1035static __always_inline
1036int cond_init_intercept(cond_t *cond, int type, void *arg)
1037{
1038 int ret;
1039 OrigFn fn;
1040 VALGRIND_GET_ORIG_FN(fn);
1041 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_INIT,
1042 cond, 0, 0, 0, 0);
1043 CALL_FN_W_WWW(ret, fn, cond, type, arg);
1044 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_INIT,
1045 cond, 0, 0, 0, 0);
1046 return ret;
1047}
1048
1049PTH_FUNCS(int, condZuinit, cond_init_intercept,
1050 (cond_t *cond, int type, void *arg),
1051 (cond, type, arg));
1052#endif /* VGO_solaris */
1053
bartb2260b82011-02-13 07:55:36 +00001054static __always_inline
bart791a0c62009-07-31 17:31:44 +00001055int pthread_cond_destroy_intercept(pthread_cond_t* cond)
sewardjaf44c822007-11-25 14:01:38 +00001056{
bartbedfd232009-03-26 19:07:15 +00001057 int ret;
bartbedfd232009-03-26 19:07:15 +00001058 OrigFn fn;
1059 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001060 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_DESTROY,
bart575ce8e2011-05-15 07:04:03 +00001061 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001062 CALL_FN_W_W(ret, fn, cond);
sewardj4b3a7422011-10-24 13:21:57 +00001063 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_DESTROY,
bartd36fa802012-12-24 10:22:14 +00001064 cond, ret==0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001065 return ret;
sewardjaf44c822007-11-25 14:01:38 +00001066}
1067
sewardj8eb8bab2015-07-21 14:44:28 +00001068#if defined(VGO_solaris)
1069/* On Solaris, pthread_cond_destroy is a weak alias to cond_destroy. */
1070PTH_FUNCS(int, condZudestroy, pthread_cond_destroy_intercept,
1071 (pthread_cond_t *cond), (cond));
1072#else
bart791a0c62009-07-31 17:31:44 +00001073PTH_FUNCS(int, pthreadZucondZudestroy, pthread_cond_destroy_intercept,
1074 (pthread_cond_t* cond), (cond));
sewardj8eb8bab2015-07-21 14:44:28 +00001075#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +00001076
bartb2260b82011-02-13 07:55:36 +00001077static __always_inline
bart791a0c62009-07-31 17:31:44 +00001078int pthread_cond_wait_intercept(pthread_cond_t *cond, pthread_mutex_t *mutex)
sewardjaf44c822007-11-25 14:01:38 +00001079{
bartbedfd232009-03-26 19:07:15 +00001080 int ret;
bartbedfd232009-03-26 19:07:15 +00001081 OrigFn fn;
1082 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001083 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001084 cond, mutex, DRD_(mutex_type)(mutex), 0, 0);
bartbedfd232009-03-26 19:07:15 +00001085 CALL_FN_W_WW(ret, fn, cond, mutex);
sewardj4b3a7422011-10-24 13:21:57 +00001086 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001087 cond, mutex, 1, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001088 return ret;
sewardjaf44c822007-11-25 14:01:38 +00001089}
1090
bart791a0c62009-07-31 17:31:44 +00001091PTH_FUNCS(int, pthreadZucondZuwait, pthread_cond_wait_intercept,
1092 (pthread_cond_t *cond, pthread_mutex_t *mutex),
1093 (cond, mutex));
sewardj8eb8bab2015-07-21 14:44:28 +00001094#if defined(VGO_solaris)
1095PTH_FUNCS(int, condZuwait, pthread_cond_wait_intercept,
1096 (pthread_cond_t *cond, pthread_mutex_t *mutex),
1097 (cond, mutex));
1098#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +00001099
bartb2260b82011-02-13 07:55:36 +00001100static __always_inline
bart791a0c62009-07-31 17:31:44 +00001101int pthread_cond_timedwait_intercept(pthread_cond_t *cond,
1102 pthread_mutex_t *mutex,
1103 const struct timespec* abstime)
sewardjaf44c822007-11-25 14:01:38 +00001104{
bartbedfd232009-03-26 19:07:15 +00001105 int ret;
bartbedfd232009-03-26 19:07:15 +00001106 OrigFn fn;
1107 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001108 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001109 cond, mutex, DRD_(mutex_type)(mutex), 0, 0);
bartbedfd232009-03-26 19:07:15 +00001110 CALL_FN_W_WWW(ret, fn, cond, mutex, abstime);
sewardj4b3a7422011-10-24 13:21:57 +00001111 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001112 cond, mutex, 1, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001113 return ret;
sewardjaf44c822007-11-25 14:01:38 +00001114}
1115
bart791a0c62009-07-31 17:31:44 +00001116PTH_FUNCS(int, pthreadZucondZutimedwait, pthread_cond_timedwait_intercept,
1117 (pthread_cond_t *cond, pthread_mutex_t *mutex,
1118 const struct timespec* abstime),
1119 (cond, mutex, abstime));
sewardj8eb8bab2015-07-21 14:44:28 +00001120#if defined(VGO_solaris)
1121PTH_FUNCS(int, condZutimedwait, pthread_cond_timedwait_intercept,
1122 (pthread_cond_t *cond, pthread_mutex_t *mutex,
1123 const struct timespec *timeout),
1124 (cond, mutex, timeout));
1125PTH_FUNCS(int, condZureltimedwait, pthread_cond_timedwait_intercept,
1126 (pthread_cond_t *cond, pthread_mutex_t *mutex,
1127 const struct timespec *timeout),
1128 (cond, mutex, timeout));
1129#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +00001130
barte8cbb402009-07-22 19:17:05 +00001131// NOTE: be careful to intercept only pthread_cond_signal() and not Darwin's
1132// pthread_cond_signal_thread_np(). The former accepts one argument; the latter
1133// two. Intercepting all pthread_cond_signal* functions will cause only one
1134// argument to be passed to pthread_cond_signal_np() and hence will cause this
1135// last function to crash.
1136
bartb2260b82011-02-13 07:55:36 +00001137static __always_inline
bart791a0c62009-07-31 17:31:44 +00001138int pthread_cond_signal_intercept(pthread_cond_t* cond)
barte8cbb402009-07-22 19:17:05 +00001139{
1140 int ret;
barte8cbb402009-07-22 19:17:05 +00001141 OrigFn fn;
1142 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001143 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_SIGNAL,
bart575ce8e2011-05-15 07:04:03 +00001144 cond, 0, 0, 0, 0);
barte8cbb402009-07-22 19:17:05 +00001145 CALL_FN_W_W(ret, fn, cond);
sewardj4b3a7422011-10-24 13:21:57 +00001146 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_SIGNAL,
bart575ce8e2011-05-15 07:04:03 +00001147 cond, 0, 0, 0, 0);
barte8cbb402009-07-22 19:17:05 +00001148 return ret;
1149}
1150
sewardj8eb8bab2015-07-21 14:44:28 +00001151#if defined(VGO_solaris)
1152/* On Solaris, pthread_cond_signal is a weak alias to cond_signal. */
1153PTH_FUNCS(int, condZusignal, pthread_cond_signal_intercept,
1154 (pthread_cond_t *cond), (cond));
1155#else
bart791a0c62009-07-31 17:31:44 +00001156PTH_FUNCS(int, pthreadZucondZusignal, pthread_cond_signal_intercept,
1157 (pthread_cond_t* cond), (cond));
sewardj8eb8bab2015-07-21 14:44:28 +00001158#endif /* VGO_solaris */
sewardjaf44c822007-11-25 14:01:38 +00001159
bartb2260b82011-02-13 07:55:36 +00001160static __always_inline
bart791a0c62009-07-31 17:31:44 +00001161int pthread_cond_broadcast_intercept(pthread_cond_t* cond)
sewardjaf44c822007-11-25 14:01:38 +00001162{
bartbedfd232009-03-26 19:07:15 +00001163 int ret;
bartbedfd232009-03-26 19:07:15 +00001164 OrigFn fn;
1165 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001166 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_BROADCAST,
bart575ce8e2011-05-15 07:04:03 +00001167 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001168 CALL_FN_W_W(ret, fn, cond);
sewardj4b3a7422011-10-24 13:21:57 +00001169 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_BROADCAST,
bart575ce8e2011-05-15 07:04:03 +00001170 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001171 return ret;
sewardjaf44c822007-11-25 14:01:38 +00001172}
1173
sewardj8eb8bab2015-07-21 14:44:28 +00001174#if defined(VGO_solaris)
1175/* On Solaris, pthread_cond_broadcast is a weak alias to cond_broadcast. */
1176PTH_FUNCS(int, condZubroadcast, pthread_cond_broadcast_intercept,
1177 (pthread_cond_t *cond), (cond));
1178#else
bart791a0c62009-07-31 17:31:44 +00001179PTH_FUNCS(int, pthreadZucondZubroadcast, pthread_cond_broadcast_intercept,
1180 (pthread_cond_t* cond), (cond));
sewardj8eb8bab2015-07-21 14:44:28 +00001181#endif /* VGO_solaris */
sewardjaf44c822007-11-25 14:01:38 +00001182
petarj6d79b742012-12-20 18:56:57 +00001183#if defined(HAVE_PTHREAD_SPIN_LOCK) \
1184 && !defined(DISABLE_PTHREAD_SPINLOCK_INTERCEPT)
bartb2260b82011-02-13 07:55:36 +00001185static __always_inline
bart791a0c62009-07-31 17:31:44 +00001186int pthread_spin_init_intercept(pthread_spinlock_t *spinlock, int pshared)
sewardjaf44c822007-11-25 14:01:38 +00001187{
bartbedfd232009-03-26 19:07:15 +00001188 int ret;
bartbedfd232009-03-26 19:07:15 +00001189 OrigFn fn;
1190 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001191 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK,
bart575ce8e2011-05-15 07:04:03 +00001192 spinlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001193 CALL_FN_W_WW(ret, fn, spinlock, pshared);
sewardj4b3a7422011-10-24 13:21:57 +00001194 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK,
bart575ce8e2011-05-15 07:04:03 +00001195 spinlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001196 return ret;
sewardjaf44c822007-11-25 14:01:38 +00001197}
1198
bart791a0c62009-07-31 17:31:44 +00001199PTH_FUNCS(int, pthreadZuspinZuinit, pthread_spin_init_intercept,
1200 (pthread_spinlock_t *spinlock, int pshared), (spinlock, pshared));
1201
bartb2260b82011-02-13 07:55:36 +00001202static __always_inline
bart791a0c62009-07-31 17:31:44 +00001203int pthread_spin_destroy_intercept(pthread_spinlock_t *spinlock)
sewardjaf44c822007-11-25 14:01:38 +00001204{
bartbedfd232009-03-26 19:07:15 +00001205 int ret;
bartbedfd232009-03-26 19:07:15 +00001206 OrigFn fn;
1207 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001208 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_DESTROY,
bart575ce8e2011-05-15 07:04:03 +00001209 spinlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001210 CALL_FN_W_W(ret, fn, spinlock);
sewardj4b3a7422011-10-24 13:21:57 +00001211 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_DESTROY,
bart575ce8e2011-05-15 07:04:03 +00001212 spinlock, mutex_type_spinlock, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001213 return ret;
sewardjaf44c822007-11-25 14:01:38 +00001214}
1215
bart791a0c62009-07-31 17:31:44 +00001216PTH_FUNCS(int, pthreadZuspinZudestroy, pthread_spin_destroy_intercept,
1217 (pthread_spinlock_t *spinlock), (spinlock));
1218
bartb2260b82011-02-13 07:55:36 +00001219static __always_inline
bart791a0c62009-07-31 17:31:44 +00001220int pthread_spin_lock_intercept(pthread_spinlock_t *spinlock)
sewardjaf44c822007-11-25 14:01:38 +00001221{
bartbedfd232009-03-26 19:07:15 +00001222 int ret;
bartbedfd232009-03-26 19:07:15 +00001223 OrigFn fn;
1224 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001225 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +00001226 spinlock, mutex_type_spinlock, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001227 CALL_FN_W_W(ret, fn, spinlock);
sewardj4b3a7422011-10-24 13:21:57 +00001228 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +00001229 spinlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001230 return ret;
sewardjaf44c822007-11-25 14:01:38 +00001231}
1232
bart791a0c62009-07-31 17:31:44 +00001233PTH_FUNCS(int, pthreadZuspinZulock, pthread_spin_lock_intercept,
1234 (pthread_spinlock_t *spinlock), (spinlock));
1235
bartb2260b82011-02-13 07:55:36 +00001236static __always_inline
bart791a0c62009-07-31 17:31:44 +00001237int pthread_spin_trylock_intercept(pthread_spinlock_t *spinlock)
sewardjaf44c822007-11-25 14:01:38 +00001238{
bartbedfd232009-03-26 19:07:15 +00001239 int ret;
bartbedfd232009-03-26 19:07:15 +00001240 OrigFn fn;
1241 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001242 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +00001243 spinlock, mutex_type_spinlock, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001244 CALL_FN_W_W(ret, fn, spinlock);
sewardj4b3a7422011-10-24 13:21:57 +00001245 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +00001246 spinlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001247 return ret;
sewardjaf44c822007-11-25 14:01:38 +00001248}
1249
bart791a0c62009-07-31 17:31:44 +00001250PTH_FUNCS(int, pthreadZuspinZutrylock, pthread_spin_trylock_intercept,
1251 (pthread_spinlock_t *spinlock), (spinlock));
1252
bartb2260b82011-02-13 07:55:36 +00001253static __always_inline
bart791a0c62009-07-31 17:31:44 +00001254int pthread_spin_unlock_intercept(pthread_spinlock_t *spinlock)
sewardjaf44c822007-11-25 14:01:38 +00001255{
bartbedfd232009-03-26 19:07:15 +00001256 int ret;
bartbedfd232009-03-26 19:07:15 +00001257 OrigFn fn;
1258 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001259 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK,
bart575ce8e2011-05-15 07:04:03 +00001260 spinlock, mutex_type_spinlock, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001261 CALL_FN_W_W(ret, fn, spinlock);
sewardj4b3a7422011-10-24 13:21:57 +00001262 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK,
bart575ce8e2011-05-15 07:04:03 +00001263 spinlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001264 return ret;
sewardjaf44c822007-11-25 14:01:38 +00001265}
bart791a0c62009-07-31 17:31:44 +00001266
1267PTH_FUNCS(int, pthreadZuspinZuunlock, pthread_spin_unlock_intercept,
1268 (pthread_spinlock_t *spinlock), (spinlock));
njnf76d27a2009-05-28 01:53:07 +00001269#endif // HAVE_PTHREAD_SPIN_LOCK
sewardjaf44c822007-11-25 14:01:38 +00001270
njnf76d27a2009-05-28 01:53:07 +00001271
1272#if defined(HAVE_PTHREAD_BARRIER_INIT)
bartb2260b82011-02-13 07:55:36 +00001273static __always_inline
bart791a0c62009-07-31 17:31:44 +00001274int pthread_barrier_init_intercept(pthread_barrier_t* barrier,
1275 const pthread_barrierattr_t* attr,
1276 unsigned count)
sewardj85642922008-01-14 11:54:56 +00001277{
bartbedfd232009-03-26 19:07:15 +00001278 int ret;
bartbedfd232009-03-26 19:07:15 +00001279 OrigFn fn;
1280 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001281 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_BARRIER_INIT,
bart575ce8e2011-05-15 07:04:03 +00001282 barrier, pthread_barrier, count, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001283 CALL_FN_W_WWW(ret, fn, barrier, attr, count);
sewardj4b3a7422011-10-24 13:21:57 +00001284 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_BARRIER_INIT,
bart575ce8e2011-05-15 07:04:03 +00001285 barrier, pthread_barrier, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001286 return ret;
sewardj85642922008-01-14 11:54:56 +00001287}
1288
bart791a0c62009-07-31 17:31:44 +00001289PTH_FUNCS(int, pthreadZubarrierZuinit, pthread_barrier_init_intercept,
1290 (pthread_barrier_t* barrier, const pthread_barrierattr_t* attr,
1291 unsigned count), (barrier, attr, count));
1292
bartb2260b82011-02-13 07:55:36 +00001293static __always_inline
bart791a0c62009-07-31 17:31:44 +00001294int pthread_barrier_destroy_intercept(pthread_barrier_t* barrier)
sewardj85642922008-01-14 11:54:56 +00001295{
bartbedfd232009-03-26 19:07:15 +00001296 int ret;
bartbedfd232009-03-26 19:07:15 +00001297 OrigFn fn;
1298 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001299 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_BARRIER_DESTROY,
bart575ce8e2011-05-15 07:04:03 +00001300 barrier, pthread_barrier, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001301 CALL_FN_W_W(ret, fn, barrier);
sewardj4b3a7422011-10-24 13:21:57 +00001302 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_BARRIER_DESTROY,
bart575ce8e2011-05-15 07:04:03 +00001303 barrier, pthread_barrier, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001304 return ret;
sewardj85642922008-01-14 11:54:56 +00001305}
1306
bart791a0c62009-07-31 17:31:44 +00001307PTH_FUNCS(int, pthreadZubarrierZudestroy, pthread_barrier_destroy_intercept,
1308 (pthread_barrier_t* barrier), (barrier));
1309
bartb2260b82011-02-13 07:55:36 +00001310static __always_inline
bart791a0c62009-07-31 17:31:44 +00001311int pthread_barrier_wait_intercept(pthread_barrier_t* barrier)
sewardj85642922008-01-14 11:54:56 +00001312{
bartbedfd232009-03-26 19:07:15 +00001313 int ret;
bartbedfd232009-03-26 19:07:15 +00001314 OrigFn fn;
1315 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001316 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_BARRIER_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001317 barrier, pthread_barrier, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001318 CALL_FN_W_W(ret, fn, barrier);
sewardj4b3a7422011-10-24 13:21:57 +00001319 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_BARRIER_WAIT,
bartbedfd232009-03-26 19:07:15 +00001320 barrier, pthread_barrier,
1321 ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD,
1322 ret == PTHREAD_BARRIER_SERIAL_THREAD, 0);
1323 return ret;
sewardj85642922008-01-14 11:54:56 +00001324}
bart791a0c62009-07-31 17:31:44 +00001325
1326PTH_FUNCS(int, pthreadZubarrierZuwait, pthread_barrier_wait_intercept,
1327 (pthread_barrier_t* barrier), (barrier));
njnf76d27a2009-05-28 01:53:07 +00001328#endif // HAVE_PTHREAD_BARRIER_INIT
sewardj85642922008-01-14 11:54:56 +00001329
1330
bartb2260b82011-02-13 07:55:36 +00001331static __always_inline
bart791a0c62009-07-31 17:31:44 +00001332int sem_init_intercept(sem_t *sem, int pshared, unsigned int value)
sewardj85642922008-01-14 11:54:56 +00001333{
bartbedfd232009-03-26 19:07:15 +00001334 int ret;
bartbedfd232009-03-26 19:07:15 +00001335 OrigFn fn;
1336 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001337 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_INIT,
bart575ce8e2011-05-15 07:04:03 +00001338 sem, pshared, value, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001339 CALL_FN_W_WWW(ret, fn, sem, pshared, value);
sewardj4b3a7422011-10-24 13:21:57 +00001340 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_INIT,
bart575ce8e2011-05-15 07:04:03 +00001341 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001342 return ret;
sewardj85642922008-01-14 11:54:56 +00001343}
1344
bart791a0c62009-07-31 17:31:44 +00001345PTH_FUNCS(int, semZuinit, sem_init_intercept,
1346 (sem_t *sem, int pshared, unsigned int value), (sem, pshared, value));
1347
sewardj8eb8bab2015-07-21 14:44:28 +00001348#if defined(VGO_solaris)
1349static __always_inline
1350int sema_init_intercept(sema_t *sem, unsigned int value, int type, void *arg)
1351{
1352 int ret;
1353 OrigFn fn;
1354 VALGRIND_GET_ORIG_FN(fn);
1355 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_INIT,
1356 sem, type == USYNC_PROCESS ? 1 : 0,
1357 value, 0, 0);
1358 CALL_FN_W_WWWW(ret, fn, sem, value, type, arg);
1359 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_INIT,
1360 sem, 0, 0, 0, 0);
1361 return ret;
1362}
1363
1364PTH_FUNCS(int, semaZuinit, sema_init_intercept,
1365 (sema_t *sem, unsigned int value, int type, void *arg),
1366 (sem, value, type, arg));
1367#endif /* VGO_solaris */
1368
bartb2260b82011-02-13 07:55:36 +00001369static __always_inline
bart791a0c62009-07-31 17:31:44 +00001370int sem_destroy_intercept(sem_t *sem)
sewardj85642922008-01-14 11:54:56 +00001371{
bartbedfd232009-03-26 19:07:15 +00001372 int ret;
bartbedfd232009-03-26 19:07:15 +00001373 OrigFn fn;
1374 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001375 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_DESTROY,
bart575ce8e2011-05-15 07:04:03 +00001376 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001377 CALL_FN_W_W(ret, fn, sem);
sewardj4b3a7422011-10-24 13:21:57 +00001378 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_DESTROY,
bart575ce8e2011-05-15 07:04:03 +00001379 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001380 return ret;
sewardj85642922008-01-14 11:54:56 +00001381}
1382
bart791a0c62009-07-31 17:31:44 +00001383PTH_FUNCS(int, semZudestroy, sem_destroy_intercept, (sem_t *sem), (sem));
sewardj8eb8bab2015-07-21 14:44:28 +00001384#if defined(VGO_solaris)
1385PTH_FUNCS(int, semaZudestroy, sem_destroy_intercept, (sem_t *sem), (sem));
1386#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +00001387
bartb2260b82011-02-13 07:55:36 +00001388static __always_inline
bart791a0c62009-07-31 17:31:44 +00001389sem_t* sem_open_intercept(const char *name, int oflag, mode_t mode,
1390 unsigned int value)
bart25f9f542009-07-23 16:31:39 +00001391{
1392 sem_t *ret;
bart25f9f542009-07-23 16:31:39 +00001393 OrigFn fn;
1394 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001395 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_OPEN,
bart575ce8e2011-05-15 07:04:03 +00001396 name, oflag, mode, value, 0);
bart25f9f542009-07-23 16:31:39 +00001397 CALL_FN_W_WWWW(ret, fn, name, oflag, mode, value);
sewardj4b3a7422011-10-24 13:21:57 +00001398 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_OPEN,
bart575ce8e2011-05-15 07:04:03 +00001399 ret != SEM_FAILED ? ret : 0,
1400 name, oflag, mode, value);
bart25f9f542009-07-23 16:31:39 +00001401 return ret;
1402}
1403
bart791a0c62009-07-31 17:31:44 +00001404PTH_FUNCS(sem_t *, semZuopen, sem_open_intercept,
1405 (const char *name, int oflag, mode_t mode, unsigned int value),
1406 (name, oflag, mode, value));
1407
bartb2260b82011-02-13 07:55:36 +00001408static __always_inline int sem_close_intercept(sem_t *sem)
bart25f9f542009-07-23 16:31:39 +00001409{
1410 int ret;
bart25f9f542009-07-23 16:31:39 +00001411 OrigFn fn;
1412 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001413 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_CLOSE,
bart575ce8e2011-05-15 07:04:03 +00001414 sem, 0, 0, 0, 0);
bart25f9f542009-07-23 16:31:39 +00001415 CALL_FN_W_W(ret, fn, sem);
sewardj4b3a7422011-10-24 13:21:57 +00001416 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_CLOSE,
bart575ce8e2011-05-15 07:04:03 +00001417 sem, 0, 0, 0, 0);
bart25f9f542009-07-23 16:31:39 +00001418 return ret;
1419}
1420
bart791a0c62009-07-31 17:31:44 +00001421PTH_FUNCS(int, semZuclose, sem_close_intercept, (sem_t *sem), (sem));
1422
bartb2260b82011-02-13 07:55:36 +00001423static __always_inline int sem_wait_intercept(sem_t *sem)
sewardj85642922008-01-14 11:54:56 +00001424{
bartbedfd232009-03-26 19:07:15 +00001425 int ret;
bartbedfd232009-03-26 19:07:15 +00001426 OrigFn fn;
1427 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001428 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001429 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001430 CALL_FN_W_W(ret, fn, sem);
sewardj4b3a7422011-10-24 13:21:57 +00001431 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001432 sem, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001433 return ret;
sewardj85642922008-01-14 11:54:56 +00001434}
1435
bart791a0c62009-07-31 17:31:44 +00001436PTH_FUNCS(int, semZuwait, sem_wait_intercept, (sem_t *sem), (sem));
sewardj8eb8bab2015-07-21 14:44:28 +00001437#if defined(VGO_solaris)
1438PTH_FUNCS(int, semaZuwait, sem_wait_intercept, (sem_t *sem), (sem));
1439#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +00001440
bartb2260b82011-02-13 07:55:36 +00001441static __always_inline int sem_trywait_intercept(sem_t *sem)
sewardj85642922008-01-14 11:54:56 +00001442{
bartbedfd232009-03-26 19:07:15 +00001443 int ret;
bartbedfd232009-03-26 19:07:15 +00001444 OrigFn fn;
1445 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001446 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001447 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001448 CALL_FN_W_W(ret, fn, sem);
sewardj4b3a7422011-10-24 13:21:57 +00001449 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001450 sem, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001451 return ret;
sewardj85642922008-01-14 11:54:56 +00001452}
1453
bart791a0c62009-07-31 17:31:44 +00001454PTH_FUNCS(int, semZutrywait, sem_trywait_intercept, (sem_t *sem), (sem));
sewardj8eb8bab2015-07-21 14:44:28 +00001455#if defined(VGO_solaris)
1456PTH_FUNCS(int, semaZutrywait, sem_trywait_intercept, (sem_t *sem), (sem));
1457#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +00001458
bartb2260b82011-02-13 07:55:36 +00001459static __always_inline
bart791a0c62009-07-31 17:31:44 +00001460int sem_timedwait_intercept(sem_t *sem, const struct timespec *abs_timeout)
sewardj85642922008-01-14 11:54:56 +00001461{
bartbedfd232009-03-26 19:07:15 +00001462 int ret;
bartbedfd232009-03-26 19:07:15 +00001463 OrigFn fn;
1464 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001465 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001466 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001467 CALL_FN_W_WW(ret, fn, sem, abs_timeout);
sewardj4b3a7422011-10-24 13:21:57 +00001468 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001469 sem, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001470 return ret;
sewardj85642922008-01-14 11:54:56 +00001471}
1472
bart791a0c62009-07-31 17:31:44 +00001473PTH_FUNCS(int, semZutimedwait, sem_timedwait_intercept,
1474 (sem_t *sem, const struct timespec *abs_timeout),
1475 (sem, abs_timeout));
sewardj8eb8bab2015-07-21 14:44:28 +00001476#if defined(VGO_solaris)
1477PTH_FUNCS(int, semaZutimedwait, sem_timedwait_intercept,
1478 (sem_t *sem, const struct timespec *timeout),
1479 (sem, timeout));
1480PTH_FUNCS(int, semaZureltimedwait, sem_timedwait_intercept,
1481 (sem_t *sem, const struct timespec *timeout),
1482 (sem, timeout));
1483#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +00001484
bartb2260b82011-02-13 07:55:36 +00001485static __always_inline int sem_post_intercept(sem_t *sem)
sewardj85642922008-01-14 11:54:56 +00001486{
bartbedfd232009-03-26 19:07:15 +00001487 int ret;
bartbedfd232009-03-26 19:07:15 +00001488 OrigFn fn;
1489 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001490 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_POST,
bart575ce8e2011-05-15 07:04:03 +00001491 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001492 CALL_FN_W_W(ret, fn, sem);
sewardj4b3a7422011-10-24 13:21:57 +00001493 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_POST,
bart575ce8e2011-05-15 07:04:03 +00001494 sem, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001495 return ret;
sewardj85642922008-01-14 11:54:56 +00001496}
1497
bart791a0c62009-07-31 17:31:44 +00001498PTH_FUNCS(int, semZupost, sem_post_intercept, (sem_t *sem), (sem));
sewardj8eb8bab2015-07-21 14:44:28 +00001499#if defined(VGO_solaris)
1500PTH_FUNCS(int, semaZupost, sem_post_intercept, (sem_t *sem), (sem));
1501#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +00001502
sewardj0c09bf02011-07-11 22:11:58 +00001503/* Android's pthread.h doesn't say anything about rwlocks, hence these
1504 functions have to be conditionally compiled. */
1505#if defined(HAVE_PTHREAD_RWLOCK_T)
1506
bartb2260b82011-02-13 07:55:36 +00001507static __always_inline
bart791a0c62009-07-31 17:31:44 +00001508int pthread_rwlock_init_intercept(pthread_rwlock_t* rwlock,
1509 const pthread_rwlockattr_t* attr)
bart00344642008-03-01 15:27:41 +00001510{
bartbedfd232009-03-26 19:07:15 +00001511 int ret;
bartbedfd232009-03-26 19:07:15 +00001512 OrigFn fn;
1513 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001514 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_INIT,
bart575ce8e2011-05-15 07:04:03 +00001515 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001516 CALL_FN_W_WW(ret, fn, rwlock, attr);
bart63eb9892014-03-19 18:48:01 +00001517 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_INIT,
1518 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001519 return ret;
bart00344642008-03-01 15:27:41 +00001520}
1521
bart791a0c62009-07-31 17:31:44 +00001522PTH_FUNCS(int,
1523 pthreadZurwlockZuinit, pthread_rwlock_init_intercept,
1524 (pthread_rwlock_t* rwlock, const pthread_rwlockattr_t* attr),
1525 (rwlock, attr));
1526
sewardj8eb8bab2015-07-21 14:44:28 +00001527#if defined(VGO_solaris)
1528static __always_inline
1529int rwlock_init_intercept(rwlock_t *rwlock, int type, void *arg)
1530{
1531 int ret;
1532 OrigFn fn;
1533 VALGRIND_GET_ORIG_FN(fn);
1534 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_INIT,
1535 rwlock, 0, 0, 0, 0);
1536 CALL_FN_W_WWW(ret, fn, rwlock, type, arg);
1537 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_INIT,
1538 rwlock, 0, 0, 0, 0);
1539 return ret;
1540}
1541
1542PTH_FUNCS(int, rwlockZuinit, rwlock_init_intercept,
1543 (rwlock_t *rwlock, int type, void *arg),
1544 (rwlock, type, arg));
1545#endif /* VGO_solaris */
1546
bartb2260b82011-02-13 07:55:36 +00001547static __always_inline
bart791a0c62009-07-31 17:31:44 +00001548int pthread_rwlock_destroy_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001549{
bartbedfd232009-03-26 19:07:15 +00001550 int ret;
bartbedfd232009-03-26 19:07:15 +00001551 OrigFn fn;
1552 VALGRIND_GET_ORIG_FN(fn);
bart63eb9892014-03-19 18:48:01 +00001553 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_DESTROY,
1554 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001555 CALL_FN_W_W(ret, fn, rwlock);
sewardj4b3a7422011-10-24 13:21:57 +00001556 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_DESTROY,
bart575ce8e2011-05-15 07:04:03 +00001557 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001558 return ret;
bart00344642008-03-01 15:27:41 +00001559}
1560
sewardj8eb8bab2015-07-21 14:44:28 +00001561#if defined(VGO_solaris)
1562/* On Solaris, pthread_rwlock_destroy is a weak alias to rwlock_destroy. */
1563PTH_FUNCS(int,
1564 rwlockZudestroy, pthread_rwlock_destroy_intercept,
1565 (pthread_rwlock_t *rwlock), (rwlock));
1566#else
bart791a0c62009-07-31 17:31:44 +00001567PTH_FUNCS(int,
1568 pthreadZurwlockZudestroy, pthread_rwlock_destroy_intercept,
1569 (pthread_rwlock_t* rwlock), (rwlock));
sewardj8eb8bab2015-07-21 14:44:28 +00001570#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +00001571
bartb2260b82011-02-13 07:55:36 +00001572static __always_inline
bart791a0c62009-07-31 17:31:44 +00001573int pthread_rwlock_rdlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001574{
bartbedfd232009-03-26 19:07:15 +00001575 int ret;
bartbedfd232009-03-26 19:07:15 +00001576 OrigFn fn;
1577 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001578 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_RDLOCK,
bart575ce8e2011-05-15 07:04:03 +00001579 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001580 CALL_FN_W_W(ret, fn, rwlock);
sewardj4b3a7422011-10-24 13:21:57 +00001581 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_RDLOCK,
bart575ce8e2011-05-15 07:04:03 +00001582 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001583 return ret;
bart00344642008-03-01 15:27:41 +00001584}
1585
sewardj8eb8bab2015-07-21 14:44:28 +00001586#if defined(VGO_solaris)
1587/* On Solaris, pthread_rwlock_rdlock is a weak alias to rw_rdlock. */
1588PTH_FUNCS(int,
1589 rwZurdlock, pthread_rwlock_rdlock_intercept,
1590 (pthread_rwlock_t *rwlock), (rwlock));
1591#else
bart791a0c62009-07-31 17:31:44 +00001592PTH_FUNCS(int,
1593 pthreadZurwlockZurdlock, pthread_rwlock_rdlock_intercept,
1594 (pthread_rwlock_t* rwlock), (rwlock));
sewardj8eb8bab2015-07-21 14:44:28 +00001595#endif /* VGO_solaris */
1596
1597#if defined(VGO_solaris)
1598/* Internal to libc. */
1599static __always_inline
1600void lrw_rdlock_intercept(rwlock_t *rwlock)
1601{
1602 OrigFn fn;
1603 VALGRIND_GET_ORIG_FN(fn);
1604 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_RDLOCK,
1605 rwlock, 0, 0, 0, 0);
1606 CALL_FN_v_W(fn, rwlock);
1607 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_RDLOCK,
1608 rwlock, True /* took_lock */, 0, 0, 0);
1609}
1610
1611PTH_FUNCS(void, lrwZurdlock, lrw_rdlock_intercept,
1612 (rwlock_t *rwlock), (rwlock));
1613#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +00001614
bartb2260b82011-02-13 07:55:36 +00001615static __always_inline
bart791a0c62009-07-31 17:31:44 +00001616int pthread_rwlock_wrlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001617{
bartbedfd232009-03-26 19:07:15 +00001618 int ret;
bartbedfd232009-03-26 19:07:15 +00001619 OrigFn fn;
1620 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001621 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_WRLOCK,
bart575ce8e2011-05-15 07:04:03 +00001622 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001623 CALL_FN_W_W(ret, fn, rwlock);
sewardj4b3a7422011-10-24 13:21:57 +00001624 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_WRLOCK,
bart575ce8e2011-05-15 07:04:03 +00001625 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001626 return ret;
bart00344642008-03-01 15:27:41 +00001627}
1628
sewardj8eb8bab2015-07-21 14:44:28 +00001629#if defined(VGO_solaris)
1630/* On Solaris, pthread_rwlock_wrlock is a weak alias to rw_wrlock. */
1631PTH_FUNCS(int,
1632 rwZuwrlock, pthread_rwlock_wrlock_intercept,
1633 (pthread_rwlock_t *rwlock), (rwlock));
1634#else
bart791a0c62009-07-31 17:31:44 +00001635PTH_FUNCS(int,
1636 pthreadZurwlockZuwrlock, pthread_rwlock_wrlock_intercept,
1637 (pthread_rwlock_t* rwlock), (rwlock));
sewardj8eb8bab2015-07-21 14:44:28 +00001638#endif /* VGO_solaris */
1639
1640#if defined(VGO_solaris)
1641/* Internal to libc. */
1642static __always_inline
1643void lrw_wrlock_intercept(rwlock_t *rwlock)
1644{
1645 OrigFn fn;
1646 VALGRIND_GET_ORIG_FN(fn);
1647 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_WRLOCK,
1648 rwlock, 0, 0, 0, 0);
1649 CALL_FN_v_W(fn, rwlock);
1650 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_WRLOCK,
1651 rwlock, True /* took_lock */, 0, 0, 0);
1652}
1653
1654PTH_FUNCS(void, lrwZuwrlock, lrw_wrlock_intercept,
1655 (rwlock_t *rwlock), (rwlock));
1656#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +00001657
bartb2260b82011-02-13 07:55:36 +00001658static __always_inline
bart4ad5efc2014-03-18 17:53:56 +00001659int pthread_rwlock_timedrdlock_intercept(pthread_rwlock_t* rwlock,
1660 const struct timespec *timeout)
bart00344642008-03-01 15:27:41 +00001661{
bartbedfd232009-03-26 19:07:15 +00001662 int ret;
bartbedfd232009-03-26 19:07:15 +00001663 OrigFn fn;
1664 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001665 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_RDLOCK,
bart575ce8e2011-05-15 07:04:03 +00001666 rwlock, 0, 0, 0, 0);
bart4ad5efc2014-03-18 17:53:56 +00001667 CALL_FN_W_WW(ret, fn, rwlock, timeout);
sewardj4b3a7422011-10-24 13:21:57 +00001668 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_RDLOCK,
bart575ce8e2011-05-15 07:04:03 +00001669 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001670 return ret;
bart00344642008-03-01 15:27:41 +00001671}
1672
bart791a0c62009-07-31 17:31:44 +00001673PTH_FUNCS(int,
1674 pthreadZurwlockZutimedrdlock, pthread_rwlock_timedrdlock_intercept,
bart4ad5efc2014-03-18 17:53:56 +00001675 (pthread_rwlock_t* rwlock, const struct timespec *timeout),
1676 (rwlock, timeout));
sewardj8eb8bab2015-07-21 14:44:28 +00001677#if defined(VGO_solaris)
1678PTH_FUNCS(int, pthreadZurwlockZureltimedrdlockZunp,
1679 pthread_rwlock_timedrdlock_intercept,
1680 (pthread_rwlock_t *rwlock, const struct timespec *timeout),
1681 (rwlock, timeout));
1682#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +00001683
bartb2260b82011-02-13 07:55:36 +00001684static __always_inline
bart4ad5efc2014-03-18 17:53:56 +00001685int pthread_rwlock_timedwrlock_intercept(pthread_rwlock_t* rwlock,
1686 const struct timespec *timeout)
bart00344642008-03-01 15:27:41 +00001687{
bartbedfd232009-03-26 19:07:15 +00001688 int ret;
bartbedfd232009-03-26 19:07:15 +00001689 OrigFn fn;
1690 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001691 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_WRLOCK,
bart575ce8e2011-05-15 07:04:03 +00001692 rwlock, 0, 0, 0, 0);
bart4ad5efc2014-03-18 17:53:56 +00001693 CALL_FN_W_WW(ret, fn, rwlock, timeout);
sewardj4b3a7422011-10-24 13:21:57 +00001694 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_WRLOCK,
bart575ce8e2011-05-15 07:04:03 +00001695 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001696 return ret;
bart00344642008-03-01 15:27:41 +00001697}
1698
bart791a0c62009-07-31 17:31:44 +00001699PTH_FUNCS(int,
1700 pthreadZurwlockZutimedwrlock, pthread_rwlock_timedwrlock_intercept,
bart4ad5efc2014-03-18 17:53:56 +00001701 (pthread_rwlock_t* rwlock, const struct timespec *timeout),
1702 (rwlock, timeout));
sewardj8eb8bab2015-07-21 14:44:28 +00001703#if defined(VGO_solaris)
1704PTH_FUNCS(int, pthreadZurwlockZureltimedwrlockZunp,
1705 pthread_rwlock_timedwrlock_intercept,
1706 (pthread_rwlock_t *rwlock, const struct timespec *timeout),
1707 (rwlock, timeout));
1708#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +00001709
bartb2260b82011-02-13 07:55:36 +00001710static __always_inline
bart791a0c62009-07-31 17:31:44 +00001711int pthread_rwlock_tryrdlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001712{
bartbedfd232009-03-26 19:07:15 +00001713 int ret;
bartbedfd232009-03-26 19:07:15 +00001714 OrigFn fn;
1715 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001716 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_RDLOCK,
bart575ce8e2011-05-15 07:04:03 +00001717 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001718 CALL_FN_W_W(ret, fn, rwlock);
sewardj4b3a7422011-10-24 13:21:57 +00001719 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_RDLOCK,
bart575ce8e2011-05-15 07:04:03 +00001720 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001721 return ret;
bart00344642008-03-01 15:27:41 +00001722}
1723
sewardj8eb8bab2015-07-21 14:44:28 +00001724#if defined(VGO_solaris)
1725/* On Solaris, pthread_rwlock_tryrdlock is a weak alias to rw_tryrdlock. */
1726PTH_FUNCS(int,
1727 rwZutryrdlock, pthread_rwlock_tryrdlock_intercept,
1728 (pthread_rwlock_t *rwlock), (rwlock));
1729#else
bart791a0c62009-07-31 17:31:44 +00001730PTH_FUNCS(int,
1731 pthreadZurwlockZutryrdlock, pthread_rwlock_tryrdlock_intercept,
1732 (pthread_rwlock_t* rwlock), (rwlock));
sewardj8eb8bab2015-07-21 14:44:28 +00001733#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +00001734
bartb2260b82011-02-13 07:55:36 +00001735static __always_inline
bart791a0c62009-07-31 17:31:44 +00001736int pthread_rwlock_trywrlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001737{
bartbedfd232009-03-26 19:07:15 +00001738 int ret;
bartbedfd232009-03-26 19:07:15 +00001739 OrigFn fn;
1740 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001741 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_WRLOCK,
bart575ce8e2011-05-15 07:04:03 +00001742 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001743 CALL_FN_W_W(ret, fn, rwlock);
sewardj4b3a7422011-10-24 13:21:57 +00001744 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_WRLOCK,
bart575ce8e2011-05-15 07:04:03 +00001745 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001746 return ret;
bart00344642008-03-01 15:27:41 +00001747}
1748
sewardj8eb8bab2015-07-21 14:44:28 +00001749#if defined(VGO_solaris)
1750/* On Solaris, pthread_rwlock_trywrlock is a weak alias to rw_trywrlock. */
1751PTH_FUNCS(int,
1752 rwZutrywrlock, pthread_rwlock_trywrlock_intercept,
1753 (pthread_rwlock_t *rwlock), (rwlock));
1754#else
bart791a0c62009-07-31 17:31:44 +00001755PTH_FUNCS(int,
1756 pthreadZurwlockZutrywrlock, pthread_rwlock_trywrlock_intercept,
1757 (pthread_rwlock_t* rwlock), (rwlock));
sewardj8eb8bab2015-07-21 14:44:28 +00001758#endif /* VGO_solaris */
bart791a0c62009-07-31 17:31:44 +00001759
bartb2260b82011-02-13 07:55:36 +00001760static __always_inline
bart791a0c62009-07-31 17:31:44 +00001761int pthread_rwlock_unlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001762{
bartbedfd232009-03-26 19:07:15 +00001763 int ret;
bartbedfd232009-03-26 19:07:15 +00001764 OrigFn fn;
1765 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001766 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_UNLOCK,
bart575ce8e2011-05-15 07:04:03 +00001767 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001768 CALL_FN_W_W(ret, fn, rwlock);
sewardj4b3a7422011-10-24 13:21:57 +00001769 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_UNLOCK,
bart575ce8e2011-05-15 07:04:03 +00001770 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001771 return ret;
bart00344642008-03-01 15:27:41 +00001772}
bart791a0c62009-07-31 17:31:44 +00001773
sewardj8eb8bab2015-07-21 14:44:28 +00001774#if defined(VGO_solaris)
1775/* On Solaris, pthread_rwlock_unlock is a weak alias to rw_unlock. */
1776PTH_FUNCS(int,
1777 rwZuunlock, pthread_rwlock_unlock_intercept,
1778 (pthread_rwlock_t *rwlock), (rwlock));
1779#else
bart791a0c62009-07-31 17:31:44 +00001780PTH_FUNCS(int,
1781 pthreadZurwlockZuunlock, pthread_rwlock_unlock_intercept,
1782 (pthread_rwlock_t* rwlock), (rwlock));
sewardj8eb8bab2015-07-21 14:44:28 +00001783#endif /* VGO_solaris */
sewardj0c09bf02011-07-11 22:11:58 +00001784
1785#endif /* defined(HAVE_PTHREAD_RWLOCK_T) */