blob: f883f7c3da8887359ebcc6d61fc11d166664da2e [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
sewardj03f8d3f2012-08-05 15:46:46 +00008 Copyright (C) 2006-2012 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. */
58#ifdef HAVE_USABLE_LINUX_FUTEX_H
bart651f56b2011-07-26 19:30:28 +000059#include <asm/unistd.h> /* __NR_futex */
60#include <linux/futex.h> /* FUTEX_WAIT */
bartd1a5cd62011-07-28 15:04:08 +000061#ifndef FUTEX_PRIVATE_FLAG
62#define FUTEX_PRIVATE_FLAG 0
63#endif
bart651f56b2011-07-26 19:30:28 +000064#endif
bart227c6592009-02-14 12:12:57 +000065#include "drd_basics.h" /* DRD_() */
sewardjaf44c822007-11-25 14:01:38 +000066#include "drd_clientreq.h"
bart227c6592009-02-14 12:12:57 +000067#include "pub_tool_redir.h" /* VG_WRAP_FUNCTION_ZZ() */
sewardjaf44c822007-11-25 14:01:38 +000068
69
barta0b72222009-03-12 18:39:31 +000070/*
bart82397422011-03-08 17:53:45 +000071 * 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.
barta0b72222009-03-12 18:39:31 +000081 */
barta0b72222009-03-12 18:39:31 +000082
bart791a0c62009-07-31 17:31:44 +000083/**
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.
90 */
bart377d23f2011-03-05 14:51:24 +000091#ifdef VGO_darwin
92static 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; \
103 }
104#else
bart791a0c62009-07-31 17:31:44 +0000105#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; }
bart377d23f2011-03-05 14:51:24 +0000109#endif
sewardjaf44c822007-11-25 14:01:38 +0000110
bart791a0c62009-07-31 17:31:44 +0000111/**
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.
117 */
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);
122
123/*
bartb2260b82011-02-13 07:55:36 +0000124 * 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.
bart791a0c62009-07-31 17:31:44 +0000128 */
129#undef __always_inline /* since already defined in <cdefs.h> */
bart4f66a772009-07-31 17:59:28 +0000130#if __GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 2
bart791a0c62009-07-31 17:31:44 +0000131#define __always_inline __inline__ __attribute__((always_inline))
132#else
133#define __always_inline __inline__
134#endif
sewardjaf44c822007-11-25 14:01:38 +0000135
bart6f07b252008-04-04 16:45:20 +0000136/* Local data structures. */
sewardjaf44c822007-11-25 14:01:38 +0000137
bart651f56b2011-07-26 19:30:28 +0000138typedef struct {
barte5286972012-01-19 19:52:15 +0000139 pthread_mutex_t mutex;
140 int counter;
bartce1d6882012-01-23 17:01:58 +0000141 int waiters;
bart651f56b2011-07-26 19:30:28 +0000142} DrdSema;
143
sewardjaf44c822007-11-25 14:01:38 +0000144typedef struct
145{
bartbedfd232009-03-26 19:07:15 +0000146 void* (*start)(void*);
147 void* arg;
148 int detachstate;
barte57a9e22012-01-24 08:30:32 +0000149 DrdSema* wrapper_started;
barta764b372009-02-15 10:40:44 +0000150} DrdPosixThreadArgs;
sewardjaf44c822007-11-25 14:01:38 +0000151
152
bart227c6592009-02-14 12:12:57 +0000153/* Local function declarations. */
sewardjaf44c822007-11-25 14:01:38 +0000154
bart227c6592009-02-14 12:12:57 +0000155static void DRD_(init)(void) __attribute__((constructor));
156static void DRD_(check_threading_library)(void);
157static void DRD_(set_main_thread_state)(void);
bart651f56b2011-07-26 19:30:28 +0000158static void DRD_(sema_init)(DrdSema* sema);
159static void DRD_(sema_destroy)(DrdSema* sema);
160static void DRD_(sema_down)(DrdSema* sema);
161static void DRD_(sema_up)(DrdSema* sema);
sewardjaf44c822007-11-25 14:01:38 +0000162
163
bart6f07b252008-04-04 16:45:20 +0000164/* Function definitions. */
165
bart227c6592009-02-14 12:12:57 +0000166/**
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.
bart6f07b252008-04-04 16:45:20 +0000175 */
bart227c6592009-02-14 12:12:57 +0000176static void DRD_(init)(void)
bart6f07b252008-04-04 16:45:20 +0000177{
bartbedfd232009-03-26 19:07:15 +0000178 DRD_(check_threading_library)();
179 DRD_(set_main_thread_state)();
bart6f07b252008-04-04 16:45:20 +0000180}
sewardjaf44c822007-11-25 14:01:38 +0000181
bart651f56b2011-07-26 19:30:28 +0000182static void DRD_(sema_init)(DrdSema* sema)
183{
184 DRD_IGNORE_VAR(sema->counter);
barte5286972012-01-19 19:52:15 +0000185 pthread_mutex_init(&sema->mutex, NULL);
bart651f56b2011-07-26 19:30:28 +0000186 sema->counter = 0;
bartce1d6882012-01-23 17:01:58 +0000187 sema->waiters = 0;
bart651f56b2011-07-26 19:30:28 +0000188}
189
190static void DRD_(sema_destroy)(DrdSema* sema)
191{
barte5286972012-01-19 19:52:15 +0000192 pthread_mutex_destroy(&sema->mutex);
bart651f56b2011-07-26 19:30:28 +0000193}
194
195static void DRD_(sema_down)(DrdSema* sema)
196{
bartd1a5cd62011-07-28 15:04:08 +0000197 int res = ENOSYS;
198
barte5286972012-01-19 19:52:15 +0000199 pthread_mutex_lock(&sema->mutex);
bartce1d6882012-01-23 17:01:58 +0000200 if (sema->counter == 0) {
201 sema->waiters++;
202 while (sema->counter == 0) {
203 pthread_mutex_unlock(&sema->mutex);
bart818f17e2011-09-17 06:24:49 +0000204#ifdef HAVE_USABLE_LINUX_FUTEX_H
bartce1d6882012-01-23 17:01:58 +0000205 if (syscall(__NR_futex, (UWord)&sema->counter,
206 FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0) == 0)
207 res = 0;
208 else
209 res = errno;
bart651f56b2011-07-26 19:30:28 +0000210#endif
bartce1d6882012-01-23 17:01:58 +0000211 /*
212 * Invoke sched_yield() on non-Linux systems, if the futex syscall has
213 * not been invoked or if this code has been built on a Linux system
214 * where __NR_futex is defined and is run on a Linux system that does
215 * not support the futex syscall.
216 */
217 if (res != 0 && res != EWOULDBLOCK)
218 sched_yield();
219 pthread_mutex_lock(&sema->mutex);
220 }
221 sema->waiters--;
bart651f56b2011-07-26 19:30:28 +0000222 }
223 sema->counter--;
barte5286972012-01-19 19:52:15 +0000224 pthread_mutex_unlock(&sema->mutex);
bart651f56b2011-07-26 19:30:28 +0000225}
226
227static void DRD_(sema_up)(DrdSema* sema)
228{
barte5286972012-01-19 19:52:15 +0000229 pthread_mutex_lock(&sema->mutex);
bart651f56b2011-07-26 19:30:28 +0000230 sema->counter++;
bart818f17e2011-09-17 06:24:49 +0000231#ifdef HAVE_USABLE_LINUX_FUTEX_H
bartce1d6882012-01-23 17:01:58 +0000232 if (sema->waiters > 0)
233 syscall(__NR_futex, (UWord)&sema->counter,
234 FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1);
bart651f56b2011-07-26 19:30:28 +0000235#endif
barte5286972012-01-19 19:52:15 +0000236 pthread_mutex_unlock(&sema->mutex);
bart651f56b2011-07-26 19:30:28 +0000237}
238
bart227c6592009-02-14 12:12:57 +0000239/**
240 * POSIX threads and DRD each have their own mutex type identification.
241 * Convert POSIX threads' mutex type to DRD's mutex type. In the code below
242 * if-statements are used to test the value of 'kind' instead of a switch
243 * statement because some of the PTHREAD_MUTEX_ macro's may have the same
244 * value.
245 */
246static MutexT DRD_(pthread_to_drd_mutex_type)(const int kind)
bart5357fcb2008-02-27 15:46:00 +0000247{
bartbedfd232009-03-26 19:07:15 +0000248 if (kind == PTHREAD_MUTEX_RECURSIVE)
249 return mutex_type_recursive_mutex;
250 else if (kind == PTHREAD_MUTEX_ERRORCHECK)
251 return mutex_type_errorcheck_mutex;
252 else if (kind == PTHREAD_MUTEX_NORMAL)
253 return mutex_type_default_mutex;
254 else if (kind == PTHREAD_MUTEX_DEFAULT)
255 return mutex_type_default_mutex;
bart227c6592009-02-14 12:12:57 +0000256#if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP)
bartbedfd232009-03-26 19:07:15 +0000257 else if (kind == PTHREAD_MUTEX_ADAPTIVE_NP)
258 return mutex_type_default_mutex;
bart227c6592009-02-14 12:12:57 +0000259#endif
bartbedfd232009-03-26 19:07:15 +0000260 else
261 {
262 return mutex_type_invalid_mutex;
263 }
bart5357fcb2008-02-27 15:46:00 +0000264}
265
bart33f76c12010-09-19 11:14:31 +0000266#define IS_ALIGNED(p) (((uintptr_t)(p) & (sizeof(*(p)) - 1)) == 0)
267
bart227c6592009-02-14 12:12:57 +0000268/**
269 * Read the mutex type stored in the client memory used for the mutex
270 * implementation.
271 *
272 * @note This function depends on the implementation of the POSIX threads
273 * library -- the POSIX standard does not define the name of the member in
274 * which the mutex type is stored.
275 * @note The function mutex_type() has been declared inline in order
276 * to avoid that it shows up in call stacks (drd/tests/...exp* files).
bart489de212009-03-13 17:32:52 +0000277 * @note glibc stores the mutex type in the lowest two bits, and uses the
278 * higher bits for flags like PTHREAD_MUTEXATTR_FLAG_ROBUST and
279 * PTHREAD_MUTEXATTR_FLAG_PSHARED.
bart2bc9c102008-09-27 12:40:57 +0000280 */
bart791a0c62009-07-31 17:31:44 +0000281static __always_inline MutexT DRD_(mutex_type)(pthread_mutex_t* mutex)
bart5357fcb2008-02-27 15:46:00 +0000282{
bart5e389f12008-04-05 12:53:15 +0000283#if defined(HAVE_PTHREAD_MUTEX_T__M_KIND)
bartbedfd232009-03-26 19:07:15 +0000284 /* glibc + LinuxThreads. */
bart33f76c12010-09-19 11:14:31 +0000285 if (IS_ALIGNED(&mutex->__m_kind))
286 {
287 const int kind = mutex->__m_kind & 3;
288 return DRD_(pthread_to_drd_mutex_type)(kind);
289 }
bart5e389f12008-04-05 12:53:15 +0000290#elif defined(HAVE_PTHREAD_MUTEX_T__DATA__KIND)
bartbedfd232009-03-26 19:07:15 +0000291 /* glibc + NPTL. */
bart33f76c12010-09-19 11:14:31 +0000292 if (IS_ALIGNED(&mutex->__data.__kind))
293 {
294 const int kind = mutex->__data.__kind & 3;
295 return DRD_(pthread_to_drd_mutex_type)(kind);
296 }
bartadb7a202009-07-21 12:39:25 +0000297#else
298 /*
299 * Another POSIX threads implementation. The mutex type won't be printed
300 * when enabling --trace-mutex=yes.
301 */
bartadb7a202009-07-21 12:39:25 +0000302#endif
bart33f76c12010-09-19 11:14:31 +0000303 return mutex_type_unknown;
bart5357fcb2008-02-27 15:46:00 +0000304}
305
bart227c6592009-02-14 12:12:57 +0000306/**
307 * Tell DRD whether 'tid' is a joinable thread or a detached thread.
308 */
309static void DRD_(set_joinable)(const pthread_t tid, const int joinable)
sewardjaf44c822007-11-25 14:01:38 +0000310{
bartbedfd232009-03-26 19:07:15 +0000311 assert(joinable == 0 || joinable == 1);
sewardj4b3a7422011-10-24 13:21:57 +0000312 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__SET_JOINABLE,
bart575ce8e2011-05-15 07:04:03 +0000313 tid, joinable, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000314}
315
bartdd75cdf2009-07-24 08:20:10 +0000316/** Tell DRD that the calling thread is about to enter pthread_create(). */
bart791a0c62009-07-31 17:31:44 +0000317static __always_inline void DRD_(entering_pthread_create)(void)
bartdd75cdf2009-07-24 08:20:10 +0000318{
sewardj4b3a7422011-10-24 13:21:57 +0000319 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__ENTERING_PTHREAD_CREATE,
bart575ce8e2011-05-15 07:04:03 +0000320 0, 0, 0, 0, 0);
bartdd75cdf2009-07-24 08:20:10 +0000321}
322
323/** Tell DRD that the calling thread has left pthread_create(). */
bart791a0c62009-07-31 17:31:44 +0000324static __always_inline void DRD_(left_pthread_create)(void)
bartdd75cdf2009-07-24 08:20:10 +0000325{
sewardj4b3a7422011-10-24 13:21:57 +0000326 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LEFT_PTHREAD_CREATE,
bart575ce8e2011-05-15 07:04:03 +0000327 0, 0, 0, 0, 0);
bartdd75cdf2009-07-24 08:20:10 +0000328}
329
bart227c6592009-02-14 12:12:57 +0000330/**
bartdd75cdf2009-07-24 08:20:10 +0000331 * Entry point for newly created threads. This function is called from the
332 * thread created by pthread_create().
bart227c6592009-02-14 12:12:57 +0000333 */
bart292c1e22009-02-14 11:54:42 +0000334static void* DRD_(thread_wrapper)(void* arg)
sewardjaf44c822007-11-25 14:01:38 +0000335{
bartbedfd232009-03-26 19:07:15 +0000336 DrdPosixThreadArgs* arg_ptr;
337 DrdPosixThreadArgs arg_copy;
bart0d063002008-03-01 07:25:13 +0000338
bartbedfd232009-03-26 19:07:15 +0000339 arg_ptr = (DrdPosixThreadArgs*)arg;
340 arg_copy = *arg_ptr;
sewardjaf44c822007-11-25 14:01:38 +0000341
sewardj4b3a7422011-10-24 13:21:57 +0000342 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__SET_PTHREADID,
bart575ce8e2011-05-15 07:04:03 +0000343 pthread_self(), 0, 0, 0, 0);
bart227c6592009-02-14 12:12:57 +0000344
bartbedfd232009-03-26 19:07:15 +0000345 DRD_(set_joinable)(pthread_self(),
346 arg_copy.detachstate == PTHREAD_CREATE_JOINABLE);
bart227c6592009-02-14 12:12:57 +0000347
bart8244b862011-03-08 18:34:44 +0000348 /*
349 * Only set 'wrapper_started' after VG_USERREQ__SET_PTHREADID and
350 * DRD_(set_joinable)() have been invoked to avoid a race with
351 * a pthread_detach() invocation for this thread from another thread.
352 */
barte57a9e22012-01-24 08:30:32 +0000353 DRD_(sema_up)(arg_copy.wrapper_started);
bart8244b862011-03-08 18:34:44 +0000354
bartbedfd232009-03-26 19:07:15 +0000355 return (arg_copy.start)(arg_copy.arg);
sewardjaf44c822007-11-25 14:01:38 +0000356}
357
bart227c6592009-02-14 12:12:57 +0000358/**
bartd2c5eae2009-02-21 15:27:04 +0000359 * Return 1 if the LinuxThreads implementation of POSIX Threads has been
360 * detected, and 0 otherwise.
361 *
362 * @see For more information about the confstr() function, see also
bart227c6592009-02-14 12:12:57 +0000363 * http://www.opengroup.org/onlinepubs/009695399/functions/confstr.html
364 */
365static int DRD_(detected_linuxthreads)(void)
bart4501d5c2008-03-04 18:36:23 +0000366{
367#if defined(linux)
368#if defined(_CS_GNU_LIBPTHREAD_VERSION)
bartbedfd232009-03-26 19:07:15 +0000369 /* Linux with a recent glibc. */
370 char buffer[256];
371 unsigned len;
372 len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
373 assert(len <= sizeof(buffer));
374 return len > 0 && buffer[0] == 'l';
bart4501d5c2008-03-04 18:36:23 +0000375#else
bartbedfd232009-03-26 19:07:15 +0000376 /* Linux without _CS_GNU_LIBPTHREAD_VERSION: most likely LinuxThreads. */
377 return 1;
bart4501d5c2008-03-04 18:36:23 +0000378#endif
379#else
bartbedfd232009-03-26 19:07:15 +0000380 /* Another OS than Linux, hence no LinuxThreads. */
381 return 0;
bart4501d5c2008-03-04 18:36:23 +0000382#endif
383}
384
bart227c6592009-02-14 12:12:57 +0000385/**
386 * Stop and print an error message in case a non-supported threading
387 * library implementation (LinuxThreads) has been detected.
bart6f07b252008-04-04 16:45:20 +0000388 */
bart227c6592009-02-14 12:12:57 +0000389static void DRD_(check_threading_library)(void)
sewardjaf44c822007-11-25 14:01:38 +0000390{
bartbedfd232009-03-26 19:07:15 +0000391 if (DRD_(detected_linuxthreads)())
392 {
393 if (getenv("LD_ASSUME_KERNEL"))
394 {
395 fprintf(stderr,
bart227c6592009-02-14 12:12:57 +0000396"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
397"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
398"after having unset the environment variable LD_ASSUME_KERNEL. Giving up.\n"
bartbedfd232009-03-26 19:07:15 +0000399);
400 }
401 else
402 {
403 fprintf(stderr,
bart227c6592009-02-14 12:12:57 +0000404"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
405"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
406"after having upgraded to a newer version of your Linux distribution.\n"
407"Giving up.\n"
bartbedfd232009-03-26 19:07:15 +0000408);
409 }
410 abort();
411 }
bart6f07b252008-04-04 16:45:20 +0000412}
413
bart227c6592009-02-14 12:12:57 +0000414/**
415 * The main thread is the only thread not created by pthread_create().
416 * Update DRD's state information about the main thread.
417 */
418static void DRD_(set_main_thread_state)(void)
bart6f07b252008-04-04 16:45:20 +0000419{
bartbedfd232009-03-26 19:07:15 +0000420 // Make sure that DRD knows about the main thread's POSIX thread ID.
sewardj4b3a7422011-10-24 13:21:57 +0000421 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__SET_PTHREADID,
bart575ce8e2011-05-15 07:04:03 +0000422 pthread_self(), 0, 0, 0, 0);
bart850f1992010-05-29 18:43:21 +0000423}
sewardjaf44c822007-11-25 14:01:38 +0000424
bartc39d1092009-04-22 18:59:50 +0000425/*
bartdd75cdf2009-07-24 08:20:10 +0000426 * Note: as of today there exist three different versions of pthread_create
427 * in Linux:
bartc39d1092009-04-22 18:59:50 +0000428 * - pthread_create@GLIBC_2.0
429 * - pthread_create@@GLIBC_2.1
430 * - pthread_create@@GLIBC_2.2.5
431 * As an example, in libpthread-2.3.4 both pthread_create@GLIBC_2.0 and
432 * pthread_create@@GLIBC_2.1 are defined, while in libpthread-2.9 all three
433 * versions have been implemented. In any glibc version where more than one
434 * pthread_create function has been implemented, older versions call the
435 * newer versions. Or: the pthread_create* wrapper defined below can be
436 * called recursively. Any code in this wrapper should take this in account.
437 * As an example, it is not safe to invoke the DRD_STOP_RECORDING
438 * / DRD_START_RECORDING client requests from the pthread_create wrapper.
439 * See also the implementation of pthread_create@GLIBC_2.0 in
440 * glibc-2.9/nptl/pthread_create.c.
441 */
442
bartb2260b82011-02-13 07:55:36 +0000443static __always_inline
bart791a0c62009-07-31 17:31:44 +0000444int pthread_create_intercept(pthread_t* thread, const pthread_attr_t* attr,
445 void* (*start)(void*), void* arg)
sewardjaf44c822007-11-25 14:01:38 +0000446{
bartbedfd232009-03-26 19:07:15 +0000447 int ret;
448 OrigFn fn;
barte57a9e22012-01-24 08:30:32 +0000449 DrdSema wrapper_started;
bartbedfd232009-03-26 19:07:15 +0000450 DrdPosixThreadArgs thread_args;
sewardjaf44c822007-11-25 14:01:38 +0000451
bartbedfd232009-03-26 19:07:15 +0000452 VALGRIND_GET_ORIG_FN(fn);
sewardjaf44c822007-11-25 14:01:38 +0000453
barte57a9e22012-01-24 08:30:32 +0000454 DRD_(sema_init)(&wrapper_started);
bartb957ab82011-03-12 11:01:06 +0000455 thread_args.start = start;
456 thread_args.arg = arg;
barte57a9e22012-01-24 08:30:32 +0000457 thread_args.wrapper_started = &wrapper_started;
bartbedfd232009-03-26 19:07:15 +0000458 /*
459 * Find out whether the thread will be started as a joinable thread
460 * or as a detached thread. If no thread attributes have been specified,
461 * this means that the new thread will be started as a joinable thread.
462 */
bartb957ab82011-03-12 11:01:06 +0000463 thread_args.detachstate = PTHREAD_CREATE_JOINABLE;
bartbedfd232009-03-26 19:07:15 +0000464 if (attr)
465 {
bartb957ab82011-03-12 11:01:06 +0000466 if (pthread_attr_getdetachstate(attr, &thread_args.detachstate) != 0)
bartbedfd232009-03-26 19:07:15 +0000467 assert(0);
bartbedfd232009-03-26 19:07:15 +0000468 }
bartb957ab82011-03-12 11:01:06 +0000469 assert(thread_args.detachstate == PTHREAD_CREATE_JOINABLE
470 || thread_args.detachstate == PTHREAD_CREATE_DETACHED);
bartdd75cdf2009-07-24 08:20:10 +0000471
472 DRD_(entering_pthread_create)();
bartb957ab82011-03-12 11:01:06 +0000473 CALL_FN_W_WWWW(ret, fn, thread, attr, DRD_(thread_wrapper), &thread_args);
bartdd75cdf2009-07-24 08:20:10 +0000474 DRD_(left_pthread_create)();
bart227c6592009-02-14 12:12:57 +0000475
barte57a9e22012-01-24 08:30:32 +0000476 if (ret == 0) {
barte476e922011-03-08 18:32:36 +0000477 /* Wait until the thread wrapper started. */
barte57a9e22012-01-24 08:30:32 +0000478 DRD_(sema_down)(&wrapper_started);
bartbedfd232009-03-26 19:07:15 +0000479 }
bart227c6592009-02-14 12:12:57 +0000480
barte57a9e22012-01-24 08:30:32 +0000481 DRD_(sema_destroy)(&wrapper_started);
bart651f56b2011-07-26 19:30:28 +0000482
sewardj4b3a7422011-10-24 13:21:57 +0000483 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_START_NEW_SEGMENT,
bart575ce8e2011-05-15 07:04:03 +0000484 pthread_self(), 0, 0, 0, 0);
barta0b72222009-03-12 18:39:31 +0000485
bartbedfd232009-03-26 19:07:15 +0000486 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000487}
488
bart791a0c62009-07-31 17:31:44 +0000489PTH_FUNCS(int, pthreadZucreate, pthread_create_intercept,
490 (pthread_t *thread, const pthread_attr_t *attr,
491 void *(*start) (void *), void *arg),
492 (thread, attr, start, arg));
493
bartb2260b82011-02-13 07:55:36 +0000494static __always_inline
bart791a0c62009-07-31 17:31:44 +0000495int pthread_join_intercept(pthread_t pt_joinee, void **thread_return)
sewardjaf44c822007-11-25 14:01:38 +0000496{
bartbedfd232009-03-26 19:07:15 +0000497 int ret;
bartbedfd232009-03-26 19:07:15 +0000498 OrigFn fn;
sewardjaf44c822007-11-25 14:01:38 +0000499
bartbedfd232009-03-26 19:07:15 +0000500 VALGRIND_GET_ORIG_FN(fn);
bart5cbd26e2011-08-24 15:02:21 +0000501 /*
502 * Avoid that the sys_futex(td->tid) call invoked by the NPTL pthread_join()
503 * implementation triggers a (false positive) race report.
504 */
505 ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
bartbedfd232009-03-26 19:07:15 +0000506 CALL_FN_W_WW(ret, fn, pt_joinee, thread_return);
507 if (ret == 0)
508 {
sewardj4b3a7422011-10-24 13:21:57 +0000509 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_THREAD_JOIN,
bart575ce8e2011-05-15 07:04:03 +0000510 pt_joinee, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000511 }
bart5cbd26e2011-08-24 15:02:21 +0000512 ANNOTATE_IGNORE_READS_AND_WRITES_END();
bartbedfd232009-03-26 19:07:15 +0000513 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000514}
515
bart791a0c62009-07-31 17:31:44 +0000516PTH_FUNCS(int, pthreadZujoin, pthread_join_intercept,
517 (pthread_t pt_joinee, void **thread_return),
518 (pt_joinee, thread_return));
519
bartb2260b82011-02-13 07:55:36 +0000520static __always_inline
bart791a0c62009-07-31 17:31:44 +0000521int pthread_detach_intercept(pthread_t pt_thread)
sewardjaf44c822007-11-25 14:01:38 +0000522{
bartbedfd232009-03-26 19:07:15 +0000523 int ret;
524 OrigFn fn;
bart5668d4e2011-03-09 17:53:28 +0000525
bartbedfd232009-03-26 19:07:15 +0000526 VALGRIND_GET_ORIG_FN(fn);
bart5668d4e2011-03-09 17:53:28 +0000527 CALL_FN_W_W(ret, fn, pt_thread);
528 DRD_(set_joinable)(pt_thread, 0);
529
bartbedfd232009-03-26 19:07:15 +0000530 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000531}
532
bart791a0c62009-07-31 17:31:44 +0000533PTH_FUNCS(int, pthreadZudetach, pthread_detach_intercept,
534 (pthread_t thread), (thread));
535
536// NOTE: be careful to intercept only pthread_cancel() and not
537// pthread_cancel_init() on Linux.
538
bartb2260b82011-02-13 07:55:36 +0000539static __always_inline
bart791a0c62009-07-31 17:31:44 +0000540int pthread_cancel_intercept(pthread_t pt_thread)
bart2bc9c102008-09-27 12:40:57 +0000541{
bartbedfd232009-03-26 19:07:15 +0000542 int ret;
543 OrigFn fn;
544 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000545 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_THREAD_CANCEL,
bart575ce8e2011-05-15 07:04:03 +0000546 pt_thread, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000547 CALL_FN_W_W(ret, fn, pt_thread);
sewardj4b3a7422011-10-24 13:21:57 +0000548 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_THREAD_CANCEL,
bart575ce8e2011-05-15 07:04:03 +0000549 pt_thread, ret==0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000550 return ret;
bart2bc9c102008-09-27 12:40:57 +0000551}
552
bart791a0c62009-07-31 17:31:44 +0000553PTH_FUNCS(int, pthreadZucancel, pthread_cancel_intercept,
554 (pthread_t thread), (thread))
555
bartb2260b82011-02-13 07:55:36 +0000556static __always_inline
bart791a0c62009-07-31 17:31:44 +0000557int pthread_once_intercept(pthread_once_t *once_control,
558 void (*init_routine)(void))
bart93a02742009-07-26 15:55:48 +0000559{
560 int ret;
561 OrigFn fn;
562 VALGRIND_GET_ORIG_FN(fn);
563 /*
564 * Ignore any data races triggered by the implementation of pthread_once().
565 * Necessary for Darwin. This is not necessary for Linux but doesn't have
566 * any known adverse effects.
567 */
bart554953f2009-07-26 16:21:00 +0000568 DRD_IGNORE_VAR(*once_control);
bart6d956dc2011-07-28 09:54:37 +0000569 ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
bart93a02742009-07-26 15:55:48 +0000570 CALL_FN_W_WW(ret, fn, once_control, init_routine);
bart6d956dc2011-07-28 09:54:37 +0000571 ANNOTATE_IGNORE_READS_AND_WRITES_END();
bart554953f2009-07-26 16:21:00 +0000572 DRD_STOP_IGNORING_VAR(*once_control);
bart93a02742009-07-26 15:55:48 +0000573 return ret;
574}
575
bart791a0c62009-07-31 17:31:44 +0000576PTH_FUNCS(int, pthreadZuonce, pthread_once_intercept,
577 (pthread_once_t *once_control, void (*init_routine)(void)),
578 (once_control, init_routine));
579
bartb2260b82011-02-13 07:55:36 +0000580static __always_inline
bart791a0c62009-07-31 17:31:44 +0000581int pthread_mutex_init_intercept(pthread_mutex_t *mutex,
582 const pthread_mutexattr_t* attr)
sewardjaf44c822007-11-25 14:01:38 +0000583{
bartbedfd232009-03-26 19:07:15 +0000584 int ret;
bartbedfd232009-03-26 19:07:15 +0000585 OrigFn fn;
586 int mt;
587 VALGRIND_GET_ORIG_FN(fn);
588 mt = PTHREAD_MUTEX_DEFAULT;
589 if (attr)
590 pthread_mutexattr_gettype(attr, &mt);
sewardj4b3a7422011-10-24 13:21:57 +0000591 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_INIT,
bart575ce8e2011-05-15 07:04:03 +0000592 mutex, DRD_(pthread_to_drd_mutex_type)(mt),
593 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000594 CALL_FN_W_WW(ret, fn, mutex, attr);
sewardj4b3a7422011-10-24 13:21:57 +0000595 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_INIT,
bart575ce8e2011-05-15 07:04:03 +0000596 mutex, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000597 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000598}
599
bart791a0c62009-07-31 17:31:44 +0000600PTH_FUNCS(int, pthreadZumutexZuinit, pthread_mutex_init_intercept,
601 (pthread_mutex_t *mutex, const pthread_mutexattr_t* attr),
602 (mutex, attr));
603
bartb2260b82011-02-13 07:55:36 +0000604static __always_inline
bart791a0c62009-07-31 17:31:44 +0000605int pthread_mutex_destroy_intercept(pthread_mutex_t* mutex)
sewardjaf44c822007-11-25 14:01:38 +0000606{
bartbedfd232009-03-26 19:07:15 +0000607 int ret;
bartbedfd232009-03-26 19:07:15 +0000608 OrigFn fn;
609 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000610 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_DESTROY,
bart575ce8e2011-05-15 07:04:03 +0000611 mutex, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000612 CALL_FN_W_W(ret, fn, mutex);
sewardj4b3a7422011-10-24 13:21:57 +0000613 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_DESTROY,
bart575ce8e2011-05-15 07:04:03 +0000614 mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000615 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000616}
617
bart791a0c62009-07-31 17:31:44 +0000618PTH_FUNCS(int, pthreadZumutexZudestroy, pthread_mutex_destroy_intercept,
619 (pthread_mutex_t *mutex), (mutex));
620
bartb2260b82011-02-13 07:55:36 +0000621static __always_inline
bart791a0c62009-07-31 17:31:44 +0000622int pthread_mutex_lock_intercept(pthread_mutex_t* mutex)
sewardjaf44c822007-11-25 14:01:38 +0000623{
bartbedfd232009-03-26 19:07:15 +0000624 int ret;
bartbedfd232009-03-26 19:07:15 +0000625 OrigFn fn;
626 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000627 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +0000628 mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000629 CALL_FN_W_W(ret, fn, mutex);
sewardj4b3a7422011-10-24 13:21:57 +0000630 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +0000631 mutex, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000632 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000633}
634
bart791a0c62009-07-31 17:31:44 +0000635PTH_FUNCS(int, pthreadZumutexZulock, pthread_mutex_lock_intercept,
636 (pthread_mutex_t *mutex), (mutex));
637
bartb2260b82011-02-13 07:55:36 +0000638static __always_inline
bart791a0c62009-07-31 17:31:44 +0000639int pthread_mutex_trylock_intercept(pthread_mutex_t* mutex)
sewardjaf44c822007-11-25 14:01:38 +0000640{
bartbedfd232009-03-26 19:07:15 +0000641 int ret;
bartbedfd232009-03-26 19:07:15 +0000642 OrigFn fn;
643 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000644 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +0000645 mutex, DRD_(mutex_type)(mutex), 1, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000646 CALL_FN_W_W(ret, fn, mutex);
sewardj4b3a7422011-10-24 13:21:57 +0000647 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +0000648 mutex, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000649 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000650}
651
bart791a0c62009-07-31 17:31:44 +0000652PTH_FUNCS(int, pthreadZumutexZutrylock, pthread_mutex_trylock_intercept,
653 (pthread_mutex_t *mutex), (mutex));
654
bartb2260b82011-02-13 07:55:36 +0000655static __always_inline
bart791a0c62009-07-31 17:31:44 +0000656int pthread_mutex_timedlock_intercept(pthread_mutex_t *mutex,
657 const struct timespec *abs_timeout)
sewardj85642922008-01-14 11:54:56 +0000658{
bartbedfd232009-03-26 19:07:15 +0000659 int ret;
bartbedfd232009-03-26 19:07:15 +0000660 OrigFn fn;
661 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000662 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +0000663 mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000664 CALL_FN_W_WW(ret, fn, mutex, abs_timeout);
sewardj4b3a7422011-10-24 13:21:57 +0000665 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +0000666 mutex, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000667 return ret;
sewardj85642922008-01-14 11:54:56 +0000668}
669
bart791a0c62009-07-31 17:31:44 +0000670PTH_FUNCS(int, pthreadZumutexZutimedlock, pthread_mutex_timedlock_intercept,
671 (pthread_mutex_t *mutex, const struct timespec *abs_timeout),
672 (mutex, abs_timeout));
673
bartb2260b82011-02-13 07:55:36 +0000674static __always_inline
bart791a0c62009-07-31 17:31:44 +0000675int pthread_mutex_unlock_intercept(pthread_mutex_t *mutex)
sewardjaf44c822007-11-25 14:01:38 +0000676{
bartbedfd232009-03-26 19:07:15 +0000677 int ret;
bartbedfd232009-03-26 19:07:15 +0000678 OrigFn fn;
679 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000680 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_UNLOCK,
bart575ce8e2011-05-15 07:04:03 +0000681 mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000682 CALL_FN_W_W(ret, fn, mutex);
sewardj4b3a7422011-10-24 13:21:57 +0000683 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_UNLOCK,
bart575ce8e2011-05-15 07:04:03 +0000684 mutex, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000685 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000686}
687
bart791a0c62009-07-31 17:31:44 +0000688PTH_FUNCS(int, pthreadZumutexZuunlock, pthread_mutex_unlock_intercept,
689 (pthread_mutex_t *mutex), (mutex));
690
bartb2260b82011-02-13 07:55:36 +0000691static __always_inline
bart791a0c62009-07-31 17:31:44 +0000692int pthread_cond_init_intercept(pthread_cond_t* cond,
693 const pthread_condattr_t* attr)
sewardjaf44c822007-11-25 14:01:38 +0000694{
bartbedfd232009-03-26 19:07:15 +0000695 int ret;
bartbedfd232009-03-26 19:07:15 +0000696 OrigFn fn;
697 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000698 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_INIT,
bart575ce8e2011-05-15 07:04:03 +0000699 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000700 CALL_FN_W_WW(ret, fn, cond, attr);
sewardj4b3a7422011-10-24 13:21:57 +0000701 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_INIT,
bart575ce8e2011-05-15 07:04:03 +0000702 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000703 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000704}
705
bart791a0c62009-07-31 17:31:44 +0000706PTH_FUNCS(int, pthreadZucondZuinit, pthread_cond_init_intercept,
707 (pthread_cond_t* cond, const pthread_condattr_t* attr),
708 (cond, attr));
709
bartb2260b82011-02-13 07:55:36 +0000710static __always_inline
bart791a0c62009-07-31 17:31:44 +0000711int pthread_cond_destroy_intercept(pthread_cond_t* cond)
sewardjaf44c822007-11-25 14:01:38 +0000712{
bartbedfd232009-03-26 19:07:15 +0000713 int ret;
bartbedfd232009-03-26 19:07:15 +0000714 OrigFn fn;
715 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000716 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_DESTROY,
bart575ce8e2011-05-15 07:04:03 +0000717 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000718 CALL_FN_W_W(ret, fn, cond);
sewardj4b3a7422011-10-24 13:21:57 +0000719 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_DESTROY,
bart575ce8e2011-05-15 07:04:03 +0000720 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000721 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000722}
723
bart791a0c62009-07-31 17:31:44 +0000724PTH_FUNCS(int, pthreadZucondZudestroy, pthread_cond_destroy_intercept,
725 (pthread_cond_t* cond), (cond));
726
bartb2260b82011-02-13 07:55:36 +0000727static __always_inline
bart791a0c62009-07-31 17:31:44 +0000728int pthread_cond_wait_intercept(pthread_cond_t *cond, pthread_mutex_t *mutex)
sewardjaf44c822007-11-25 14:01:38 +0000729{
bartbedfd232009-03-26 19:07:15 +0000730 int ret;
bartbedfd232009-03-26 19:07:15 +0000731 OrigFn fn;
732 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000733 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_WAIT,
bart575ce8e2011-05-15 07:04:03 +0000734 cond, mutex, DRD_(mutex_type)(mutex), 0, 0);
bartbedfd232009-03-26 19:07:15 +0000735 CALL_FN_W_WW(ret, fn, cond, mutex);
sewardj4b3a7422011-10-24 13:21:57 +0000736 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_WAIT,
bart575ce8e2011-05-15 07:04:03 +0000737 cond, mutex, 1, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000738 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000739}
740
bart791a0c62009-07-31 17:31:44 +0000741PTH_FUNCS(int, pthreadZucondZuwait, pthread_cond_wait_intercept,
742 (pthread_cond_t *cond, pthread_mutex_t *mutex),
743 (cond, mutex));
744
bartb2260b82011-02-13 07:55:36 +0000745static __always_inline
bart791a0c62009-07-31 17:31:44 +0000746int pthread_cond_timedwait_intercept(pthread_cond_t *cond,
747 pthread_mutex_t *mutex,
748 const struct timespec* abstime)
sewardjaf44c822007-11-25 14:01:38 +0000749{
bartbedfd232009-03-26 19:07:15 +0000750 int ret;
bartbedfd232009-03-26 19:07:15 +0000751 OrigFn fn;
752 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000753 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_WAIT,
bart575ce8e2011-05-15 07:04:03 +0000754 cond, mutex, DRD_(mutex_type)(mutex), 0, 0);
bartbedfd232009-03-26 19:07:15 +0000755 CALL_FN_W_WWW(ret, fn, cond, mutex, abstime);
sewardj4b3a7422011-10-24 13:21:57 +0000756 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_WAIT,
bart575ce8e2011-05-15 07:04:03 +0000757 cond, mutex, 1, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000758 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000759}
760
bart791a0c62009-07-31 17:31:44 +0000761PTH_FUNCS(int, pthreadZucondZutimedwait, pthread_cond_timedwait_intercept,
762 (pthread_cond_t *cond, pthread_mutex_t *mutex,
763 const struct timespec* abstime),
764 (cond, mutex, abstime));
765
barte8cbb402009-07-22 19:17:05 +0000766// NOTE: be careful to intercept only pthread_cond_signal() and not Darwin's
767// pthread_cond_signal_thread_np(). The former accepts one argument; the latter
768// two. Intercepting all pthread_cond_signal* functions will cause only one
769// argument to be passed to pthread_cond_signal_np() and hence will cause this
770// last function to crash.
771
bartb2260b82011-02-13 07:55:36 +0000772static __always_inline
bart791a0c62009-07-31 17:31:44 +0000773int pthread_cond_signal_intercept(pthread_cond_t* cond)
barte8cbb402009-07-22 19:17:05 +0000774{
775 int ret;
barte8cbb402009-07-22 19:17:05 +0000776 OrigFn fn;
777 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000778 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_SIGNAL,
bart575ce8e2011-05-15 07:04:03 +0000779 cond, 0, 0, 0, 0);
barte8cbb402009-07-22 19:17:05 +0000780 CALL_FN_W_W(ret, fn, cond);
sewardj4b3a7422011-10-24 13:21:57 +0000781 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_SIGNAL,
bart575ce8e2011-05-15 07:04:03 +0000782 cond, 0, 0, 0, 0);
barte8cbb402009-07-22 19:17:05 +0000783 return ret;
784}
785
bart791a0c62009-07-31 17:31:44 +0000786PTH_FUNCS(int, pthreadZucondZusignal, pthread_cond_signal_intercept,
787 (pthread_cond_t* cond), (cond));
sewardjaf44c822007-11-25 14:01:38 +0000788
bartb2260b82011-02-13 07:55:36 +0000789static __always_inline
bart791a0c62009-07-31 17:31:44 +0000790int pthread_cond_broadcast_intercept(pthread_cond_t* cond)
sewardjaf44c822007-11-25 14:01:38 +0000791{
bartbedfd232009-03-26 19:07:15 +0000792 int ret;
bartbedfd232009-03-26 19:07:15 +0000793 OrigFn fn;
794 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000795 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_BROADCAST,
bart575ce8e2011-05-15 07:04:03 +0000796 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000797 CALL_FN_W_W(ret, fn, cond);
sewardj4b3a7422011-10-24 13:21:57 +0000798 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_BROADCAST,
bart575ce8e2011-05-15 07:04:03 +0000799 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000800 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000801}
802
bart791a0c62009-07-31 17:31:44 +0000803PTH_FUNCS(int, pthreadZucondZubroadcast, pthread_cond_broadcast_intercept,
804 (pthread_cond_t* cond), (cond));
sewardjaf44c822007-11-25 14:01:38 +0000805
njnf76d27a2009-05-28 01:53:07 +0000806#if defined(HAVE_PTHREAD_SPIN_LOCK)
bartb2260b82011-02-13 07:55:36 +0000807static __always_inline
bart791a0c62009-07-31 17:31:44 +0000808int pthread_spin_init_intercept(pthread_spinlock_t *spinlock, int pshared)
sewardjaf44c822007-11-25 14:01:38 +0000809{
bartbedfd232009-03-26 19:07:15 +0000810 int ret;
bartbedfd232009-03-26 19:07:15 +0000811 OrigFn fn;
812 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000813 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK,
bart575ce8e2011-05-15 07:04:03 +0000814 spinlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000815 CALL_FN_W_WW(ret, fn, spinlock, pshared);
sewardj4b3a7422011-10-24 13:21:57 +0000816 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK,
bart575ce8e2011-05-15 07:04:03 +0000817 spinlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000818 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000819}
820
bart791a0c62009-07-31 17:31:44 +0000821PTH_FUNCS(int, pthreadZuspinZuinit, pthread_spin_init_intercept,
822 (pthread_spinlock_t *spinlock, int pshared), (spinlock, pshared));
823
bartb2260b82011-02-13 07:55:36 +0000824static __always_inline
bart791a0c62009-07-31 17:31:44 +0000825int pthread_spin_destroy_intercept(pthread_spinlock_t *spinlock)
sewardjaf44c822007-11-25 14:01:38 +0000826{
bartbedfd232009-03-26 19:07:15 +0000827 int ret;
bartbedfd232009-03-26 19:07:15 +0000828 OrigFn fn;
829 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000830 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_DESTROY,
bart575ce8e2011-05-15 07:04:03 +0000831 spinlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000832 CALL_FN_W_W(ret, fn, spinlock);
sewardj4b3a7422011-10-24 13:21:57 +0000833 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_DESTROY,
bart575ce8e2011-05-15 07:04:03 +0000834 spinlock, mutex_type_spinlock, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000835 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000836}
837
bart791a0c62009-07-31 17:31:44 +0000838PTH_FUNCS(int, pthreadZuspinZudestroy, pthread_spin_destroy_intercept,
839 (pthread_spinlock_t *spinlock), (spinlock));
840
bartb2260b82011-02-13 07:55:36 +0000841static __always_inline
bart791a0c62009-07-31 17:31:44 +0000842int pthread_spin_lock_intercept(pthread_spinlock_t *spinlock)
sewardjaf44c822007-11-25 14:01:38 +0000843{
bartbedfd232009-03-26 19:07:15 +0000844 int ret;
bartbedfd232009-03-26 19:07:15 +0000845 OrigFn fn;
846 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000847 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +0000848 spinlock, mutex_type_spinlock, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000849 CALL_FN_W_W(ret, fn, spinlock);
sewardj4b3a7422011-10-24 13:21:57 +0000850 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +0000851 spinlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000852 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000853}
854
bart791a0c62009-07-31 17:31:44 +0000855PTH_FUNCS(int, pthreadZuspinZulock, pthread_spin_lock_intercept,
856 (pthread_spinlock_t *spinlock), (spinlock));
857
bartb2260b82011-02-13 07:55:36 +0000858static __always_inline
bart791a0c62009-07-31 17:31:44 +0000859int pthread_spin_trylock_intercept(pthread_spinlock_t *spinlock)
sewardjaf44c822007-11-25 14:01:38 +0000860{
bartbedfd232009-03-26 19:07:15 +0000861 int ret;
bartbedfd232009-03-26 19:07:15 +0000862 OrigFn fn;
863 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000864 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +0000865 spinlock, mutex_type_spinlock, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000866 CALL_FN_W_W(ret, fn, spinlock);
sewardj4b3a7422011-10-24 13:21:57 +0000867 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK,
bart575ce8e2011-05-15 07:04:03 +0000868 spinlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000869 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000870}
871
bart791a0c62009-07-31 17:31:44 +0000872PTH_FUNCS(int, pthreadZuspinZutrylock, pthread_spin_trylock_intercept,
873 (pthread_spinlock_t *spinlock), (spinlock));
874
bartb2260b82011-02-13 07:55:36 +0000875static __always_inline
bart791a0c62009-07-31 17:31:44 +0000876int pthread_spin_unlock_intercept(pthread_spinlock_t *spinlock)
sewardjaf44c822007-11-25 14:01:38 +0000877{
bartbedfd232009-03-26 19:07:15 +0000878 int ret;
bartbedfd232009-03-26 19:07:15 +0000879 OrigFn fn;
880 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000881 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK,
bart575ce8e2011-05-15 07:04:03 +0000882 spinlock, mutex_type_spinlock, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000883 CALL_FN_W_W(ret, fn, spinlock);
sewardj4b3a7422011-10-24 13:21:57 +0000884 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK,
bart575ce8e2011-05-15 07:04:03 +0000885 spinlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000886 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000887}
bart791a0c62009-07-31 17:31:44 +0000888
889PTH_FUNCS(int, pthreadZuspinZuunlock, pthread_spin_unlock_intercept,
890 (pthread_spinlock_t *spinlock), (spinlock));
njnf76d27a2009-05-28 01:53:07 +0000891#endif // HAVE_PTHREAD_SPIN_LOCK
sewardjaf44c822007-11-25 14:01:38 +0000892
njnf76d27a2009-05-28 01:53:07 +0000893
894#if defined(HAVE_PTHREAD_BARRIER_INIT)
bartb2260b82011-02-13 07:55:36 +0000895static __always_inline
bart791a0c62009-07-31 17:31:44 +0000896int pthread_barrier_init_intercept(pthread_barrier_t* barrier,
897 const pthread_barrierattr_t* attr,
898 unsigned count)
sewardj85642922008-01-14 11:54:56 +0000899{
bartbedfd232009-03-26 19:07:15 +0000900 int ret;
bartbedfd232009-03-26 19:07:15 +0000901 OrigFn fn;
902 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000903 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_BARRIER_INIT,
bart575ce8e2011-05-15 07:04:03 +0000904 barrier, pthread_barrier, count, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000905 CALL_FN_W_WWW(ret, fn, barrier, attr, count);
sewardj4b3a7422011-10-24 13:21:57 +0000906 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_BARRIER_INIT,
bart575ce8e2011-05-15 07:04:03 +0000907 barrier, pthread_barrier, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000908 return ret;
sewardj85642922008-01-14 11:54:56 +0000909}
910
bart791a0c62009-07-31 17:31:44 +0000911PTH_FUNCS(int, pthreadZubarrierZuinit, pthread_barrier_init_intercept,
912 (pthread_barrier_t* barrier, const pthread_barrierattr_t* attr,
913 unsigned count), (barrier, attr, count));
914
bartb2260b82011-02-13 07:55:36 +0000915static __always_inline
bart791a0c62009-07-31 17:31:44 +0000916int pthread_barrier_destroy_intercept(pthread_barrier_t* barrier)
sewardj85642922008-01-14 11:54:56 +0000917{
bartbedfd232009-03-26 19:07:15 +0000918 int ret;
bartbedfd232009-03-26 19:07:15 +0000919 OrigFn fn;
920 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000921 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_BARRIER_DESTROY,
bart575ce8e2011-05-15 07:04:03 +0000922 barrier, pthread_barrier, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000923 CALL_FN_W_W(ret, fn, barrier);
sewardj4b3a7422011-10-24 13:21:57 +0000924 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_BARRIER_DESTROY,
bart575ce8e2011-05-15 07:04:03 +0000925 barrier, pthread_barrier, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000926 return ret;
sewardj85642922008-01-14 11:54:56 +0000927}
928
bart791a0c62009-07-31 17:31:44 +0000929PTH_FUNCS(int, pthreadZubarrierZudestroy, pthread_barrier_destroy_intercept,
930 (pthread_barrier_t* barrier), (barrier));
931
bartb2260b82011-02-13 07:55:36 +0000932static __always_inline
bart791a0c62009-07-31 17:31:44 +0000933int pthread_barrier_wait_intercept(pthread_barrier_t* barrier)
sewardj85642922008-01-14 11:54:56 +0000934{
bartbedfd232009-03-26 19:07:15 +0000935 int ret;
bartbedfd232009-03-26 19:07:15 +0000936 OrigFn fn;
937 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000938 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_BARRIER_WAIT,
bart575ce8e2011-05-15 07:04:03 +0000939 barrier, pthread_barrier, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000940 CALL_FN_W_W(ret, fn, barrier);
sewardj4b3a7422011-10-24 13:21:57 +0000941 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_BARRIER_WAIT,
bartbedfd232009-03-26 19:07:15 +0000942 barrier, pthread_barrier,
943 ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD,
944 ret == PTHREAD_BARRIER_SERIAL_THREAD, 0);
945 return ret;
sewardj85642922008-01-14 11:54:56 +0000946}
bart791a0c62009-07-31 17:31:44 +0000947
948PTH_FUNCS(int, pthreadZubarrierZuwait, pthread_barrier_wait_intercept,
949 (pthread_barrier_t* barrier), (barrier));
njnf76d27a2009-05-28 01:53:07 +0000950#endif // HAVE_PTHREAD_BARRIER_INIT
sewardj85642922008-01-14 11:54:56 +0000951
952
bartb2260b82011-02-13 07:55:36 +0000953static __always_inline
bart791a0c62009-07-31 17:31:44 +0000954int sem_init_intercept(sem_t *sem, int pshared, unsigned int value)
sewardj85642922008-01-14 11:54:56 +0000955{
bartbedfd232009-03-26 19:07:15 +0000956 int ret;
bartbedfd232009-03-26 19:07:15 +0000957 OrigFn fn;
958 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000959 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_INIT,
bart575ce8e2011-05-15 07:04:03 +0000960 sem, pshared, value, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000961 CALL_FN_W_WWW(ret, fn, sem, pshared, value);
sewardj4b3a7422011-10-24 13:21:57 +0000962 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_INIT,
bart575ce8e2011-05-15 07:04:03 +0000963 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000964 return ret;
sewardj85642922008-01-14 11:54:56 +0000965}
966
bart791a0c62009-07-31 17:31:44 +0000967PTH_FUNCS(int, semZuinit, sem_init_intercept,
968 (sem_t *sem, int pshared, unsigned int value), (sem, pshared, value));
969
bartb2260b82011-02-13 07:55:36 +0000970static __always_inline
bart791a0c62009-07-31 17:31:44 +0000971int sem_destroy_intercept(sem_t *sem)
sewardj85642922008-01-14 11:54:56 +0000972{
bartbedfd232009-03-26 19:07:15 +0000973 int ret;
bartbedfd232009-03-26 19:07:15 +0000974 OrigFn fn;
975 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000976 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_DESTROY,
bart575ce8e2011-05-15 07:04:03 +0000977 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000978 CALL_FN_W_W(ret, fn, sem);
sewardj4b3a7422011-10-24 13:21:57 +0000979 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_DESTROY,
bart575ce8e2011-05-15 07:04:03 +0000980 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000981 return ret;
sewardj85642922008-01-14 11:54:56 +0000982}
983
bart791a0c62009-07-31 17:31:44 +0000984PTH_FUNCS(int, semZudestroy, sem_destroy_intercept, (sem_t *sem), (sem));
985
bartb2260b82011-02-13 07:55:36 +0000986static __always_inline
bart791a0c62009-07-31 17:31:44 +0000987sem_t* sem_open_intercept(const char *name, int oflag, mode_t mode,
988 unsigned int value)
bart25f9f542009-07-23 16:31:39 +0000989{
990 sem_t *ret;
bart25f9f542009-07-23 16:31:39 +0000991 OrigFn fn;
992 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +0000993 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_OPEN,
bart575ce8e2011-05-15 07:04:03 +0000994 name, oflag, mode, value, 0);
bart25f9f542009-07-23 16:31:39 +0000995 CALL_FN_W_WWWW(ret, fn, name, oflag, mode, value);
sewardj4b3a7422011-10-24 13:21:57 +0000996 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_OPEN,
bart575ce8e2011-05-15 07:04:03 +0000997 ret != SEM_FAILED ? ret : 0,
998 name, oflag, mode, value);
bart25f9f542009-07-23 16:31:39 +0000999 return ret;
1000}
1001
bart791a0c62009-07-31 17:31:44 +00001002PTH_FUNCS(sem_t *, semZuopen, sem_open_intercept,
1003 (const char *name, int oflag, mode_t mode, unsigned int value),
1004 (name, oflag, mode, value));
1005
bartb2260b82011-02-13 07:55:36 +00001006static __always_inline int sem_close_intercept(sem_t *sem)
bart25f9f542009-07-23 16:31:39 +00001007{
1008 int ret;
bart25f9f542009-07-23 16:31:39 +00001009 OrigFn fn;
1010 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001011 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_CLOSE,
bart575ce8e2011-05-15 07:04:03 +00001012 sem, 0, 0, 0, 0);
bart25f9f542009-07-23 16:31:39 +00001013 CALL_FN_W_W(ret, fn, sem);
sewardj4b3a7422011-10-24 13:21:57 +00001014 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_CLOSE,
bart575ce8e2011-05-15 07:04:03 +00001015 sem, 0, 0, 0, 0);
bart25f9f542009-07-23 16:31:39 +00001016 return ret;
1017}
1018
bart791a0c62009-07-31 17:31:44 +00001019PTH_FUNCS(int, semZuclose, sem_close_intercept, (sem_t *sem), (sem));
1020
bartb2260b82011-02-13 07:55:36 +00001021static __always_inline int sem_wait_intercept(sem_t *sem)
sewardj85642922008-01-14 11:54:56 +00001022{
bartbedfd232009-03-26 19:07:15 +00001023 int ret;
bartbedfd232009-03-26 19:07:15 +00001024 OrigFn fn;
1025 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001026 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001027 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001028 CALL_FN_W_W(ret, fn, sem);
sewardj4b3a7422011-10-24 13:21:57 +00001029 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001030 sem, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001031 return ret;
sewardj85642922008-01-14 11:54:56 +00001032}
1033
bart791a0c62009-07-31 17:31:44 +00001034PTH_FUNCS(int, semZuwait, sem_wait_intercept, (sem_t *sem), (sem));
1035
bartb2260b82011-02-13 07:55:36 +00001036static __always_inline int sem_trywait_intercept(sem_t *sem)
sewardj85642922008-01-14 11:54:56 +00001037{
bartbedfd232009-03-26 19:07:15 +00001038 int ret;
bartbedfd232009-03-26 19:07:15 +00001039 OrigFn fn;
1040 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001041 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001042 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001043 CALL_FN_W_W(ret, fn, sem);
sewardj4b3a7422011-10-24 13:21:57 +00001044 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001045 sem, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001046 return ret;
sewardj85642922008-01-14 11:54:56 +00001047}
1048
bart791a0c62009-07-31 17:31:44 +00001049PTH_FUNCS(int, semZutrywait, sem_trywait_intercept, (sem_t *sem), (sem));
1050
bartb2260b82011-02-13 07:55:36 +00001051static __always_inline
bart791a0c62009-07-31 17:31:44 +00001052int sem_timedwait_intercept(sem_t *sem, const struct timespec *abs_timeout)
sewardj85642922008-01-14 11:54:56 +00001053{
bartbedfd232009-03-26 19:07:15 +00001054 int ret;
bartbedfd232009-03-26 19:07:15 +00001055 OrigFn fn;
1056 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001057 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001058 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001059 CALL_FN_W_WW(ret, fn, sem, abs_timeout);
sewardj4b3a7422011-10-24 13:21:57 +00001060 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_WAIT,
bart575ce8e2011-05-15 07:04:03 +00001061 sem, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001062 return ret;
sewardj85642922008-01-14 11:54:56 +00001063}
1064
bart791a0c62009-07-31 17:31:44 +00001065PTH_FUNCS(int, semZutimedwait, sem_timedwait_intercept,
1066 (sem_t *sem, const struct timespec *abs_timeout),
1067 (sem, abs_timeout));
1068
bartb2260b82011-02-13 07:55:36 +00001069static __always_inline int sem_post_intercept(sem_t *sem)
sewardj85642922008-01-14 11:54:56 +00001070{
bartbedfd232009-03-26 19:07:15 +00001071 int ret;
bartbedfd232009-03-26 19:07:15 +00001072 OrigFn fn;
1073 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001074 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_POST,
bart575ce8e2011-05-15 07:04:03 +00001075 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001076 CALL_FN_W_W(ret, fn, sem);
sewardj4b3a7422011-10-24 13:21:57 +00001077 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_POST,
bart575ce8e2011-05-15 07:04:03 +00001078 sem, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001079 return ret;
sewardj85642922008-01-14 11:54:56 +00001080}
1081
bart791a0c62009-07-31 17:31:44 +00001082PTH_FUNCS(int, semZupost, sem_post_intercept, (sem_t *sem), (sem));
1083
sewardj0c09bf02011-07-11 22:11:58 +00001084/* Android's pthread.h doesn't say anything about rwlocks, hence these
1085 functions have to be conditionally compiled. */
1086#if defined(HAVE_PTHREAD_RWLOCK_T)
1087
bartb2260b82011-02-13 07:55:36 +00001088static __always_inline
bart791a0c62009-07-31 17:31:44 +00001089int pthread_rwlock_init_intercept(pthread_rwlock_t* rwlock,
1090 const pthread_rwlockattr_t* attr)
bart00344642008-03-01 15:27:41 +00001091{
bartbedfd232009-03-26 19:07:15 +00001092 int ret;
bartbedfd232009-03-26 19:07:15 +00001093 OrigFn fn;
1094 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001095 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_INIT,
bart575ce8e2011-05-15 07:04:03 +00001096 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001097 CALL_FN_W_WW(ret, fn, rwlock, attr);
1098 return ret;
bart00344642008-03-01 15:27:41 +00001099}
1100
bart791a0c62009-07-31 17:31:44 +00001101PTH_FUNCS(int,
1102 pthreadZurwlockZuinit, pthread_rwlock_init_intercept,
1103 (pthread_rwlock_t* rwlock, const pthread_rwlockattr_t* attr),
1104 (rwlock, attr));
1105
bartb2260b82011-02-13 07:55:36 +00001106static __always_inline
bart791a0c62009-07-31 17:31:44 +00001107int pthread_rwlock_destroy_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001108{
bartbedfd232009-03-26 19:07:15 +00001109 int ret;
bartbedfd232009-03-26 19:07:15 +00001110 OrigFn fn;
1111 VALGRIND_GET_ORIG_FN(fn);
1112 CALL_FN_W_W(ret, fn, rwlock);
sewardj4b3a7422011-10-24 13:21:57 +00001113 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_DESTROY,
bart575ce8e2011-05-15 07:04:03 +00001114 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001115 return ret;
bart00344642008-03-01 15:27:41 +00001116}
1117
bart791a0c62009-07-31 17:31:44 +00001118PTH_FUNCS(int,
1119 pthreadZurwlockZudestroy, pthread_rwlock_destroy_intercept,
1120 (pthread_rwlock_t* rwlock), (rwlock));
1121
bartb2260b82011-02-13 07:55:36 +00001122static __always_inline
bart791a0c62009-07-31 17:31:44 +00001123int pthread_rwlock_rdlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001124{
bartbedfd232009-03-26 19:07:15 +00001125 int ret;
bartbedfd232009-03-26 19:07:15 +00001126 OrigFn fn;
1127 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001128 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_RDLOCK,
bart575ce8e2011-05-15 07:04:03 +00001129 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001130 CALL_FN_W_W(ret, fn, rwlock);
sewardj4b3a7422011-10-24 13:21:57 +00001131 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_RDLOCK,
bart575ce8e2011-05-15 07:04:03 +00001132 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001133 return ret;
bart00344642008-03-01 15:27:41 +00001134}
1135
bart791a0c62009-07-31 17:31:44 +00001136PTH_FUNCS(int,
1137 pthreadZurwlockZurdlock, pthread_rwlock_rdlock_intercept,
1138 (pthread_rwlock_t* rwlock), (rwlock));
1139
bartb2260b82011-02-13 07:55:36 +00001140static __always_inline
bart791a0c62009-07-31 17:31:44 +00001141int pthread_rwlock_wrlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001142{
bartbedfd232009-03-26 19:07:15 +00001143 int ret;
bartbedfd232009-03-26 19:07:15 +00001144 OrigFn fn;
1145 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001146 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_WRLOCK,
bart575ce8e2011-05-15 07:04:03 +00001147 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001148 CALL_FN_W_W(ret, fn, rwlock);
sewardj4b3a7422011-10-24 13:21:57 +00001149 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_WRLOCK,
bart575ce8e2011-05-15 07:04:03 +00001150 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001151 return ret;
bart00344642008-03-01 15:27:41 +00001152}
1153
bart791a0c62009-07-31 17:31:44 +00001154PTH_FUNCS(int,
1155 pthreadZurwlockZuwrlock, pthread_rwlock_wrlock_intercept,
1156 (pthread_rwlock_t* rwlock), (rwlock));
1157
bartb2260b82011-02-13 07:55:36 +00001158static __always_inline
bart791a0c62009-07-31 17:31:44 +00001159int pthread_rwlock_timedrdlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001160{
bartbedfd232009-03-26 19:07:15 +00001161 int ret;
bartbedfd232009-03-26 19:07:15 +00001162 OrigFn fn;
1163 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001164 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_RDLOCK,
bart575ce8e2011-05-15 07:04:03 +00001165 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001166 CALL_FN_W_W(ret, fn, rwlock);
sewardj4b3a7422011-10-24 13:21:57 +00001167 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_RDLOCK,
bart575ce8e2011-05-15 07:04:03 +00001168 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001169 return ret;
bart00344642008-03-01 15:27:41 +00001170}
1171
bart791a0c62009-07-31 17:31:44 +00001172PTH_FUNCS(int,
1173 pthreadZurwlockZutimedrdlock, pthread_rwlock_timedrdlock_intercept,
1174 (pthread_rwlock_t* rwlock), (rwlock));
1175
bartb2260b82011-02-13 07:55:36 +00001176static __always_inline
bart791a0c62009-07-31 17:31:44 +00001177int pthread_rwlock_timedwrlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001178{
bartbedfd232009-03-26 19:07:15 +00001179 int ret;
bartbedfd232009-03-26 19:07:15 +00001180 OrigFn fn;
1181 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001182 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_WRLOCK,
bart575ce8e2011-05-15 07:04:03 +00001183 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001184 CALL_FN_W_W(ret, fn, rwlock);
sewardj4b3a7422011-10-24 13:21:57 +00001185 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_WRLOCK,
bart575ce8e2011-05-15 07:04:03 +00001186 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001187 return ret;
bart00344642008-03-01 15:27:41 +00001188}
1189
bart791a0c62009-07-31 17:31:44 +00001190PTH_FUNCS(int,
1191 pthreadZurwlockZutimedwrlock, pthread_rwlock_timedwrlock_intercept,
1192 (pthread_rwlock_t* rwlock), (rwlock));
1193
bartb2260b82011-02-13 07:55:36 +00001194static __always_inline
bart791a0c62009-07-31 17:31:44 +00001195int pthread_rwlock_tryrdlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001196{
bartbedfd232009-03-26 19:07:15 +00001197 int ret;
bartbedfd232009-03-26 19:07:15 +00001198 OrigFn fn;
1199 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001200 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_RDLOCK,
bart575ce8e2011-05-15 07:04:03 +00001201 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001202 CALL_FN_W_W(ret, fn, rwlock);
sewardj4b3a7422011-10-24 13:21:57 +00001203 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_RDLOCK,
bart575ce8e2011-05-15 07:04:03 +00001204 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001205 return ret;
bart00344642008-03-01 15:27:41 +00001206}
1207
bart791a0c62009-07-31 17:31:44 +00001208PTH_FUNCS(int,
1209 pthreadZurwlockZutryrdlock, pthread_rwlock_tryrdlock_intercept,
1210 (pthread_rwlock_t* rwlock), (rwlock));
1211
bartb2260b82011-02-13 07:55:36 +00001212static __always_inline
bart791a0c62009-07-31 17:31:44 +00001213int pthread_rwlock_trywrlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001214{
bartbedfd232009-03-26 19:07:15 +00001215 int ret;
bartbedfd232009-03-26 19:07:15 +00001216 OrigFn fn;
1217 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001218 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_WRLOCK,
bart575ce8e2011-05-15 07:04:03 +00001219 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001220 CALL_FN_W_W(ret, fn, rwlock);
sewardj4b3a7422011-10-24 13:21:57 +00001221 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_WRLOCK,
bart575ce8e2011-05-15 07:04:03 +00001222 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001223 return ret;
bart00344642008-03-01 15:27:41 +00001224}
1225
bart791a0c62009-07-31 17:31:44 +00001226PTH_FUNCS(int,
1227 pthreadZurwlockZutrywrlock, pthread_rwlock_trywrlock_intercept,
1228 (pthread_rwlock_t* rwlock), (rwlock));
1229
bartb2260b82011-02-13 07:55:36 +00001230static __always_inline
bart791a0c62009-07-31 17:31:44 +00001231int pthread_rwlock_unlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001232{
bartbedfd232009-03-26 19:07:15 +00001233 int ret;
bartbedfd232009-03-26 19:07:15 +00001234 OrigFn fn;
1235 VALGRIND_GET_ORIG_FN(fn);
sewardj4b3a7422011-10-24 13:21:57 +00001236 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_UNLOCK,
bart575ce8e2011-05-15 07:04:03 +00001237 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001238 CALL_FN_W_W(ret, fn, rwlock);
sewardj4b3a7422011-10-24 13:21:57 +00001239 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_UNLOCK,
bart575ce8e2011-05-15 07:04:03 +00001240 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001241 return ret;
bart00344642008-03-01 15:27:41 +00001242}
bart791a0c62009-07-31 17:31:44 +00001243
1244PTH_FUNCS(int,
1245 pthreadZurwlockZuunlock, pthread_rwlock_unlock_intercept,
1246 (pthread_rwlock_t* rwlock), (rwlock));
sewardj0c09bf02011-07-11 22:11:58 +00001247
1248#endif /* defined(HAVE_PTHREAD_RWLOCK_T) */