blob: 5b13bb30b673968ac96d174db8e7e510162100d0 [file] [log] [blame]
bart922304f2011-03-13 12:02:44 +00001/* -*- mode: C; c-basic-offset: 3; indent-tabs-mode: nil; -*- */
sewardjaf44c822007-11-25 14:01:38 +00002
3/*--------------------------------------------------------------------*/
bart227c6592009-02-14 12:12:57 +00004/*--- Client-space code for DRD. drd_pthread_intercepts.c ---*/
sewardjaf44c822007-11-25 14:01:38 +00005/*--------------------------------------------------------------------*/
6
7/*
bart86562bd2009-02-16 19:43:56 +00008 This file is part of DRD, a thread error detector.
sewardjaf44c822007-11-25 14:01:38 +00009
bart82397422011-03-08 17:53:45 +000010 Copyright (C) 2006-2011 Bart Van Assche <bvanassche@acm.org>.
sewardjaf44c822007-11-25 14:01:38 +000011
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 02111-1307, USA.
26
27 The GNU General Public License is contained in the file COPYING.
28*/
29
30/* ---------------------------------------------------------------------
bart31b983d2010-02-21 14:52:59 +000031 ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU.
sewardjaf44c822007-11-25 14:01:38 +000032
33 These functions are not called directly - they're the targets of code
34 redirection or load notifications (see pub_core_redir.h for info).
35 They're named weirdly so that the intercept code can find them when the
36 shared object is initially loaded.
37
38 Note that this filename has the "drd_" prefix because it can appear
39 in stack traces, and the "drd_" makes it a little clearer that it
40 originates from Valgrind.
41 ------------------------------------------------------------------ */
42
bart227c6592009-02-14 12:12:57 +000043/*
barta764b372009-02-15 10:40:44 +000044 * Define _GNU_SOURCE to make sure that pthread_spinlock_t is available when
45 * compiling with older glibc versions (2.3 or before).
46 */
sewardjaf44c822007-11-25 14:01:38 +000047#ifndef _GNU_SOURCE
48#define _GNU_SOURCE
49#endif
50
bart227c6592009-02-14 12:12:57 +000051#include <assert.h> /* assert() */
bartd1a5cd62011-07-28 15:04:08 +000052#include <errno.h>
bart227c6592009-02-14 12:12:57 +000053#include <pthread.h> /* pthread_mutex_t */
54#include <semaphore.h> /* sem_t */
bart33f76c12010-09-19 11:14:31 +000055#include <stdint.h> /* uintptr_t */
bart227c6592009-02-14 12:12:57 +000056#include <stdio.h> /* fprintf() */
57#include <stdlib.h> /* malloc(), free() */
58#include <unistd.h> /* confstr() */
bart651f56b2011-07-26 19:30:28 +000059#ifdef __linux__
60#include <asm/unistd.h> /* __NR_futex */
61#include <linux/futex.h> /* FUTEX_WAIT */
bartd1a5cd62011-07-28 15:04:08 +000062#ifndef FUTEX_PRIVATE_FLAG
63#define FUTEX_PRIVATE_FLAG 0
64#endif
bart651f56b2011-07-26 19:30:28 +000065#endif
bart227c6592009-02-14 12:12:57 +000066#include "config.h" /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP etc. */
67#include "drd_basics.h" /* DRD_() */
sewardjaf44c822007-11-25 14:01:38 +000068#include "drd_clientreq.h"
bart227c6592009-02-14 12:12:57 +000069#include "pub_tool_redir.h" /* VG_WRAP_FUNCTION_ZZ() */
sewardjaf44c822007-11-25 14:01:38 +000070
71
barta0b72222009-03-12 18:39:31 +000072/*
bart82397422011-03-08 17:53:45 +000073 * Notes regarding thread creation:
74 * - sg_init() runs on the context of the created thread and copies the vector
75 * clock of the creator thread. This only works reliably if the creator
76 * thread waits until this copy has been performed.
77 * - DRD_(thread_compute_minimum_vc)() does not take the vector clocks into
78 * account that are involved in thread creation and for which the
79 * corresponding thread has not yet been created. So not waiting until the
80 * created thread has been started would make it possible that segments get
81 * discarded that should not yet be discarded. Or: some data races are not
82 * detected.
barta0b72222009-03-12 18:39:31 +000083 */
barta0b72222009-03-12 18:39:31 +000084
bart791a0c62009-07-31 17:31:44 +000085/**
86 * Macro for generating a Valgrind interception function.
87 * @param[in] ret_ty Return type of the function to be generated.
88 * @param[in] zf Z-encoded name of the interception function.
89 * @param[in] implf Name of the function that implements the intercept.
90 * @param[in] arg_decl Argument declaration list enclosed in parentheses.
91 * @param[in] argl Argument list enclosed in parentheses.
92 */
bart377d23f2011-03-05 14:51:24 +000093#ifdef VGO_darwin
94static int never_true;
95#define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl) \
96 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl; \
97 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl \
98 { \
99 ret_ty pth_func_result = implf argl; \
100 /* Apparently inserting a function call in wrapper functions */ \
101 /* is sufficient to avoid misaligned stack errors. */ \
102 if (never_true) \
103 fflush(stdout); \
104 return pth_func_result; \
105 }
106#else
bart791a0c62009-07-31 17:31:44 +0000107#define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl) \
108 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl; \
109 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl \
110 { return implf argl; }
bart377d23f2011-03-05 14:51:24 +0000111#endif
sewardjaf44c822007-11-25 14:01:38 +0000112
bart791a0c62009-07-31 17:31:44 +0000113/**
114 * Macro for generating three Valgrind interception functions: one with the
115 * Z-encoded name zf, one with ZAZa ("@*") appended to the name zf and one
116 * with ZDZa ("$*") appended to the name zf. The second generated interception
117 * function will intercept versioned symbols on Linux, and the third will
118 * intercept versioned symbols on Darwin.
119 */
120#define PTH_FUNCS(ret_ty, zf, implf, argl_decl, argl) \
121 PTH_FUNC(ret_ty, zf, implf, argl_decl, argl); \
122 PTH_FUNC(ret_ty, zf ## ZAZa, implf, argl_decl, argl); \
123 PTH_FUNC(ret_ty, zf ## ZDZa, implf, argl_decl, argl);
124
125/*
bartb2260b82011-02-13 07:55:36 +0000126 * Not inlining one of the intercept functions will cause the regression
127 * tests to fail because this would cause an additional stackfram to appear
128 * in the output. The __always_inline macro guarantees that inlining will
129 * happen, even when compiling with optimization disabled.
bart791a0c62009-07-31 17:31:44 +0000130 */
131#undef __always_inline /* since already defined in <cdefs.h> */
bart4f66a772009-07-31 17:59:28 +0000132#if __GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 2
bart791a0c62009-07-31 17:31:44 +0000133#define __always_inline __inline__ __attribute__((always_inline))
134#else
135#define __always_inline __inline__
136#endif
sewardjaf44c822007-11-25 14:01:38 +0000137
bart6f07b252008-04-04 16:45:20 +0000138/* Local data structures. */
sewardjaf44c822007-11-25 14:01:38 +0000139
bart651f56b2011-07-26 19:30:28 +0000140typedef struct {
141 volatile int counter;
142} 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;
bart651f56b2011-07-26 19:30:28 +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);
185 sema->counter = 0;
186}
187
188static void DRD_(sema_destroy)(DrdSema* sema)
189{
190}
191
192static void DRD_(sema_down)(DrdSema* sema)
193{
bartd1a5cd62011-07-28 15:04:08 +0000194 int res = ENOSYS;
195
bart651f56b2011-07-26 19:30:28 +0000196 while (sema->counter == 0) {
bartd1a5cd62011-07-28 15:04:08 +0000197#if defined(__linux__) && defined(__NR_futex)
198 if (syscall(__NR_futex, (UWord)&sema->counter,
bart1f4f3002011-07-29 06:30:23 +0000199 FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0) == 0)
bartd1a5cd62011-07-28 15:04:08 +0000200 res = 0;
bart1f4f3002011-07-29 06:30:23 +0000201 else
bartd1a5cd62011-07-28 15:04:08 +0000202 res = errno;
bart651f56b2011-07-26 19:30:28 +0000203#endif
bartd1a5cd62011-07-28 15:04:08 +0000204 /*
205 * Invoke sched_yield() on non-Linux systems, if the futex syscall has
206 * not been invoked or if this code has been built on a Linux system
207 * where __NR_futex is defined and is run on a Linux system that does
208 * not support the futex syscall.
209 */
bart1f4f3002011-07-29 06:30:23 +0000210 if (res != 0 && res != EWOULDBLOCK)
bartd1a5cd62011-07-28 15:04:08 +0000211 sched_yield();
bart651f56b2011-07-26 19:30:28 +0000212 }
213 sema->counter--;
214}
215
216static void DRD_(sema_up)(DrdSema* sema)
217{
218 sema->counter++;
bartd1a5cd62011-07-28 15:04:08 +0000219#if defined(__linux__) && defined(__NR_futex)
bart651f56b2011-07-26 19:30:28 +0000220 syscall(__NR_futex, (UWord)&sema->counter,
221 FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1);
222#endif
223}
224
bart227c6592009-02-14 12:12:57 +0000225/**
226 * POSIX threads and DRD each have their own mutex type identification.
227 * Convert POSIX threads' mutex type to DRD's mutex type. In the code below
228 * if-statements are used to test the value of 'kind' instead of a switch
229 * statement because some of the PTHREAD_MUTEX_ macro's may have the same
230 * value.
231 */
232static MutexT DRD_(pthread_to_drd_mutex_type)(const int kind)
bart5357fcb2008-02-27 15:46:00 +0000233{
bartbedfd232009-03-26 19:07:15 +0000234 if (kind == PTHREAD_MUTEX_RECURSIVE)
235 return mutex_type_recursive_mutex;
236 else if (kind == PTHREAD_MUTEX_ERRORCHECK)
237 return mutex_type_errorcheck_mutex;
238 else if (kind == PTHREAD_MUTEX_NORMAL)
239 return mutex_type_default_mutex;
240 else if (kind == PTHREAD_MUTEX_DEFAULT)
241 return mutex_type_default_mutex;
bart227c6592009-02-14 12:12:57 +0000242#if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP)
bartbedfd232009-03-26 19:07:15 +0000243 else if (kind == PTHREAD_MUTEX_ADAPTIVE_NP)
244 return mutex_type_default_mutex;
bart227c6592009-02-14 12:12:57 +0000245#endif
bartbedfd232009-03-26 19:07:15 +0000246 else
247 {
248 return mutex_type_invalid_mutex;
249 }
bart5357fcb2008-02-27 15:46:00 +0000250}
251
bart33f76c12010-09-19 11:14:31 +0000252#define IS_ALIGNED(p) (((uintptr_t)(p) & (sizeof(*(p)) - 1)) == 0)
253
bart227c6592009-02-14 12:12:57 +0000254/**
255 * Read the mutex type stored in the client memory used for the mutex
256 * implementation.
257 *
258 * @note This function depends on the implementation of the POSIX threads
259 * library -- the POSIX standard does not define the name of the member in
260 * which the mutex type is stored.
261 * @note The function mutex_type() has been declared inline in order
262 * to avoid that it shows up in call stacks (drd/tests/...exp* files).
bart489de212009-03-13 17:32:52 +0000263 * @note glibc stores the mutex type in the lowest two bits, and uses the
264 * higher bits for flags like PTHREAD_MUTEXATTR_FLAG_ROBUST and
265 * PTHREAD_MUTEXATTR_FLAG_PSHARED.
bart2bc9c102008-09-27 12:40:57 +0000266 */
bart791a0c62009-07-31 17:31:44 +0000267static __always_inline MutexT DRD_(mutex_type)(pthread_mutex_t* mutex)
bart5357fcb2008-02-27 15:46:00 +0000268{
bart5e389f12008-04-05 12:53:15 +0000269#if defined(HAVE_PTHREAD_MUTEX_T__M_KIND)
bartbedfd232009-03-26 19:07:15 +0000270 /* glibc + LinuxThreads. */
bart33f76c12010-09-19 11:14:31 +0000271 if (IS_ALIGNED(&mutex->__m_kind))
272 {
273 const int kind = mutex->__m_kind & 3;
274 return DRD_(pthread_to_drd_mutex_type)(kind);
275 }
bart5e389f12008-04-05 12:53:15 +0000276#elif defined(HAVE_PTHREAD_MUTEX_T__DATA__KIND)
bartbedfd232009-03-26 19:07:15 +0000277 /* glibc + NPTL. */
bart33f76c12010-09-19 11:14:31 +0000278 if (IS_ALIGNED(&mutex->__data.__kind))
279 {
280 const int kind = mutex->__data.__kind & 3;
281 return DRD_(pthread_to_drd_mutex_type)(kind);
282 }
bartadb7a202009-07-21 12:39:25 +0000283#else
284 /*
285 * Another POSIX threads implementation. The mutex type won't be printed
286 * when enabling --trace-mutex=yes.
287 */
bartadb7a202009-07-21 12:39:25 +0000288#endif
bart33f76c12010-09-19 11:14:31 +0000289 return mutex_type_unknown;
bart5357fcb2008-02-27 15:46:00 +0000290}
291
bart227c6592009-02-14 12:12:57 +0000292/**
293 * Tell DRD whether 'tid' is a joinable thread or a detached thread.
294 */
295static void DRD_(set_joinable)(const pthread_t tid, const int joinable)
sewardjaf44c822007-11-25 14:01:38 +0000296{
bartbedfd232009-03-26 19:07:15 +0000297 assert(joinable == 0 || joinable == 1);
bart575ce8e2011-05-15 07:04:03 +0000298 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__SET_JOINABLE,
299 tid, joinable, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000300}
301
bartdd75cdf2009-07-24 08:20:10 +0000302/** Tell DRD that the calling thread is about to enter pthread_create(). */
bart791a0c62009-07-31 17:31:44 +0000303static __always_inline void DRD_(entering_pthread_create)(void)
bartdd75cdf2009-07-24 08:20:10 +0000304{
bart575ce8e2011-05-15 07:04:03 +0000305 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__ENTERING_PTHREAD_CREATE,
306 0, 0, 0, 0, 0);
bartdd75cdf2009-07-24 08:20:10 +0000307}
308
309/** Tell DRD that the calling thread has left pthread_create(). */
bart791a0c62009-07-31 17:31:44 +0000310static __always_inline void DRD_(left_pthread_create)(void)
bartdd75cdf2009-07-24 08:20:10 +0000311{
bart575ce8e2011-05-15 07:04:03 +0000312 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__LEFT_PTHREAD_CREATE,
313 0, 0, 0, 0, 0);
bartdd75cdf2009-07-24 08:20:10 +0000314}
315
bart227c6592009-02-14 12:12:57 +0000316/**
bartdd75cdf2009-07-24 08:20:10 +0000317 * Entry point for newly created threads. This function is called from the
318 * thread created by pthread_create().
bart227c6592009-02-14 12:12:57 +0000319 */
bart292c1e22009-02-14 11:54:42 +0000320static void* DRD_(thread_wrapper)(void* arg)
sewardjaf44c822007-11-25 14:01:38 +0000321{
bartbedfd232009-03-26 19:07:15 +0000322 DrdPosixThreadArgs* arg_ptr;
323 DrdPosixThreadArgs arg_copy;
bart0d063002008-03-01 07:25:13 +0000324
bartbedfd232009-03-26 19:07:15 +0000325 arg_ptr = (DrdPosixThreadArgs*)arg;
326 arg_copy = *arg_ptr;
sewardjaf44c822007-11-25 14:01:38 +0000327
bart575ce8e2011-05-15 07:04:03 +0000328 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__SET_PTHREADID,
329 pthread_self(), 0, 0, 0, 0);
bart227c6592009-02-14 12:12:57 +0000330
bartbedfd232009-03-26 19:07:15 +0000331 DRD_(set_joinable)(pthread_self(),
332 arg_copy.detachstate == PTHREAD_CREATE_JOINABLE);
bart227c6592009-02-14 12:12:57 +0000333
bart8244b862011-03-08 18:34:44 +0000334 /*
335 * Only set 'wrapper_started' after VG_USERREQ__SET_PTHREADID and
336 * DRD_(set_joinable)() have been invoked to avoid a race with
337 * a pthread_detach() invocation for this thread from another thread.
338 */
bart651f56b2011-07-26 19:30:28 +0000339 DRD_(sema_up)(&arg_ptr->wrapper_started);
bart8244b862011-03-08 18:34:44 +0000340
bartbedfd232009-03-26 19:07:15 +0000341 return (arg_copy.start)(arg_copy.arg);
sewardjaf44c822007-11-25 14:01:38 +0000342}
343
bart227c6592009-02-14 12:12:57 +0000344/**
bartd2c5eae2009-02-21 15:27:04 +0000345 * Return 1 if the LinuxThreads implementation of POSIX Threads has been
346 * detected, and 0 otherwise.
347 *
348 * @see For more information about the confstr() function, see also
bart227c6592009-02-14 12:12:57 +0000349 * http://www.opengroup.org/onlinepubs/009695399/functions/confstr.html
350 */
351static int DRD_(detected_linuxthreads)(void)
bart4501d5c2008-03-04 18:36:23 +0000352{
353#if defined(linux)
354#if defined(_CS_GNU_LIBPTHREAD_VERSION)
bartbedfd232009-03-26 19:07:15 +0000355 /* Linux with a recent glibc. */
356 char buffer[256];
357 unsigned len;
358 len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
359 assert(len <= sizeof(buffer));
360 return len > 0 && buffer[0] == 'l';
bart4501d5c2008-03-04 18:36:23 +0000361#else
bartbedfd232009-03-26 19:07:15 +0000362 /* Linux without _CS_GNU_LIBPTHREAD_VERSION: most likely LinuxThreads. */
363 return 1;
bart4501d5c2008-03-04 18:36:23 +0000364#endif
365#else
bartbedfd232009-03-26 19:07:15 +0000366 /* Another OS than Linux, hence no LinuxThreads. */
367 return 0;
bart4501d5c2008-03-04 18:36:23 +0000368#endif
369}
370
bart227c6592009-02-14 12:12:57 +0000371/**
372 * Stop and print an error message in case a non-supported threading
373 * library implementation (LinuxThreads) has been detected.
bart6f07b252008-04-04 16:45:20 +0000374 */
bart227c6592009-02-14 12:12:57 +0000375static void DRD_(check_threading_library)(void)
sewardjaf44c822007-11-25 14:01:38 +0000376{
bartbedfd232009-03-26 19:07:15 +0000377 if (DRD_(detected_linuxthreads)())
378 {
379 if (getenv("LD_ASSUME_KERNEL"))
380 {
381 fprintf(stderr,
bart227c6592009-02-14 12:12:57 +0000382"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
383"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
384"after having unset the environment variable LD_ASSUME_KERNEL. Giving up.\n"
bartbedfd232009-03-26 19:07:15 +0000385);
386 }
387 else
388 {
389 fprintf(stderr,
bart227c6592009-02-14 12:12:57 +0000390"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
391"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
392"after having upgraded to a newer version of your Linux distribution.\n"
393"Giving up.\n"
bartbedfd232009-03-26 19:07:15 +0000394);
395 }
396 abort();
397 }
bart6f07b252008-04-04 16:45:20 +0000398}
399
bart227c6592009-02-14 12:12:57 +0000400/**
401 * The main thread is the only thread not created by pthread_create().
402 * Update DRD's state information about the main thread.
403 */
404static void DRD_(set_main_thread_state)(void)
bart6f07b252008-04-04 16:45:20 +0000405{
bartbedfd232009-03-26 19:07:15 +0000406 // Make sure that DRD knows about the main thread's POSIX thread ID.
bart575ce8e2011-05-15 07:04:03 +0000407 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__SET_PTHREADID,
408 pthread_self(), 0, 0, 0, 0);
bart850f1992010-05-29 18:43:21 +0000409}
sewardjaf44c822007-11-25 14:01:38 +0000410
bartc39d1092009-04-22 18:59:50 +0000411/*
bartdd75cdf2009-07-24 08:20:10 +0000412 * Note: as of today there exist three different versions of pthread_create
413 * in Linux:
bartc39d1092009-04-22 18:59:50 +0000414 * - pthread_create@GLIBC_2.0
415 * - pthread_create@@GLIBC_2.1
416 * - pthread_create@@GLIBC_2.2.5
417 * As an example, in libpthread-2.3.4 both pthread_create@GLIBC_2.0 and
418 * pthread_create@@GLIBC_2.1 are defined, while in libpthread-2.9 all three
419 * versions have been implemented. In any glibc version where more than one
420 * pthread_create function has been implemented, older versions call the
421 * newer versions. Or: the pthread_create* wrapper defined below can be
422 * called recursively. Any code in this wrapper should take this in account.
423 * As an example, it is not safe to invoke the DRD_STOP_RECORDING
424 * / DRD_START_RECORDING client requests from the pthread_create wrapper.
425 * See also the implementation of pthread_create@GLIBC_2.0 in
426 * glibc-2.9/nptl/pthread_create.c.
427 */
428
bartb2260b82011-02-13 07:55:36 +0000429static __always_inline
bart791a0c62009-07-31 17:31:44 +0000430int pthread_create_intercept(pthread_t* thread, const pthread_attr_t* attr,
431 void* (*start)(void*), void* arg)
sewardjaf44c822007-11-25 14:01:38 +0000432{
bartbedfd232009-03-26 19:07:15 +0000433 int ret;
434 OrigFn fn;
bartbedfd232009-03-26 19:07:15 +0000435 DrdPosixThreadArgs thread_args;
sewardjaf44c822007-11-25 14:01:38 +0000436
bartbedfd232009-03-26 19:07:15 +0000437 VALGRIND_GET_ORIG_FN(fn);
sewardjaf44c822007-11-25 14:01:38 +0000438
bartb957ab82011-03-12 11:01:06 +0000439 thread_args.start = start;
440 thread_args.arg = arg;
bart651f56b2011-07-26 19:30:28 +0000441 DRD_(sema_init)(&thread_args.wrapper_started);
bartbedfd232009-03-26 19:07:15 +0000442 /*
443 * Find out whether the thread will be started as a joinable thread
444 * or as a detached thread. If no thread attributes have been specified,
445 * this means that the new thread will be started as a joinable thread.
446 */
bartb957ab82011-03-12 11:01:06 +0000447 thread_args.detachstate = PTHREAD_CREATE_JOINABLE;
bartbedfd232009-03-26 19:07:15 +0000448 if (attr)
449 {
bartb957ab82011-03-12 11:01:06 +0000450 if (pthread_attr_getdetachstate(attr, &thread_args.detachstate) != 0)
bartbedfd232009-03-26 19:07:15 +0000451 assert(0);
bartbedfd232009-03-26 19:07:15 +0000452 }
bartb957ab82011-03-12 11:01:06 +0000453 assert(thread_args.detachstate == PTHREAD_CREATE_JOINABLE
454 || thread_args.detachstate == PTHREAD_CREATE_DETACHED);
bartdd75cdf2009-07-24 08:20:10 +0000455
456 DRD_(entering_pthread_create)();
bartb957ab82011-03-12 11:01:06 +0000457 CALL_FN_W_WWWW(ret, fn, thread, attr, DRD_(thread_wrapper), &thread_args);
bartdd75cdf2009-07-24 08:20:10 +0000458 DRD_(left_pthread_create)();
bart227c6592009-02-14 12:12:57 +0000459
bartbedfd232009-03-26 19:07:15 +0000460 if (ret == 0)
461 {
barte476e922011-03-08 18:32:36 +0000462 /* Wait until the thread wrapper started. */
bart651f56b2011-07-26 19:30:28 +0000463 DRD_(sema_down)(&thread_args.wrapper_started);
bartbedfd232009-03-26 19:07:15 +0000464 }
bart227c6592009-02-14 12:12:57 +0000465
bart651f56b2011-07-26 19:30:28 +0000466 DRD_(sema_destroy)(&thread_args.wrapper_started);
467
bart575ce8e2011-05-15 07:04:03 +0000468 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__DRD_START_NEW_SEGMENT,
469 pthread_self(), 0, 0, 0, 0);
barta0b72222009-03-12 18:39:31 +0000470
bartbedfd232009-03-26 19:07:15 +0000471 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000472}
473
bart791a0c62009-07-31 17:31:44 +0000474PTH_FUNCS(int, pthreadZucreate, pthread_create_intercept,
475 (pthread_t *thread, const pthread_attr_t *attr,
476 void *(*start) (void *), void *arg),
477 (thread, attr, start, arg));
478
bartb2260b82011-02-13 07:55:36 +0000479static __always_inline
bart791a0c62009-07-31 17:31:44 +0000480int pthread_join_intercept(pthread_t pt_joinee, void **thread_return)
sewardjaf44c822007-11-25 14:01:38 +0000481{
bartbedfd232009-03-26 19:07:15 +0000482 int ret;
bartbedfd232009-03-26 19:07:15 +0000483 OrigFn fn;
sewardjaf44c822007-11-25 14:01:38 +0000484
bartbedfd232009-03-26 19:07:15 +0000485 VALGRIND_GET_ORIG_FN(fn);
bart5cbd26e2011-08-24 15:02:21 +0000486 /*
487 * Avoid that the sys_futex(td->tid) call invoked by the NPTL pthread_join()
488 * implementation triggers a (false positive) race report.
489 */
490 ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
bartbedfd232009-03-26 19:07:15 +0000491 CALL_FN_W_WW(ret, fn, pt_joinee, thread_return);
492 if (ret == 0)
493 {
bart575ce8e2011-05-15 07:04:03 +0000494 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_THREAD_JOIN,
495 pt_joinee, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000496 }
bart5cbd26e2011-08-24 15:02:21 +0000497 ANNOTATE_IGNORE_READS_AND_WRITES_END();
bartbedfd232009-03-26 19:07:15 +0000498 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000499}
500
bart791a0c62009-07-31 17:31:44 +0000501PTH_FUNCS(int, pthreadZujoin, pthread_join_intercept,
502 (pthread_t pt_joinee, void **thread_return),
503 (pt_joinee, thread_return));
504
bartb2260b82011-02-13 07:55:36 +0000505static __always_inline
bart791a0c62009-07-31 17:31:44 +0000506int pthread_detach_intercept(pthread_t pt_thread)
sewardjaf44c822007-11-25 14:01:38 +0000507{
bartbedfd232009-03-26 19:07:15 +0000508 int ret;
509 OrigFn fn;
bart5668d4e2011-03-09 17:53:28 +0000510
bartbedfd232009-03-26 19:07:15 +0000511 VALGRIND_GET_ORIG_FN(fn);
bart5668d4e2011-03-09 17:53:28 +0000512 CALL_FN_W_W(ret, fn, pt_thread);
513 DRD_(set_joinable)(pt_thread, 0);
514
bartbedfd232009-03-26 19:07:15 +0000515 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000516}
517
bart791a0c62009-07-31 17:31:44 +0000518PTH_FUNCS(int, pthreadZudetach, pthread_detach_intercept,
519 (pthread_t thread), (thread));
520
521// NOTE: be careful to intercept only pthread_cancel() and not
522// pthread_cancel_init() on Linux.
523
bartb2260b82011-02-13 07:55:36 +0000524static __always_inline
bart791a0c62009-07-31 17:31:44 +0000525int pthread_cancel_intercept(pthread_t pt_thread)
bart2bc9c102008-09-27 12:40:57 +0000526{
bartbedfd232009-03-26 19:07:15 +0000527 int ret;
528 OrigFn fn;
529 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000530 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_THREAD_CANCEL,
531 pt_thread, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000532 CALL_FN_W_W(ret, fn, pt_thread);
bart575ce8e2011-05-15 07:04:03 +0000533 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_THREAD_CANCEL,
534 pt_thread, ret==0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000535 return ret;
bart2bc9c102008-09-27 12:40:57 +0000536}
537
bart791a0c62009-07-31 17:31:44 +0000538PTH_FUNCS(int, pthreadZucancel, pthread_cancel_intercept,
539 (pthread_t thread), (thread))
540
bartb2260b82011-02-13 07:55:36 +0000541static __always_inline
bart791a0c62009-07-31 17:31:44 +0000542int pthread_once_intercept(pthread_once_t *once_control,
543 void (*init_routine)(void))
bart93a02742009-07-26 15:55:48 +0000544{
545 int ret;
546 OrigFn fn;
547 VALGRIND_GET_ORIG_FN(fn);
548 /*
549 * Ignore any data races triggered by the implementation of pthread_once().
550 * Necessary for Darwin. This is not necessary for Linux but doesn't have
551 * any known adverse effects.
552 */
bart554953f2009-07-26 16:21:00 +0000553 DRD_IGNORE_VAR(*once_control);
bart6d956dc2011-07-28 09:54:37 +0000554 ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
bart93a02742009-07-26 15:55:48 +0000555 CALL_FN_W_WW(ret, fn, once_control, init_routine);
bart6d956dc2011-07-28 09:54:37 +0000556 ANNOTATE_IGNORE_READS_AND_WRITES_END();
bart554953f2009-07-26 16:21:00 +0000557 DRD_STOP_IGNORING_VAR(*once_control);
bart93a02742009-07-26 15:55:48 +0000558 return ret;
559}
560
bart791a0c62009-07-31 17:31:44 +0000561PTH_FUNCS(int, pthreadZuonce, pthread_once_intercept,
562 (pthread_once_t *once_control, void (*init_routine)(void)),
563 (once_control, init_routine));
564
bartb2260b82011-02-13 07:55:36 +0000565static __always_inline
bart791a0c62009-07-31 17:31:44 +0000566int pthread_mutex_init_intercept(pthread_mutex_t *mutex,
567 const pthread_mutexattr_t* attr)
sewardjaf44c822007-11-25 14:01:38 +0000568{
bartbedfd232009-03-26 19:07:15 +0000569 int ret;
bartbedfd232009-03-26 19:07:15 +0000570 OrigFn fn;
571 int mt;
572 VALGRIND_GET_ORIG_FN(fn);
573 mt = PTHREAD_MUTEX_DEFAULT;
574 if (attr)
575 pthread_mutexattr_gettype(attr, &mt);
bart575ce8e2011-05-15 07:04:03 +0000576 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_MUTEX_INIT,
577 mutex, DRD_(pthread_to_drd_mutex_type)(mt),
578 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000579 CALL_FN_W_WW(ret, fn, mutex, attr);
bart575ce8e2011-05-15 07:04:03 +0000580 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_MUTEX_INIT,
581 mutex, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000582 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000583}
584
bart791a0c62009-07-31 17:31:44 +0000585PTH_FUNCS(int, pthreadZumutexZuinit, pthread_mutex_init_intercept,
586 (pthread_mutex_t *mutex, const pthread_mutexattr_t* attr),
587 (mutex, attr));
588
bartb2260b82011-02-13 07:55:36 +0000589static __always_inline
bart791a0c62009-07-31 17:31:44 +0000590int pthread_mutex_destroy_intercept(pthread_mutex_t* mutex)
sewardjaf44c822007-11-25 14:01:38 +0000591{
bartbedfd232009-03-26 19:07:15 +0000592 int ret;
bartbedfd232009-03-26 19:07:15 +0000593 OrigFn fn;
594 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000595 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_MUTEX_DESTROY,
596 mutex, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000597 CALL_FN_W_W(ret, fn, mutex);
bart575ce8e2011-05-15 07:04:03 +0000598 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_MUTEX_DESTROY,
599 mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000600 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000601}
602
bart791a0c62009-07-31 17:31:44 +0000603PTH_FUNCS(int, pthreadZumutexZudestroy, pthread_mutex_destroy_intercept,
604 (pthread_mutex_t *mutex), (mutex));
605
bartb2260b82011-02-13 07:55:36 +0000606static __always_inline
bart791a0c62009-07-31 17:31:44 +0000607int pthread_mutex_lock_intercept(pthread_mutex_t* mutex)
sewardjaf44c822007-11-25 14:01:38 +0000608{
bartbedfd232009-03-26 19:07:15 +0000609 int ret;
bartbedfd232009-03-26 19:07:15 +0000610 OrigFn fn;
611 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000612 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__PRE_MUTEX_LOCK,
613 mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000614 CALL_FN_W_W(ret, fn, mutex);
bart575ce8e2011-05-15 07:04:03 +0000615 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__POST_MUTEX_LOCK,
616 mutex, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000617 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000618}
619
bart791a0c62009-07-31 17:31:44 +0000620PTH_FUNCS(int, pthreadZumutexZulock, pthread_mutex_lock_intercept,
621 (pthread_mutex_t *mutex), (mutex));
622
bartb2260b82011-02-13 07:55:36 +0000623static __always_inline
bart791a0c62009-07-31 17:31:44 +0000624int pthread_mutex_trylock_intercept(pthread_mutex_t* mutex)
sewardjaf44c822007-11-25 14:01:38 +0000625{
bartbedfd232009-03-26 19:07:15 +0000626 int ret;
bartbedfd232009-03-26 19:07:15 +0000627 OrigFn fn;
628 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000629 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__PRE_MUTEX_LOCK,
630 mutex, DRD_(mutex_type)(mutex), 1, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000631 CALL_FN_W_W(ret, fn, mutex);
bart575ce8e2011-05-15 07:04:03 +0000632 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_MUTEX_LOCK,
633 mutex, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000634 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000635}
636
bart791a0c62009-07-31 17:31:44 +0000637PTH_FUNCS(int, pthreadZumutexZutrylock, pthread_mutex_trylock_intercept,
638 (pthread_mutex_t *mutex), (mutex));
639
bartb2260b82011-02-13 07:55:36 +0000640static __always_inline
bart791a0c62009-07-31 17:31:44 +0000641int pthread_mutex_timedlock_intercept(pthread_mutex_t *mutex,
642 const struct timespec *abs_timeout)
sewardj85642922008-01-14 11:54:56 +0000643{
bartbedfd232009-03-26 19:07:15 +0000644 int ret;
bartbedfd232009-03-26 19:07:15 +0000645 OrigFn fn;
646 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000647 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__PRE_MUTEX_LOCK,
648 mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000649 CALL_FN_W_WW(ret, fn, mutex, abs_timeout);
bart575ce8e2011-05-15 07:04:03 +0000650 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_MUTEX_LOCK,
651 mutex, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000652 return ret;
sewardj85642922008-01-14 11:54:56 +0000653}
654
bart791a0c62009-07-31 17:31:44 +0000655PTH_FUNCS(int, pthreadZumutexZutimedlock, pthread_mutex_timedlock_intercept,
656 (pthread_mutex_t *mutex, const struct timespec *abs_timeout),
657 (mutex, abs_timeout));
658
bartb2260b82011-02-13 07:55:36 +0000659static __always_inline
bart791a0c62009-07-31 17:31:44 +0000660int pthread_mutex_unlock_intercept(pthread_mutex_t *mutex)
sewardjaf44c822007-11-25 14:01:38 +0000661{
bartbedfd232009-03-26 19:07:15 +0000662 int ret;
bartbedfd232009-03-26 19:07:15 +0000663 OrigFn fn;
664 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000665 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_MUTEX_UNLOCK,
666 mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000667 CALL_FN_W_W(ret, fn, mutex);
bart575ce8e2011-05-15 07:04:03 +0000668 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_MUTEX_UNLOCK,
669 mutex, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000670 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000671}
672
bart791a0c62009-07-31 17:31:44 +0000673PTH_FUNCS(int, pthreadZumutexZuunlock, pthread_mutex_unlock_intercept,
674 (pthread_mutex_t *mutex), (mutex));
675
bartb2260b82011-02-13 07:55:36 +0000676static __always_inline
bart791a0c62009-07-31 17:31:44 +0000677int pthread_cond_init_intercept(pthread_cond_t* cond,
678 const pthread_condattr_t* attr)
sewardjaf44c822007-11-25 14:01:38 +0000679{
bartbedfd232009-03-26 19:07:15 +0000680 int ret;
bartbedfd232009-03-26 19:07:15 +0000681 OrigFn fn;
682 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000683 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_COND_INIT,
684 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000685 CALL_FN_W_WW(ret, fn, cond, attr);
bart575ce8e2011-05-15 07:04:03 +0000686 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_COND_INIT,
687 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000688 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000689}
690
bart791a0c62009-07-31 17:31:44 +0000691PTH_FUNCS(int, pthreadZucondZuinit, pthread_cond_init_intercept,
692 (pthread_cond_t* cond, const pthread_condattr_t* attr),
693 (cond, attr));
694
bartb2260b82011-02-13 07:55:36 +0000695static __always_inline
bart791a0c62009-07-31 17:31:44 +0000696int pthread_cond_destroy_intercept(pthread_cond_t* cond)
sewardjaf44c822007-11-25 14:01:38 +0000697{
bartbedfd232009-03-26 19:07:15 +0000698 int ret;
bartbedfd232009-03-26 19:07:15 +0000699 OrigFn fn;
700 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000701 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_COND_DESTROY,
702 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000703 CALL_FN_W_W(ret, fn, cond);
bart575ce8e2011-05-15 07:04:03 +0000704 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_COND_DESTROY,
705 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000706 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000707}
708
bart791a0c62009-07-31 17:31:44 +0000709PTH_FUNCS(int, pthreadZucondZudestroy, pthread_cond_destroy_intercept,
710 (pthread_cond_t* cond), (cond));
711
bartb2260b82011-02-13 07:55:36 +0000712static __always_inline
bart791a0c62009-07-31 17:31:44 +0000713int pthread_cond_wait_intercept(pthread_cond_t *cond, pthread_mutex_t *mutex)
sewardjaf44c822007-11-25 14:01:38 +0000714{
bartbedfd232009-03-26 19:07:15 +0000715 int ret;
bartbedfd232009-03-26 19:07:15 +0000716 OrigFn fn;
717 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000718 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_COND_WAIT,
719 cond, mutex, DRD_(mutex_type)(mutex), 0, 0);
bartbedfd232009-03-26 19:07:15 +0000720 CALL_FN_W_WW(ret, fn, cond, mutex);
bart575ce8e2011-05-15 07:04:03 +0000721 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_COND_WAIT,
722 cond, mutex, 1, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000723 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000724}
725
bart791a0c62009-07-31 17:31:44 +0000726PTH_FUNCS(int, pthreadZucondZuwait, pthread_cond_wait_intercept,
727 (pthread_cond_t *cond, pthread_mutex_t *mutex),
728 (cond, mutex));
729
bartb2260b82011-02-13 07:55:36 +0000730static __always_inline
bart791a0c62009-07-31 17:31:44 +0000731int pthread_cond_timedwait_intercept(pthread_cond_t *cond,
732 pthread_mutex_t *mutex,
733 const struct timespec* abstime)
sewardjaf44c822007-11-25 14:01:38 +0000734{
bartbedfd232009-03-26 19:07:15 +0000735 int ret;
bartbedfd232009-03-26 19:07:15 +0000736 OrigFn fn;
737 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000738 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_COND_WAIT,
739 cond, mutex, DRD_(mutex_type)(mutex), 0, 0);
bartbedfd232009-03-26 19:07:15 +0000740 CALL_FN_W_WWW(ret, fn, cond, mutex, abstime);
bart575ce8e2011-05-15 07:04:03 +0000741 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_COND_WAIT,
742 cond, mutex, 1, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000743 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000744}
745
bart791a0c62009-07-31 17:31:44 +0000746PTH_FUNCS(int, pthreadZucondZutimedwait, pthread_cond_timedwait_intercept,
747 (pthread_cond_t *cond, pthread_mutex_t *mutex,
748 const struct timespec* abstime),
749 (cond, mutex, abstime));
750
barte8cbb402009-07-22 19:17:05 +0000751// NOTE: be careful to intercept only pthread_cond_signal() and not Darwin's
752// pthread_cond_signal_thread_np(). The former accepts one argument; the latter
753// two. Intercepting all pthread_cond_signal* functions will cause only one
754// argument to be passed to pthread_cond_signal_np() and hence will cause this
755// last function to crash.
756
bartb2260b82011-02-13 07:55:36 +0000757static __always_inline
bart791a0c62009-07-31 17:31:44 +0000758int pthread_cond_signal_intercept(pthread_cond_t* cond)
barte8cbb402009-07-22 19:17:05 +0000759{
760 int ret;
barte8cbb402009-07-22 19:17:05 +0000761 OrigFn fn;
762 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000763 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_COND_SIGNAL,
764 cond, 0, 0, 0, 0);
barte8cbb402009-07-22 19:17:05 +0000765 CALL_FN_W_W(ret, fn, cond);
bart575ce8e2011-05-15 07:04:03 +0000766 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_COND_SIGNAL,
767 cond, 0, 0, 0, 0);
barte8cbb402009-07-22 19:17:05 +0000768 return ret;
769}
770
bart791a0c62009-07-31 17:31:44 +0000771PTH_FUNCS(int, pthreadZucondZusignal, pthread_cond_signal_intercept,
772 (pthread_cond_t* cond), (cond));
sewardjaf44c822007-11-25 14:01:38 +0000773
bartb2260b82011-02-13 07:55:36 +0000774static __always_inline
bart791a0c62009-07-31 17:31:44 +0000775int pthread_cond_broadcast_intercept(pthread_cond_t* cond)
sewardjaf44c822007-11-25 14:01:38 +0000776{
bartbedfd232009-03-26 19:07:15 +0000777 int ret;
bartbedfd232009-03-26 19:07:15 +0000778 OrigFn fn;
779 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000780 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_COND_BROADCAST,
781 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000782 CALL_FN_W_W(ret, fn, cond);
bart575ce8e2011-05-15 07:04:03 +0000783 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_COND_BROADCAST,
784 cond, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000785 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000786}
787
bart791a0c62009-07-31 17:31:44 +0000788PTH_FUNCS(int, pthreadZucondZubroadcast, pthread_cond_broadcast_intercept,
789 (pthread_cond_t* cond), (cond));
sewardjaf44c822007-11-25 14:01:38 +0000790
njnf76d27a2009-05-28 01:53:07 +0000791#if defined(HAVE_PTHREAD_SPIN_LOCK)
bartb2260b82011-02-13 07:55:36 +0000792static __always_inline
bart791a0c62009-07-31 17:31:44 +0000793int pthread_spin_init_intercept(pthread_spinlock_t *spinlock, int pshared)
sewardjaf44c822007-11-25 14:01:38 +0000794{
bartbedfd232009-03-26 19:07:15 +0000795 int ret;
bartbedfd232009-03-26 19:07:15 +0000796 OrigFn fn;
797 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000798 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK,
799 spinlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000800 CALL_FN_W_WW(ret, fn, spinlock, pshared);
bart575ce8e2011-05-15 07:04:03 +0000801 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK,
802 spinlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000803 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000804}
805
bart791a0c62009-07-31 17:31:44 +0000806PTH_FUNCS(int, pthreadZuspinZuinit, pthread_spin_init_intercept,
807 (pthread_spinlock_t *spinlock, int pshared), (spinlock, pshared));
808
bartb2260b82011-02-13 07:55:36 +0000809static __always_inline
bart791a0c62009-07-31 17:31:44 +0000810int pthread_spin_destroy_intercept(pthread_spinlock_t *spinlock)
sewardjaf44c822007-11-25 14:01:38 +0000811{
bartbedfd232009-03-26 19:07:15 +0000812 int ret;
bartbedfd232009-03-26 19:07:15 +0000813 OrigFn fn;
814 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000815 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_MUTEX_DESTROY,
816 spinlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000817 CALL_FN_W_W(ret, fn, spinlock);
bart575ce8e2011-05-15 07:04:03 +0000818 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_MUTEX_DESTROY,
819 spinlock, mutex_type_spinlock, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000820 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000821}
822
bart791a0c62009-07-31 17:31:44 +0000823PTH_FUNCS(int, pthreadZuspinZudestroy, pthread_spin_destroy_intercept,
824 (pthread_spinlock_t *spinlock), (spinlock));
825
bartb2260b82011-02-13 07:55:36 +0000826static __always_inline
bart791a0c62009-07-31 17:31:44 +0000827int pthread_spin_lock_intercept(pthread_spinlock_t *spinlock)
sewardjaf44c822007-11-25 14:01:38 +0000828{
bartbedfd232009-03-26 19:07:15 +0000829 int ret;
bartbedfd232009-03-26 19:07:15 +0000830 OrigFn fn;
831 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000832 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__PRE_MUTEX_LOCK,
833 spinlock, mutex_type_spinlock, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000834 CALL_FN_W_W(ret, fn, spinlock);
bart575ce8e2011-05-15 07:04:03 +0000835 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_MUTEX_LOCK,
836 spinlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000837 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000838}
839
bart791a0c62009-07-31 17:31:44 +0000840PTH_FUNCS(int, pthreadZuspinZulock, pthread_spin_lock_intercept,
841 (pthread_spinlock_t *spinlock), (spinlock));
842
bartb2260b82011-02-13 07:55:36 +0000843static __always_inline
bart791a0c62009-07-31 17:31:44 +0000844int pthread_spin_trylock_intercept(pthread_spinlock_t *spinlock)
sewardjaf44c822007-11-25 14:01:38 +0000845{
bartbedfd232009-03-26 19:07:15 +0000846 int ret;
bartbedfd232009-03-26 19:07:15 +0000847 OrigFn fn;
848 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000849 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__PRE_MUTEX_LOCK,
850 spinlock, mutex_type_spinlock, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000851 CALL_FN_W_W(ret, fn, spinlock);
bart575ce8e2011-05-15 07:04:03 +0000852 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_MUTEX_LOCK,
853 spinlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000854 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000855}
856
bart791a0c62009-07-31 17:31:44 +0000857PTH_FUNCS(int, pthreadZuspinZutrylock, pthread_spin_trylock_intercept,
858 (pthread_spinlock_t *spinlock), (spinlock));
859
bartb2260b82011-02-13 07:55:36 +0000860static __always_inline
bart791a0c62009-07-31 17:31:44 +0000861int pthread_spin_unlock_intercept(pthread_spinlock_t *spinlock)
sewardjaf44c822007-11-25 14:01:38 +0000862{
bartbedfd232009-03-26 19:07:15 +0000863 int ret;
bartbedfd232009-03-26 19:07:15 +0000864 OrigFn fn;
865 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000866 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK,
867 spinlock, mutex_type_spinlock, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000868 CALL_FN_W_W(ret, fn, spinlock);
bart575ce8e2011-05-15 07:04:03 +0000869 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK,
870 spinlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000871 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000872}
bart791a0c62009-07-31 17:31:44 +0000873
874PTH_FUNCS(int, pthreadZuspinZuunlock, pthread_spin_unlock_intercept,
875 (pthread_spinlock_t *spinlock), (spinlock));
njnf76d27a2009-05-28 01:53:07 +0000876#endif // HAVE_PTHREAD_SPIN_LOCK
sewardjaf44c822007-11-25 14:01:38 +0000877
njnf76d27a2009-05-28 01:53:07 +0000878
879#if defined(HAVE_PTHREAD_BARRIER_INIT)
bartb2260b82011-02-13 07:55:36 +0000880static __always_inline
bart791a0c62009-07-31 17:31:44 +0000881int pthread_barrier_init_intercept(pthread_barrier_t* barrier,
882 const pthread_barrierattr_t* attr,
883 unsigned count)
sewardj85642922008-01-14 11:54:56 +0000884{
bartbedfd232009-03-26 19:07:15 +0000885 int ret;
bartbedfd232009-03-26 19:07:15 +0000886 OrigFn fn;
887 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000888 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_BARRIER_INIT,
889 barrier, pthread_barrier, count, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000890 CALL_FN_W_WWW(ret, fn, barrier, attr, count);
bart575ce8e2011-05-15 07:04:03 +0000891 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_BARRIER_INIT,
892 barrier, pthread_barrier, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000893 return ret;
sewardj85642922008-01-14 11:54:56 +0000894}
895
bart791a0c62009-07-31 17:31:44 +0000896PTH_FUNCS(int, pthreadZubarrierZuinit, pthread_barrier_init_intercept,
897 (pthread_barrier_t* barrier, const pthread_barrierattr_t* attr,
898 unsigned count), (barrier, attr, count));
899
bartb2260b82011-02-13 07:55:36 +0000900static __always_inline
bart791a0c62009-07-31 17:31:44 +0000901int pthread_barrier_destroy_intercept(pthread_barrier_t* barrier)
sewardj85642922008-01-14 11:54:56 +0000902{
bartbedfd232009-03-26 19:07:15 +0000903 int ret;
bartbedfd232009-03-26 19:07:15 +0000904 OrigFn fn;
905 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000906 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_BARRIER_DESTROY,
907 barrier, pthread_barrier, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000908 CALL_FN_W_W(ret, fn, barrier);
bart575ce8e2011-05-15 07:04:03 +0000909 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_BARRIER_DESTROY,
910 barrier, pthread_barrier, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000911 return ret;
sewardj85642922008-01-14 11:54:56 +0000912}
913
bart791a0c62009-07-31 17:31:44 +0000914PTH_FUNCS(int, pthreadZubarrierZudestroy, pthread_barrier_destroy_intercept,
915 (pthread_barrier_t* barrier), (barrier));
916
bartb2260b82011-02-13 07:55:36 +0000917static __always_inline
bart791a0c62009-07-31 17:31:44 +0000918int pthread_barrier_wait_intercept(pthread_barrier_t* barrier)
sewardj85642922008-01-14 11:54:56 +0000919{
bartbedfd232009-03-26 19:07:15 +0000920 int ret;
bartbedfd232009-03-26 19:07:15 +0000921 OrigFn fn;
922 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000923 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_BARRIER_WAIT,
924 barrier, pthread_barrier, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000925 CALL_FN_W_W(ret, fn, barrier);
bart575ce8e2011-05-15 07:04:03 +0000926 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_BARRIER_WAIT,
bartbedfd232009-03-26 19:07:15 +0000927 barrier, pthread_barrier,
928 ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD,
929 ret == PTHREAD_BARRIER_SERIAL_THREAD, 0);
930 return ret;
sewardj85642922008-01-14 11:54:56 +0000931}
bart791a0c62009-07-31 17:31:44 +0000932
933PTH_FUNCS(int, pthreadZubarrierZuwait, pthread_barrier_wait_intercept,
934 (pthread_barrier_t* barrier), (barrier));
njnf76d27a2009-05-28 01:53:07 +0000935#endif // HAVE_PTHREAD_BARRIER_INIT
sewardj85642922008-01-14 11:54:56 +0000936
937
bartb2260b82011-02-13 07:55:36 +0000938static __always_inline
bart791a0c62009-07-31 17:31:44 +0000939int sem_init_intercept(sem_t *sem, int pshared, unsigned int value)
sewardj85642922008-01-14 11:54:56 +0000940{
bartbedfd232009-03-26 19:07:15 +0000941 int ret;
bartbedfd232009-03-26 19:07:15 +0000942 OrigFn fn;
943 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000944 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_SEM_INIT,
945 sem, pshared, value, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000946 CALL_FN_W_WWW(ret, fn, sem, pshared, value);
bart575ce8e2011-05-15 07:04:03 +0000947 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_SEM_INIT,
948 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000949 return ret;
sewardj85642922008-01-14 11:54:56 +0000950}
951
bart791a0c62009-07-31 17:31:44 +0000952PTH_FUNCS(int, semZuinit, sem_init_intercept,
953 (sem_t *sem, int pshared, unsigned int value), (sem, pshared, value));
954
bartb2260b82011-02-13 07:55:36 +0000955static __always_inline
bart791a0c62009-07-31 17:31:44 +0000956int sem_destroy_intercept(sem_t *sem)
sewardj85642922008-01-14 11:54:56 +0000957{
bartbedfd232009-03-26 19:07:15 +0000958 int ret;
bartbedfd232009-03-26 19:07:15 +0000959 OrigFn fn;
960 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000961 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_SEM_DESTROY,
962 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000963 CALL_FN_W_W(ret, fn, sem);
bart575ce8e2011-05-15 07:04:03 +0000964 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_SEM_DESTROY,
965 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +0000966 return ret;
sewardj85642922008-01-14 11:54:56 +0000967}
968
bart791a0c62009-07-31 17:31:44 +0000969PTH_FUNCS(int, semZudestroy, sem_destroy_intercept, (sem_t *sem), (sem));
970
bartb2260b82011-02-13 07:55:36 +0000971static __always_inline
bart791a0c62009-07-31 17:31:44 +0000972sem_t* sem_open_intercept(const char *name, int oflag, mode_t mode,
973 unsigned int value)
bart25f9f542009-07-23 16:31:39 +0000974{
975 sem_t *ret;
bart25f9f542009-07-23 16:31:39 +0000976 OrigFn fn;
977 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000978 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_SEM_OPEN,
979 name, oflag, mode, value, 0);
bart25f9f542009-07-23 16:31:39 +0000980 CALL_FN_W_WWWW(ret, fn, name, oflag, mode, value);
bart575ce8e2011-05-15 07:04:03 +0000981 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_SEM_OPEN,
982 ret != SEM_FAILED ? ret : 0,
983 name, oflag, mode, value);
bart25f9f542009-07-23 16:31:39 +0000984 return ret;
985}
986
bart791a0c62009-07-31 17:31:44 +0000987PTH_FUNCS(sem_t *, semZuopen, sem_open_intercept,
988 (const char *name, int oflag, mode_t mode, unsigned int value),
989 (name, oflag, mode, value));
990
bartb2260b82011-02-13 07:55:36 +0000991static __always_inline int sem_close_intercept(sem_t *sem)
bart25f9f542009-07-23 16:31:39 +0000992{
993 int ret;
bart25f9f542009-07-23 16:31:39 +0000994 OrigFn fn;
995 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +0000996 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_SEM_CLOSE,
997 sem, 0, 0, 0, 0);
bart25f9f542009-07-23 16:31:39 +0000998 CALL_FN_W_W(ret, fn, sem);
bart575ce8e2011-05-15 07:04:03 +0000999 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_SEM_CLOSE,
1000 sem, 0, 0, 0, 0);
bart25f9f542009-07-23 16:31:39 +00001001 return ret;
1002}
1003
bart791a0c62009-07-31 17:31:44 +00001004PTH_FUNCS(int, semZuclose, sem_close_intercept, (sem_t *sem), (sem));
1005
bartb2260b82011-02-13 07:55:36 +00001006static __always_inline int sem_wait_intercept(sem_t *sem)
sewardj85642922008-01-14 11:54:56 +00001007{
bartbedfd232009-03-26 19:07:15 +00001008 int ret;
bartbedfd232009-03-26 19:07:15 +00001009 OrigFn fn;
1010 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +00001011 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_SEM_WAIT,
1012 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001013 CALL_FN_W_W(ret, fn, sem);
bart575ce8e2011-05-15 07:04:03 +00001014 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_SEM_WAIT,
1015 sem, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001016 return ret;
sewardj85642922008-01-14 11:54:56 +00001017}
1018
bart791a0c62009-07-31 17:31:44 +00001019PTH_FUNCS(int, semZuwait, sem_wait_intercept, (sem_t *sem), (sem));
1020
bartb2260b82011-02-13 07:55:36 +00001021static __always_inline int sem_trywait_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);
bart575ce8e2011-05-15 07:04:03 +00001026 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_SEM_WAIT,
1027 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001028 CALL_FN_W_W(ret, fn, sem);
bart575ce8e2011-05-15 07:04:03 +00001029 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_SEM_WAIT,
1030 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, semZutrywait, sem_trywait_intercept, (sem_t *sem), (sem));
1035
bartb2260b82011-02-13 07:55:36 +00001036static __always_inline
bart791a0c62009-07-31 17:31:44 +00001037int sem_timedwait_intercept(sem_t *sem, const struct timespec *abs_timeout)
sewardj85642922008-01-14 11:54:56 +00001038{
bartbedfd232009-03-26 19:07:15 +00001039 int ret;
bartbedfd232009-03-26 19:07:15 +00001040 OrigFn fn;
1041 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +00001042 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_SEM_WAIT,
1043 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001044 CALL_FN_W_WW(ret, fn, sem, abs_timeout);
bart575ce8e2011-05-15 07:04:03 +00001045 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_SEM_WAIT,
1046 sem, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001047 return ret;
sewardj85642922008-01-14 11:54:56 +00001048}
1049
bart791a0c62009-07-31 17:31:44 +00001050PTH_FUNCS(int, semZutimedwait, sem_timedwait_intercept,
1051 (sem_t *sem, const struct timespec *abs_timeout),
1052 (sem, abs_timeout));
1053
bartb2260b82011-02-13 07:55:36 +00001054static __always_inline int sem_post_intercept(sem_t *sem)
sewardj85642922008-01-14 11:54:56 +00001055{
bartbedfd232009-03-26 19:07:15 +00001056 int ret;
bartbedfd232009-03-26 19:07:15 +00001057 OrigFn fn;
1058 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +00001059 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_SEM_POST,
1060 sem, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001061 CALL_FN_W_W(ret, fn, sem);
bart575ce8e2011-05-15 07:04:03 +00001062 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_SEM_POST,
1063 sem, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001064 return ret;
sewardj85642922008-01-14 11:54:56 +00001065}
1066
bart791a0c62009-07-31 17:31:44 +00001067PTH_FUNCS(int, semZupost, sem_post_intercept, (sem_t *sem), (sem));
1068
sewardj0c09bf02011-07-11 22:11:58 +00001069/* Android's pthread.h doesn't say anything about rwlocks, hence these
1070 functions have to be conditionally compiled. */
1071#if defined(HAVE_PTHREAD_RWLOCK_T)
1072
bartb2260b82011-02-13 07:55:36 +00001073static __always_inline
bart791a0c62009-07-31 17:31:44 +00001074int pthread_rwlock_init_intercept(pthread_rwlock_t* rwlock,
1075 const pthread_rwlockattr_t* attr)
bart00344642008-03-01 15:27:41 +00001076{
bartbedfd232009-03-26 19:07:15 +00001077 int ret;
bartbedfd232009-03-26 19:07:15 +00001078 OrigFn fn;
1079 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +00001080 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_RWLOCK_INIT,
1081 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001082 CALL_FN_W_WW(ret, fn, rwlock, attr);
1083 return ret;
bart00344642008-03-01 15:27:41 +00001084}
1085
bart791a0c62009-07-31 17:31:44 +00001086PTH_FUNCS(int,
1087 pthreadZurwlockZuinit, pthread_rwlock_init_intercept,
1088 (pthread_rwlock_t* rwlock, const pthread_rwlockattr_t* attr),
1089 (rwlock, attr));
1090
bartb2260b82011-02-13 07:55:36 +00001091static __always_inline
bart791a0c62009-07-31 17:31:44 +00001092int pthread_rwlock_destroy_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001093{
bartbedfd232009-03-26 19:07:15 +00001094 int ret;
bartbedfd232009-03-26 19:07:15 +00001095 OrigFn fn;
1096 VALGRIND_GET_ORIG_FN(fn);
1097 CALL_FN_W_W(ret, fn, rwlock);
bart575ce8e2011-05-15 07:04:03 +00001098 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_RWLOCK_DESTROY,
1099 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001100 return ret;
bart00344642008-03-01 15:27:41 +00001101}
1102
bart791a0c62009-07-31 17:31:44 +00001103PTH_FUNCS(int,
1104 pthreadZurwlockZudestroy, pthread_rwlock_destroy_intercept,
1105 (pthread_rwlock_t* rwlock), (rwlock));
1106
bartb2260b82011-02-13 07:55:36 +00001107static __always_inline
bart791a0c62009-07-31 17:31:44 +00001108int pthread_rwlock_rdlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001109{
bartbedfd232009-03-26 19:07:15 +00001110 int ret;
bartbedfd232009-03-26 19:07:15 +00001111 OrigFn fn;
1112 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +00001113 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
1114 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001115 CALL_FN_W_W(ret, fn, rwlock);
bart575ce8e2011-05-15 07:04:03 +00001116 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_RWLOCK_RDLOCK,
1117 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001118 return ret;
bart00344642008-03-01 15:27:41 +00001119}
1120
bart791a0c62009-07-31 17:31:44 +00001121PTH_FUNCS(int,
1122 pthreadZurwlockZurdlock, pthread_rwlock_rdlock_intercept,
1123 (pthread_rwlock_t* rwlock), (rwlock));
1124
bartb2260b82011-02-13 07:55:36 +00001125static __always_inline
bart791a0c62009-07-31 17:31:44 +00001126int pthread_rwlock_wrlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001127{
bartbedfd232009-03-26 19:07:15 +00001128 int ret;
bartbedfd232009-03-26 19:07:15 +00001129 OrigFn fn;
1130 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +00001131 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
1132 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001133 CALL_FN_W_W(ret, fn, rwlock);
bart575ce8e2011-05-15 07:04:03 +00001134 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_RWLOCK_WRLOCK,
1135 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001136 return ret;
bart00344642008-03-01 15:27:41 +00001137}
1138
bart791a0c62009-07-31 17:31:44 +00001139PTH_FUNCS(int,
1140 pthreadZurwlockZuwrlock, pthread_rwlock_wrlock_intercept,
1141 (pthread_rwlock_t* rwlock), (rwlock));
1142
bartb2260b82011-02-13 07:55:36 +00001143static __always_inline
bart791a0c62009-07-31 17:31:44 +00001144int pthread_rwlock_timedrdlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001145{
bartbedfd232009-03-26 19:07:15 +00001146 int ret;
bartbedfd232009-03-26 19:07:15 +00001147 OrigFn fn;
1148 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +00001149 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
1150 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001151 CALL_FN_W_W(ret, fn, rwlock);
bart575ce8e2011-05-15 07:04:03 +00001152 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_RWLOCK_RDLOCK,
1153 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001154 return ret;
bart00344642008-03-01 15:27:41 +00001155}
1156
bart791a0c62009-07-31 17:31:44 +00001157PTH_FUNCS(int,
1158 pthreadZurwlockZutimedrdlock, pthread_rwlock_timedrdlock_intercept,
1159 (pthread_rwlock_t* rwlock), (rwlock));
1160
bartb2260b82011-02-13 07:55:36 +00001161static __always_inline
bart791a0c62009-07-31 17:31:44 +00001162int pthread_rwlock_timedwrlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001163{
bartbedfd232009-03-26 19:07:15 +00001164 int ret;
bartbedfd232009-03-26 19:07:15 +00001165 OrigFn fn;
1166 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +00001167 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
1168 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001169 CALL_FN_W_W(ret, fn, rwlock);
bart575ce8e2011-05-15 07:04:03 +00001170 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_RWLOCK_WRLOCK,
1171 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001172 return ret;
bart00344642008-03-01 15:27:41 +00001173}
1174
bart791a0c62009-07-31 17:31:44 +00001175PTH_FUNCS(int,
1176 pthreadZurwlockZutimedwrlock, pthread_rwlock_timedwrlock_intercept,
1177 (pthread_rwlock_t* rwlock), (rwlock));
1178
bartb2260b82011-02-13 07:55:36 +00001179static __always_inline
bart791a0c62009-07-31 17:31:44 +00001180int pthread_rwlock_tryrdlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001181{
bartbedfd232009-03-26 19:07:15 +00001182 int ret;
bartbedfd232009-03-26 19:07:15 +00001183 OrigFn fn;
1184 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +00001185 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
1186 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001187 CALL_FN_W_W(ret, fn, rwlock);
bart575ce8e2011-05-15 07:04:03 +00001188 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_RWLOCK_RDLOCK,
1189 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001190 return ret;
bart00344642008-03-01 15:27:41 +00001191}
1192
bart791a0c62009-07-31 17:31:44 +00001193PTH_FUNCS(int,
1194 pthreadZurwlockZutryrdlock, pthread_rwlock_tryrdlock_intercept,
1195 (pthread_rwlock_t* rwlock), (rwlock));
1196
bartb2260b82011-02-13 07:55:36 +00001197static __always_inline
bart791a0c62009-07-31 17:31:44 +00001198int pthread_rwlock_trywrlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001199{
bartbedfd232009-03-26 19:07:15 +00001200 int ret;
bartbedfd232009-03-26 19:07:15 +00001201 OrigFn fn;
1202 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +00001203 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
1204 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001205 CALL_FN_W_W(ret, fn, rwlock);
bart575ce8e2011-05-15 07:04:03 +00001206 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_RWLOCK_WRLOCK,
1207 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001208 return ret;
bart00344642008-03-01 15:27:41 +00001209}
1210
bart791a0c62009-07-31 17:31:44 +00001211PTH_FUNCS(int,
1212 pthreadZurwlockZutrywrlock, pthread_rwlock_trywrlock_intercept,
1213 (pthread_rwlock_t* rwlock), (rwlock));
1214
bartb2260b82011-02-13 07:55:36 +00001215static __always_inline
bart791a0c62009-07-31 17:31:44 +00001216int pthread_rwlock_unlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001217{
bartbedfd232009-03-26 19:07:15 +00001218 int ret;
bartbedfd232009-03-26 19:07:15 +00001219 OrigFn fn;
1220 VALGRIND_GET_ORIG_FN(fn);
bart575ce8e2011-05-15 07:04:03 +00001221 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__PRE_RWLOCK_UNLOCK,
1222 rwlock, 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001223 CALL_FN_W_W(ret, fn, rwlock);
bart575ce8e2011-05-15 07:04:03 +00001224 VALGRIND_DO_CLIENT_REQUEST_EXPR(-1, VG_USERREQ__POST_RWLOCK_UNLOCK,
1225 rwlock, ret == 0, 0, 0, 0);
bartbedfd232009-03-26 19:07:15 +00001226 return ret;
bart00344642008-03-01 15:27:41 +00001227}
bart791a0c62009-07-31 17:31:44 +00001228
1229PTH_FUNCS(int,
1230 pthreadZurwlockZuunlock, pthread_rwlock_unlock_intercept,
1231 (pthread_rwlock_t* rwlock), (rwlock));
sewardj0c09bf02011-07-11 22:11:58 +00001232
1233#endif /* defined(HAVE_PTHREAD_RWLOCK_T) */