blob: c494db1bccd59345b4f4a11d32902307de19de68 [file] [log] [blame]
bartbedfd232009-03-26 19:07:15 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
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
bart227c6592009-02-14 12:12:57 +000010 Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>.
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() */
52#include <pthread.h> /* pthread_mutex_t */
53#include <semaphore.h> /* sem_t */
54#include <stdio.h> /* fprintf() */
55#include <stdlib.h> /* malloc(), free() */
56#include <unistd.h> /* confstr() */
57#include "config.h" /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP etc. */
58#include "drd_basics.h" /* DRD_() */
sewardjaf44c822007-11-25 14:01:38 +000059#include "drd_clientreq.h"
bart227c6592009-02-14 12:12:57 +000060#include "pub_tool_redir.h" /* VG_WRAP_FUNCTION_ZZ() */
sewardjaf44c822007-11-25 14:01:38 +000061
62
bart227c6592009-02-14 12:12:57 +000063/* Defines. */
sewardjaf44c822007-11-25 14:01:38 +000064
barta0b72222009-03-12 18:39:31 +000065/*
66 * Do not undefine the two macro's below, or the following two subtle race
67 * conditions will be introduced in the data race detection algorithm:
68 * - sg_init() runs on the context of the created thread and copies the
69 * vector clock of the creator thread. This only works reliably if
70 * the creator thread waits until this copy has been performed.
71 * - Since DRD_(thread_compute_minimum_vc)() does not take the vector
72 * clocks into account that are involved in thread creation but
73 * for which the corresponding thread has not yet been created, by
74 * undefining the macro below it becomes possible that segments get
75 * discarded that should not yet be discarded. Or: some data races
76 * are not detected.
77 */
78#define WAIT_UNTIL_CREATED_THREAD_STARTED
79#define ALLOCATE_THREAD_ARGS_ON_THE_STACK
80
bart791a0c62009-07-31 17:31:44 +000081/**
82 * Macro for generating a Valgrind interception function.
83 * @param[in] ret_ty Return type of the function to be generated.
84 * @param[in] zf Z-encoded name of the interception function.
85 * @param[in] implf Name of the function that implements the intercept.
86 * @param[in] arg_decl Argument declaration list enclosed in parentheses.
87 * @param[in] argl Argument list enclosed in parentheses.
88 */
89#define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl) \
90 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl; \
91 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl \
92 { return implf argl; }
sewardjaf44c822007-11-25 14:01:38 +000093
bart791a0c62009-07-31 17:31:44 +000094/**
95 * Macro for generating three Valgrind interception functions: one with the
96 * Z-encoded name zf, one with ZAZa ("@*") appended to the name zf and one
97 * with ZDZa ("$*") appended to the name zf. The second generated interception
98 * function will intercept versioned symbols on Linux, and the third will
99 * intercept versioned symbols on Darwin.
100 */
101#define PTH_FUNCS(ret_ty, zf, implf, argl_decl, argl) \
102 PTH_FUNC(ret_ty, zf, implf, argl_decl, argl); \
103 PTH_FUNC(ret_ty, zf ## ZAZa, implf, argl_decl, argl); \
104 PTH_FUNC(ret_ty, zf ## ZDZa, implf, argl_decl, argl);
105
106/*
107 * Not inlining one of the intercept functions will cause the regression
108 * tests to fail because this would cause an additional stackfram to appear
109 * in the output. The __always_inline macro guarantees that inlining will
110 * happen, even when compiling with optimization disabled.
111 */
112#undef __always_inline /* since already defined in <cdefs.h> */
bart4f66a772009-07-31 17:59:28 +0000113#if __GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 2
bart791a0c62009-07-31 17:31:44 +0000114#define __always_inline __inline__ __attribute__((always_inline))
115#else
116#define __always_inline __inline__
117#endif
sewardjaf44c822007-11-25 14:01:38 +0000118
bart6f07b252008-04-04 16:45:20 +0000119/* Local data structures. */
sewardjaf44c822007-11-25 14:01:38 +0000120
121typedef struct
122{
bartbedfd232009-03-26 19:07:15 +0000123 void* (*start)(void*);
124 void* arg;
125 int detachstate;
barta0b72222009-03-12 18:39:31 +0000126#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED)
bartbedfd232009-03-26 19:07:15 +0000127 int wrapper_started;
barta0b72222009-03-12 18:39:31 +0000128#endif
barta764b372009-02-15 10:40:44 +0000129} DrdPosixThreadArgs;
sewardjaf44c822007-11-25 14:01:38 +0000130
131
bart227c6592009-02-14 12:12:57 +0000132/* Local function declarations. */
sewardjaf44c822007-11-25 14:01:38 +0000133
bart227c6592009-02-14 12:12:57 +0000134static void DRD_(init)(void) __attribute__((constructor));
135static void DRD_(check_threading_library)(void);
136static void DRD_(set_main_thread_state)(void);
sewardjaf44c822007-11-25 14:01:38 +0000137
138
bart6f07b252008-04-04 16:45:20 +0000139/* Function definitions. */
140
bart227c6592009-02-14 12:12:57 +0000141/**
142 * Shared library initialization function. The function init() is called after
143 * dlopen() has loaded the shared library with DRD client intercepts because
144 * the constructor attribute was specified in the declaration of this function.
145 * Note: do specify the -nostdlib option to gcc when linking this code into a
146 * shared library because doing so would cancel the effect of the constructor
147 * attribute ! Using the gcc option -nodefaultlibs is fine because this last
148 * option preserves the shared library initialization code that calls
149 * constructor and destructor functions.
bart6f07b252008-04-04 16:45:20 +0000150 */
bart227c6592009-02-14 12:12:57 +0000151static void DRD_(init)(void)
bart6f07b252008-04-04 16:45:20 +0000152{
bartbedfd232009-03-26 19:07:15 +0000153 DRD_(check_threading_library)();
154 DRD_(set_main_thread_state)();
bart6f07b252008-04-04 16:45:20 +0000155}
sewardjaf44c822007-11-25 14:01:38 +0000156
bart227c6592009-02-14 12:12:57 +0000157/**
158 * POSIX threads and DRD each have their own mutex type identification.
159 * Convert POSIX threads' mutex type to DRD's mutex type. In the code below
160 * if-statements are used to test the value of 'kind' instead of a switch
161 * statement because some of the PTHREAD_MUTEX_ macro's may have the same
162 * value.
163 */
164static MutexT DRD_(pthread_to_drd_mutex_type)(const int kind)
bart5357fcb2008-02-27 15:46:00 +0000165{
bartbedfd232009-03-26 19:07:15 +0000166 if (kind == PTHREAD_MUTEX_RECURSIVE)
167 return mutex_type_recursive_mutex;
168 else if (kind == PTHREAD_MUTEX_ERRORCHECK)
169 return mutex_type_errorcheck_mutex;
170 else if (kind == PTHREAD_MUTEX_NORMAL)
171 return mutex_type_default_mutex;
172 else if (kind == PTHREAD_MUTEX_DEFAULT)
173 return mutex_type_default_mutex;
bart227c6592009-02-14 12:12:57 +0000174#if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP)
bartbedfd232009-03-26 19:07:15 +0000175 else if (kind == PTHREAD_MUTEX_ADAPTIVE_NP)
176 return mutex_type_default_mutex;
bart227c6592009-02-14 12:12:57 +0000177#endif
bartbedfd232009-03-26 19:07:15 +0000178 else
179 {
180 return mutex_type_invalid_mutex;
181 }
bart5357fcb2008-02-27 15:46:00 +0000182}
183
bart227c6592009-02-14 12:12:57 +0000184/**
185 * Read the mutex type stored in the client memory used for the mutex
186 * implementation.
187 *
188 * @note This function depends on the implementation of the POSIX threads
189 * library -- the POSIX standard does not define the name of the member in
190 * which the mutex type is stored.
191 * @note The function mutex_type() has been declared inline in order
192 * to avoid that it shows up in call stacks (drd/tests/...exp* files).
bart489de212009-03-13 17:32:52 +0000193 * @note glibc stores the mutex type in the lowest two bits, and uses the
194 * higher bits for flags like PTHREAD_MUTEXATTR_FLAG_ROBUST and
195 * PTHREAD_MUTEXATTR_FLAG_PSHARED.
bart2bc9c102008-09-27 12:40:57 +0000196 */
bart791a0c62009-07-31 17:31:44 +0000197static __always_inline MutexT DRD_(mutex_type)(pthread_mutex_t* mutex)
bart5357fcb2008-02-27 15:46:00 +0000198{
bart5e389f12008-04-05 12:53:15 +0000199#if defined(HAVE_PTHREAD_MUTEX_T__M_KIND)
bartbedfd232009-03-26 19:07:15 +0000200 /* glibc + LinuxThreads. */
201 const int kind = mutex->__m_kind & 3;
bartadb7a202009-07-21 12:39:25 +0000202 return DRD_(pthread_to_drd_mutex_type)(kind);
bart5e389f12008-04-05 12:53:15 +0000203#elif defined(HAVE_PTHREAD_MUTEX_T__DATA__KIND)
bartbedfd232009-03-26 19:07:15 +0000204 /* glibc + NPTL. */
205 const int kind = mutex->__data.__kind & 3;
bartbedfd232009-03-26 19:07:15 +0000206 return DRD_(pthread_to_drd_mutex_type)(kind);
bartadb7a202009-07-21 12:39:25 +0000207#else
208 /*
209 * Another POSIX threads implementation. The mutex type won't be printed
210 * when enabling --trace-mutex=yes.
211 */
212 return mutex_type_unknown;
213#endif
bart5357fcb2008-02-27 15:46:00 +0000214}
215
bart227c6592009-02-14 12:12:57 +0000216/**
217 * Tell DRD whether 'tid' is a joinable thread or a detached thread.
218 */
219static void DRD_(set_joinable)(const pthread_t tid, const int joinable)
sewardjaf44c822007-11-25 14:01:38 +0000220{
bartbedfd232009-03-26 19:07:15 +0000221 int res;
222 assert(joinable == 0 || joinable == 1);
223 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__SET_JOINABLE,
224 tid, joinable, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000225}
226
bartdd75cdf2009-07-24 08:20:10 +0000227/** Tell DRD that the calling thread is about to enter pthread_create(). */
bart791a0c62009-07-31 17:31:44 +0000228static __always_inline void DRD_(entering_pthread_create)(void)
bartdd75cdf2009-07-24 08:20:10 +0000229{
230 int res;
231 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__ENTERING_PTHREAD_CREATE,
232 0, 0, 0, 0, 0);
233}
234
235/** Tell DRD that the calling thread has left pthread_create(). */
bart791a0c62009-07-31 17:31:44 +0000236static __always_inline void DRD_(left_pthread_create)(void)
bartdd75cdf2009-07-24 08:20:10 +0000237{
238 int res;
239 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__LEFT_PTHREAD_CREATE,
240 0, 0, 0, 0, 0);
241}
242
bart227c6592009-02-14 12:12:57 +0000243/**
bartdd75cdf2009-07-24 08:20:10 +0000244 * Entry point for newly created threads. This function is called from the
245 * thread created by pthread_create().
bart227c6592009-02-14 12:12:57 +0000246 */
bart292c1e22009-02-14 11:54:42 +0000247static void* DRD_(thread_wrapper)(void* arg)
sewardjaf44c822007-11-25 14:01:38 +0000248{
bartbedfd232009-03-26 19:07:15 +0000249 int res;
250 DrdPosixThreadArgs* arg_ptr;
251 DrdPosixThreadArgs arg_copy;
bart0d063002008-03-01 07:25:13 +0000252
bartbedfd232009-03-26 19:07:15 +0000253 arg_ptr = (DrdPosixThreadArgs*)arg;
254 arg_copy = *arg_ptr;
barta0b72222009-03-12 18:39:31 +0000255#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED)
bartbedfd232009-03-26 19:07:15 +0000256 arg_ptr->wrapper_started = 1;
barta0b72222009-03-12 18:39:31 +0000257#else
258#if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK)
bartbedfd232009-03-26 19:07:15 +0000259#error Defining ALLOCATE_THREAD_ARGS_ON_THE_STACK but not \
260 WAIT_UNTIL_CREATED_THREAD_STARTED is not supported.
barta0b72222009-03-12 18:39:31 +0000261#else
bartbedfd232009-03-26 19:07:15 +0000262 free(arg_ptr);
barta0b72222009-03-12 18:39:31 +0000263#endif
264#endif
sewardjaf44c822007-11-25 14:01:38 +0000265
bartbedfd232009-03-26 19:07:15 +0000266 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
267 pthread_self(), 0, 0, 0, 0);
bart227c6592009-02-14 12:12:57 +0000268
bartbedfd232009-03-26 19:07:15 +0000269 DRD_(set_joinable)(pthread_self(),
270 arg_copy.detachstate == PTHREAD_CREATE_JOINABLE);
bart227c6592009-02-14 12:12:57 +0000271
bartbedfd232009-03-26 19:07:15 +0000272 return (arg_copy.start)(arg_copy.arg);
sewardjaf44c822007-11-25 14:01:38 +0000273}
274
bart227c6592009-02-14 12:12:57 +0000275/**
bartd2c5eae2009-02-21 15:27:04 +0000276 * Return 1 if the LinuxThreads implementation of POSIX Threads has been
277 * detected, and 0 otherwise.
278 *
279 * @see For more information about the confstr() function, see also
bart227c6592009-02-14 12:12:57 +0000280 * http://www.opengroup.org/onlinepubs/009695399/functions/confstr.html
281 */
282static int DRD_(detected_linuxthreads)(void)
bart4501d5c2008-03-04 18:36:23 +0000283{
284#if defined(linux)
285#if defined(_CS_GNU_LIBPTHREAD_VERSION)
bartbedfd232009-03-26 19:07:15 +0000286 /* Linux with a recent glibc. */
287 char buffer[256];
288 unsigned len;
289 len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
290 assert(len <= sizeof(buffer));
291 return len > 0 && buffer[0] == 'l';
bart4501d5c2008-03-04 18:36:23 +0000292#else
bartbedfd232009-03-26 19:07:15 +0000293 /* Linux without _CS_GNU_LIBPTHREAD_VERSION: most likely LinuxThreads. */
294 return 1;
bart4501d5c2008-03-04 18:36:23 +0000295#endif
296#else
bartbedfd232009-03-26 19:07:15 +0000297 /* Another OS than Linux, hence no LinuxThreads. */
298 return 0;
bart4501d5c2008-03-04 18:36:23 +0000299#endif
300}
301
bart227c6592009-02-14 12:12:57 +0000302/**
303 * Stop and print an error message in case a non-supported threading
304 * library implementation (LinuxThreads) has been detected.
bart6f07b252008-04-04 16:45:20 +0000305 */
bart227c6592009-02-14 12:12:57 +0000306static void DRD_(check_threading_library)(void)
sewardjaf44c822007-11-25 14:01:38 +0000307{
bartbedfd232009-03-26 19:07:15 +0000308 if (DRD_(detected_linuxthreads)())
309 {
310 if (getenv("LD_ASSUME_KERNEL"))
311 {
312 fprintf(stderr,
bart227c6592009-02-14 12:12:57 +0000313"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
314"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
315"after having unset the environment variable LD_ASSUME_KERNEL. Giving up.\n"
bartbedfd232009-03-26 19:07:15 +0000316);
317 }
318 else
319 {
320 fprintf(stderr,
bart227c6592009-02-14 12:12:57 +0000321"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
322"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
323"after having upgraded to a newer version of your Linux distribution.\n"
324"Giving up.\n"
bartbedfd232009-03-26 19:07:15 +0000325);
326 }
327 abort();
328 }
bart6f07b252008-04-04 16:45:20 +0000329}
330
bart227c6592009-02-14 12:12:57 +0000331/**
332 * The main thread is the only thread not created by pthread_create().
333 * Update DRD's state information about the main thread.
334 */
335static void DRD_(set_main_thread_state)(void)
bart6f07b252008-04-04 16:45:20 +0000336{
bartbedfd232009-03-26 19:07:15 +0000337 int res;
bart0d063002008-03-01 07:25:13 +0000338
bartbedfd232009-03-26 19:07:15 +0000339 // Make sure that DRD knows about the main thread's POSIX thread ID.
340 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
341 pthread_self(), 0, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000342
343}
344
bartc39d1092009-04-22 18:59:50 +0000345
346/*
bartdd75cdf2009-07-24 08:20:10 +0000347 * Note: as of today there exist three different versions of pthread_create
348 * in Linux:
bartc39d1092009-04-22 18:59:50 +0000349 * - pthread_create@GLIBC_2.0
350 * - pthread_create@@GLIBC_2.1
351 * - pthread_create@@GLIBC_2.2.5
352 * As an example, in libpthread-2.3.4 both pthread_create@GLIBC_2.0 and
353 * pthread_create@@GLIBC_2.1 are defined, while in libpthread-2.9 all three
354 * versions have been implemented. In any glibc version where more than one
355 * pthread_create function has been implemented, older versions call the
356 * newer versions. Or: the pthread_create* wrapper defined below can be
357 * called recursively. Any code in this wrapper should take this in account.
358 * As an example, it is not safe to invoke the DRD_STOP_RECORDING
359 * / DRD_START_RECORDING client requests from the pthread_create wrapper.
360 * See also the implementation of pthread_create@GLIBC_2.0 in
361 * glibc-2.9/nptl/pthread_create.c.
362 */
363
bart791a0c62009-07-31 17:31:44 +0000364static __always_inline
365int pthread_create_intercept(pthread_t* thread, const pthread_attr_t* attr,
366 void* (*start)(void*), void* arg)
sewardjaf44c822007-11-25 14:01:38 +0000367{
bartbedfd232009-03-26 19:07:15 +0000368 int res;
369 int ret;
370 OrigFn fn;
barta0b72222009-03-12 18:39:31 +0000371#if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK)
bartbedfd232009-03-26 19:07:15 +0000372 DrdPosixThreadArgs thread_args;
barta0b72222009-03-12 18:39:31 +0000373#endif
bartbedfd232009-03-26 19:07:15 +0000374 DrdPosixThreadArgs* thread_args_p;
sewardjaf44c822007-11-25 14:01:38 +0000375
bartbedfd232009-03-26 19:07:15 +0000376 VALGRIND_GET_ORIG_FN(fn);
sewardjaf44c822007-11-25 14:01:38 +0000377
barta0b72222009-03-12 18:39:31 +0000378#if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK)
bartbedfd232009-03-26 19:07:15 +0000379 thread_args_p = &thread_args;
barta0b72222009-03-12 18:39:31 +0000380#else
bartbedfd232009-03-26 19:07:15 +0000381 thread_args_p = malloc(sizeof(*thread_args_p));
barta0b72222009-03-12 18:39:31 +0000382#endif
bartbedfd232009-03-26 19:07:15 +0000383 assert(thread_args_p);
barta0b72222009-03-12 18:39:31 +0000384
bartbedfd232009-03-26 19:07:15 +0000385 thread_args_p->start = start;
386 thread_args_p->arg = arg;
barta0b72222009-03-12 18:39:31 +0000387#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED)
bartbedfd232009-03-26 19:07:15 +0000388 DRD_IGNORE_VAR(thread_args_p->wrapper_started);
389 thread_args_p->wrapper_started = 0;
barta0b72222009-03-12 18:39:31 +0000390#endif
bartbedfd232009-03-26 19:07:15 +0000391 /*
392 * Find out whether the thread will be started as a joinable thread
393 * or as a detached thread. If no thread attributes have been specified,
394 * this means that the new thread will be started as a joinable thread.
395 */
396 thread_args_p->detachstate = PTHREAD_CREATE_JOINABLE;
397 if (attr)
398 {
399 if (pthread_attr_getdetachstate(attr, &thread_args_p->detachstate) != 0)
400 {
401 assert(0);
402 }
403 }
404 assert(thread_args_p->detachstate == PTHREAD_CREATE_JOINABLE
405 || thread_args_p->detachstate == PTHREAD_CREATE_DETACHED);
bart227c6592009-02-14 12:12:57 +0000406
bartdd75cdf2009-07-24 08:20:10 +0000407
408 DRD_(entering_pthread_create)();
bartbedfd232009-03-26 19:07:15 +0000409 CALL_FN_W_WWWW(ret, fn, thread, attr, DRD_(thread_wrapper), thread_args_p);
bartdd75cdf2009-07-24 08:20:10 +0000410 DRD_(left_pthread_create)();
bart227c6592009-02-14 12:12:57 +0000411
barta0b72222009-03-12 18:39:31 +0000412#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED)
bartbedfd232009-03-26 19:07:15 +0000413 if (ret == 0)
414 {
415 /*
416 * Wait until the thread wrapper started.
417 * @todo Find out why some regression tests fail if thread arguments are
418 * passed via dynamically allocated memory and if the loop below is
419 * removed.
420 */
421 while (! thread_args_p->wrapper_started)
422 {
423 sched_yield();
424 }
425 }
bart227c6592009-02-14 12:12:57 +0000426
barta0b72222009-03-12 18:39:31 +0000427#if defined(ALLOCATE_THREAD_ARGS_DYNAMICALLY)
bartbedfd232009-03-26 19:07:15 +0000428 free(thread_args_p);
barta0b72222009-03-12 18:39:31 +0000429#endif
430
431#endif
432
bartbedfd232009-03-26 19:07:15 +0000433 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_START_NEW_SEGMENT,
434 pthread_self(), 0, 0, 0, 0);
barta0b72222009-03-12 18:39:31 +0000435
bartbedfd232009-03-26 19:07:15 +0000436 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000437}
438
bart791a0c62009-07-31 17:31:44 +0000439PTH_FUNCS(int, pthreadZucreate, pthread_create_intercept,
440 (pthread_t *thread, const pthread_attr_t *attr,
441 void *(*start) (void *), void *arg),
442 (thread, attr, start, arg));
443
444static __always_inline
445int pthread_join_intercept(pthread_t pt_joinee, void **thread_return)
sewardjaf44c822007-11-25 14:01:38 +0000446{
bartbedfd232009-03-26 19:07:15 +0000447 int ret;
448 int res;
449 OrigFn fn;
sewardjaf44c822007-11-25 14:01:38 +0000450
bartbedfd232009-03-26 19:07:15 +0000451 VALGRIND_GET_ORIG_FN(fn);
452 CALL_FN_W_WW(ret, fn, pt_joinee, thread_return);
453 if (ret == 0)
454 {
455 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_JOIN,
456 pt_joinee, 0, 0, 0, 0);
457 }
458 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000459}
460
bart791a0c62009-07-31 17:31:44 +0000461PTH_FUNCS(int, pthreadZujoin, pthread_join_intercept,
462 (pthread_t pt_joinee, void **thread_return),
463 (pt_joinee, thread_return));
464
465static __always_inline
466int pthread_detach_intercept(pthread_t pt_thread)
sewardjaf44c822007-11-25 14:01:38 +0000467{
bartbedfd232009-03-26 19:07:15 +0000468 int ret;
469 OrigFn fn;
470 VALGRIND_GET_ORIG_FN(fn);
471 {
472 CALL_FN_W_W(ret, fn, pt_thread);
473 if (ret == 0)
474 {
475 DRD_(set_joinable)(pt_thread, 0);
476 }
477 }
478 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000479}
480
bart791a0c62009-07-31 17:31:44 +0000481PTH_FUNCS(int, pthreadZudetach, pthread_detach_intercept,
482 (pthread_t thread), (thread));
483
484// NOTE: be careful to intercept only pthread_cancel() and not
485// pthread_cancel_init() on Linux.
486
487static __always_inline
488int pthread_cancel_intercept(pthread_t pt_thread)
bart2bc9c102008-09-27 12:40:57 +0000489{
bartbedfd232009-03-26 19:07:15 +0000490 int res;
491 int ret;
492 OrigFn fn;
493 VALGRIND_GET_ORIG_FN(fn);
494 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_THREAD_CANCEL,
495 pt_thread, 0, 0, 0, 0);
496 CALL_FN_W_W(ret, fn, pt_thread);
497 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_CANCEL,
498 pt_thread, ret==0, 0, 0, 0);
499 return ret;
bart2bc9c102008-09-27 12:40:57 +0000500}
501
bart791a0c62009-07-31 17:31:44 +0000502PTH_FUNCS(int, pthreadZucancel, pthread_cancel_intercept,
503 (pthread_t thread), (thread))
504
505static __always_inline
506int pthread_once_intercept(pthread_once_t *once_control,
507 void (*init_routine)(void))
bart93a02742009-07-26 15:55:48 +0000508{
509 int ret;
510 OrigFn fn;
511 VALGRIND_GET_ORIG_FN(fn);
512 /*
513 * Ignore any data races triggered by the implementation of pthread_once().
514 * Necessary for Darwin. This is not necessary for Linux but doesn't have
515 * any known adverse effects.
516 */
bart554953f2009-07-26 16:21:00 +0000517 DRD_IGNORE_VAR(*once_control);
bart93a02742009-07-26 15:55:48 +0000518 CALL_FN_W_WW(ret, fn, once_control, init_routine);
bart554953f2009-07-26 16:21:00 +0000519 DRD_STOP_IGNORING_VAR(*once_control);
bart93a02742009-07-26 15:55:48 +0000520 return ret;
521}
522
bart791a0c62009-07-31 17:31:44 +0000523PTH_FUNCS(int, pthreadZuonce, pthread_once_intercept,
524 (pthread_once_t *once_control, void (*init_routine)(void)),
525 (once_control, init_routine));
526
527static __always_inline
528int pthread_mutex_init_intercept(pthread_mutex_t *mutex,
529 const pthread_mutexattr_t* attr)
sewardjaf44c822007-11-25 14:01:38 +0000530{
bartbedfd232009-03-26 19:07:15 +0000531 int ret;
532 int res;
533 OrigFn fn;
534 int mt;
535 VALGRIND_GET_ORIG_FN(fn);
536 mt = PTHREAD_MUTEX_DEFAULT;
537 if (attr)
538 pthread_mutexattr_gettype(attr, &mt);
539 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT,
540 mutex, DRD_(pthread_to_drd_mutex_type)(mt),
541 0, 0, 0);
542 CALL_FN_W_WW(ret, fn, mutex, attr);
543 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT,
544 mutex, 0, 0, 0, 0);
545 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000546}
547
bart791a0c62009-07-31 17:31:44 +0000548PTH_FUNCS(int, pthreadZumutexZuinit, pthread_mutex_init_intercept,
549 (pthread_mutex_t *mutex, const pthread_mutexattr_t* attr),
550 (mutex, attr));
551
552static __always_inline
553int pthread_mutex_destroy_intercept(pthread_mutex_t* mutex)
sewardjaf44c822007-11-25 14:01:38 +0000554{
bartbedfd232009-03-26 19:07:15 +0000555 int ret;
556 int res;
557 OrigFn fn;
558 VALGRIND_GET_ORIG_FN(fn);
559 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY,
560 mutex, 0, 0, 0, 0);
561 CALL_FN_W_W(ret, fn, mutex);
562 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
563 mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
564 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000565}
566
bart791a0c62009-07-31 17:31:44 +0000567PTH_FUNCS(int, pthreadZumutexZudestroy, pthread_mutex_destroy_intercept,
568 (pthread_mutex_t *mutex), (mutex));
569
570static __always_inline
571int pthread_mutex_lock_intercept(pthread_mutex_t* mutex)
sewardjaf44c822007-11-25 14:01:38 +0000572{
bartbedfd232009-03-26 19:07:15 +0000573 int ret;
574 int res;
575 OrigFn fn;
576 VALGRIND_GET_ORIG_FN(fn);
577 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
578 mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
579 CALL_FN_W_W(ret, fn, mutex);
580 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_MUTEX_LOCK,
581 mutex, ret == 0, 0, 0, 0);
582 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000583}
584
bart791a0c62009-07-31 17:31:44 +0000585PTH_FUNCS(int, pthreadZumutexZulock, pthread_mutex_lock_intercept,
586 (pthread_mutex_t *mutex), (mutex));
587
588static __always_inline
589int pthread_mutex_trylock_intercept(pthread_mutex_t* mutex)
sewardjaf44c822007-11-25 14:01:38 +0000590{
bartbedfd232009-03-26 19:07:15 +0000591 int ret;
592 int res;
593 OrigFn fn;
594 VALGRIND_GET_ORIG_FN(fn);
595 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
596 mutex, DRD_(mutex_type)(mutex), 1, 0, 0);
597 CALL_FN_W_W(ret, fn, mutex);
598 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK,
599 mutex, ret == 0, 0, 0, 0);
600 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000601}
602
bart791a0c62009-07-31 17:31:44 +0000603PTH_FUNCS(int, pthreadZumutexZutrylock, pthread_mutex_trylock_intercept,
604 (pthread_mutex_t *mutex), (mutex));
605
606static __always_inline
607int pthread_mutex_timedlock_intercept(pthread_mutex_t *mutex,
608 const struct timespec *abs_timeout)
sewardj85642922008-01-14 11:54:56 +0000609{
bartbedfd232009-03-26 19:07:15 +0000610 int ret;
611 int res;
612 OrigFn fn;
613 VALGRIND_GET_ORIG_FN(fn);
614 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
615 mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
616 CALL_FN_W_WW(ret, fn, mutex, abs_timeout);
617 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK,
618 mutex, ret == 0, 0, 0, 0);
619 return ret;
sewardj85642922008-01-14 11:54:56 +0000620}
621
bart791a0c62009-07-31 17:31:44 +0000622PTH_FUNCS(int, pthreadZumutexZutimedlock, pthread_mutex_timedlock_intercept,
623 (pthread_mutex_t *mutex, const struct timespec *abs_timeout),
624 (mutex, abs_timeout));
625
626static __always_inline
627int pthread_mutex_unlock_intercept(pthread_mutex_t *mutex)
sewardjaf44c822007-11-25 14:01:38 +0000628{
bartbedfd232009-03-26 19:07:15 +0000629 int ret;
630 int res;
631 OrigFn fn;
632 VALGRIND_GET_ORIG_FN(fn);
633 VALGRIND_DO_CLIENT_REQUEST(res, -1,
634 VG_USERREQ__PRE_MUTEX_UNLOCK,
635 mutex, DRD_(mutex_type)(mutex), 0, 0, 0);
636 CALL_FN_W_W(ret, fn, mutex);
637 VALGRIND_DO_CLIENT_REQUEST(res, -1,
638 VG_USERREQ__POST_MUTEX_UNLOCK,
639 mutex, 0, 0, 0, 0);
640 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000641}
642
bart791a0c62009-07-31 17:31:44 +0000643PTH_FUNCS(int, pthreadZumutexZuunlock, pthread_mutex_unlock_intercept,
644 (pthread_mutex_t *mutex), (mutex));
645
646static __always_inline
647int pthread_cond_init_intercept(pthread_cond_t* cond,
648 const pthread_condattr_t* attr)
sewardjaf44c822007-11-25 14:01:38 +0000649{
bartbedfd232009-03-26 19:07:15 +0000650 int ret;
651 int res;
652 OrigFn fn;
653 VALGRIND_GET_ORIG_FN(fn);
654 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_INIT,
655 cond, 0, 0, 0, 0);
656 CALL_FN_W_WW(ret, fn, cond, attr);
657 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_INIT,
658 cond, 0, 0, 0, 0);
659 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000660}
661
bart791a0c62009-07-31 17:31:44 +0000662PTH_FUNCS(int, pthreadZucondZuinit, pthread_cond_init_intercept,
663 (pthread_cond_t* cond, const pthread_condattr_t* attr),
664 (cond, attr));
665
666static __always_inline
667int pthread_cond_destroy_intercept(pthread_cond_t* cond)
sewardjaf44c822007-11-25 14:01:38 +0000668{
bartbedfd232009-03-26 19:07:15 +0000669 int ret;
670 int res;
671 OrigFn fn;
672 VALGRIND_GET_ORIG_FN(fn);
673 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_DESTROY,
674 cond, 0, 0, 0, 0);
675 CALL_FN_W_W(ret, fn, cond);
676 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_DESTROY,
677 cond, 0, 0, 0, 0);
678 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000679}
680
bart791a0c62009-07-31 17:31:44 +0000681PTH_FUNCS(int, pthreadZucondZudestroy, pthread_cond_destroy_intercept,
682 (pthread_cond_t* cond), (cond));
683
684static __always_inline
685int pthread_cond_wait_intercept(pthread_cond_t *cond, pthread_mutex_t *mutex)
sewardjaf44c822007-11-25 14:01:38 +0000686{
bartbedfd232009-03-26 19:07:15 +0000687 int ret;
688 int res;
689 OrigFn fn;
690 VALGRIND_GET_ORIG_FN(fn);
691 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_WAIT,
692 cond, mutex, DRD_(mutex_type)(mutex), 0, 0);
693 CALL_FN_W_WW(ret, fn, cond, mutex);
694 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT,
695 cond, mutex, 1, 0, 0);
696 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000697}
698
bart791a0c62009-07-31 17:31:44 +0000699PTH_FUNCS(int, pthreadZucondZuwait, pthread_cond_wait_intercept,
700 (pthread_cond_t *cond, pthread_mutex_t *mutex),
701 (cond, mutex));
702
703static __always_inline
704int pthread_cond_timedwait_intercept(pthread_cond_t *cond,
705 pthread_mutex_t *mutex,
706 const struct timespec* abstime)
sewardjaf44c822007-11-25 14:01:38 +0000707{
bartbedfd232009-03-26 19:07:15 +0000708 int ret;
709 int res;
710 OrigFn fn;
711 VALGRIND_GET_ORIG_FN(fn);
712 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_WAIT,
713 cond, mutex, DRD_(mutex_type)(mutex), 0, 0);
714 CALL_FN_W_WWW(ret, fn, cond, mutex, abstime);
715 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT,
716 cond, mutex, 1, 0, 0);
717 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000718}
719
bart791a0c62009-07-31 17:31:44 +0000720PTH_FUNCS(int, pthreadZucondZutimedwait, pthread_cond_timedwait_intercept,
721 (pthread_cond_t *cond, pthread_mutex_t *mutex,
722 const struct timespec* abstime),
723 (cond, mutex, abstime));
724
barte8cbb402009-07-22 19:17:05 +0000725// NOTE: be careful to intercept only pthread_cond_signal() and not Darwin's
726// pthread_cond_signal_thread_np(). The former accepts one argument; the latter
727// two. Intercepting all pthread_cond_signal* functions will cause only one
728// argument to be passed to pthread_cond_signal_np() and hence will cause this
729// last function to crash.
730
bart791a0c62009-07-31 17:31:44 +0000731static __always_inline
732int pthread_cond_signal_intercept(pthread_cond_t* cond)
barte8cbb402009-07-22 19:17:05 +0000733{
734 int ret;
735 int res;
736 OrigFn fn;
737 VALGRIND_GET_ORIG_FN(fn);
738 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_SIGNAL,
739 cond, 0, 0, 0, 0);
740 CALL_FN_W_W(ret, fn, cond);
741 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_SIGNAL,
742 cond, 0, 0, 0, 0);
743 return ret;
744}
745
bart791a0c62009-07-31 17:31:44 +0000746PTH_FUNCS(int, pthreadZucondZusignal, pthread_cond_signal_intercept,
747 (pthread_cond_t* cond), (cond));
sewardjaf44c822007-11-25 14:01:38 +0000748
bart791a0c62009-07-31 17:31:44 +0000749static __always_inline
750int pthread_cond_broadcast_intercept(pthread_cond_t* cond)
sewardjaf44c822007-11-25 14:01:38 +0000751{
bartbedfd232009-03-26 19:07:15 +0000752 int ret;
753 int res;
754 OrigFn fn;
755 VALGRIND_GET_ORIG_FN(fn);
756 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_BROADCAST,
757 cond, 0, 0, 0, 0);
758 CALL_FN_W_W(ret, fn, cond);
759 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_BROADCAST,
760 cond, 0, 0, 0, 0);
761 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000762}
763
bart791a0c62009-07-31 17:31:44 +0000764PTH_FUNCS(int, pthreadZucondZubroadcast, pthread_cond_broadcast_intercept,
765 (pthread_cond_t* cond), (cond));
sewardjaf44c822007-11-25 14:01:38 +0000766
njnf76d27a2009-05-28 01:53:07 +0000767#if defined(HAVE_PTHREAD_SPIN_LOCK)
bart791a0c62009-07-31 17:31:44 +0000768static __always_inline
769int pthread_spin_init_intercept(pthread_spinlock_t *spinlock, int pshared)
sewardjaf44c822007-11-25 14:01:38 +0000770{
bartbedfd232009-03-26 19:07:15 +0000771 int ret;
772 int res;
773 OrigFn fn;
774 VALGRIND_GET_ORIG_FN(fn);
775 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK,
776 spinlock, 0, 0, 0, 0);
777 CALL_FN_W_WW(ret, fn, spinlock, pshared);
778 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK,
779 spinlock, 0, 0, 0, 0);
780 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000781}
782
bart791a0c62009-07-31 17:31:44 +0000783PTH_FUNCS(int, pthreadZuspinZuinit, pthread_spin_init_intercept,
784 (pthread_spinlock_t *spinlock, int pshared), (spinlock, pshared));
785
786static __always_inline
787int pthread_spin_destroy_intercept(pthread_spinlock_t *spinlock)
sewardjaf44c822007-11-25 14:01:38 +0000788{
bartbedfd232009-03-26 19:07:15 +0000789 int ret;
790 int res;
791 OrigFn fn;
792 VALGRIND_GET_ORIG_FN(fn);
793 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY,
794 spinlock, 0, 0, 0, 0);
795 CALL_FN_W_W(ret, fn, spinlock);
796 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
797 spinlock, mutex_type_spinlock, 0, 0, 0);
798 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000799}
800
bart791a0c62009-07-31 17:31:44 +0000801PTH_FUNCS(int, pthreadZuspinZudestroy, pthread_spin_destroy_intercept,
802 (pthread_spinlock_t *spinlock), (spinlock));
803
804static __always_inline
805int pthread_spin_lock_intercept(pthread_spinlock_t *spinlock)
sewardjaf44c822007-11-25 14:01:38 +0000806{
bartbedfd232009-03-26 19:07:15 +0000807 int ret;
808 int res;
809 OrigFn fn;
810 VALGRIND_GET_ORIG_FN(fn);
811 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
812 spinlock, mutex_type_spinlock, 0, 0, 0);
813 CALL_FN_W_W(ret, fn, spinlock);
814 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK,
815 spinlock, ret == 0, 0, 0, 0);
816 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000817}
818
bart791a0c62009-07-31 17:31:44 +0000819PTH_FUNCS(int, pthreadZuspinZulock, pthread_spin_lock_intercept,
820 (pthread_spinlock_t *spinlock), (spinlock));
821
822static __always_inline
823int pthread_spin_trylock_intercept(pthread_spinlock_t *spinlock)
sewardjaf44c822007-11-25 14:01:38 +0000824{
bartbedfd232009-03-26 19:07:15 +0000825 int ret;
826 int res;
827 OrigFn fn;
828 VALGRIND_GET_ORIG_FN(fn);
829 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
830 spinlock, mutex_type_spinlock, 0, 0, 0);
831 CALL_FN_W_W(ret, fn, spinlock);
832 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK,
833 spinlock, ret == 0, 0, 0, 0);
834 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000835}
836
bart791a0c62009-07-31 17:31:44 +0000837PTH_FUNCS(int, pthreadZuspinZutrylock, pthread_spin_trylock_intercept,
838 (pthread_spinlock_t *spinlock), (spinlock));
839
840static __always_inline
841int pthread_spin_unlock_intercept(pthread_spinlock_t *spinlock)
sewardjaf44c822007-11-25 14:01:38 +0000842{
bartbedfd232009-03-26 19:07:15 +0000843 int ret;
844 int res;
845 OrigFn fn;
846 VALGRIND_GET_ORIG_FN(fn);
847 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK,
848 spinlock, mutex_type_spinlock, 0, 0, 0);
849 CALL_FN_W_W(ret, fn, spinlock);
850 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK,
851 spinlock, 0, 0, 0, 0);
852 return ret;
sewardjaf44c822007-11-25 14:01:38 +0000853}
bart791a0c62009-07-31 17:31:44 +0000854
855PTH_FUNCS(int, pthreadZuspinZuunlock, pthread_spin_unlock_intercept,
856 (pthread_spinlock_t *spinlock), (spinlock));
njnf76d27a2009-05-28 01:53:07 +0000857#endif // HAVE_PTHREAD_SPIN_LOCK
sewardjaf44c822007-11-25 14:01:38 +0000858
njnf76d27a2009-05-28 01:53:07 +0000859
860#if defined(HAVE_PTHREAD_BARRIER_INIT)
bart791a0c62009-07-31 17:31:44 +0000861static __always_inline
862int pthread_barrier_init_intercept(pthread_barrier_t* barrier,
863 const pthread_barrierattr_t* attr,
864 unsigned count)
sewardj85642922008-01-14 11:54:56 +0000865{
bartbedfd232009-03-26 19:07:15 +0000866 int ret;
867 int res;
868 OrigFn fn;
869 VALGRIND_GET_ORIG_FN(fn);
870 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_INIT,
871 barrier, pthread_barrier, count, 0, 0);
872 CALL_FN_W_WWW(ret, fn, barrier, attr, count);
873 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_INIT,
874 barrier, pthread_barrier, 0, 0, 0);
875 return ret;
sewardj85642922008-01-14 11:54:56 +0000876}
877
bart791a0c62009-07-31 17:31:44 +0000878PTH_FUNCS(int, pthreadZubarrierZuinit, pthread_barrier_init_intercept,
879 (pthread_barrier_t* barrier, const pthread_barrierattr_t* attr,
880 unsigned count), (barrier, attr, count));
881
882static __always_inline
883int pthread_barrier_destroy_intercept(pthread_barrier_t* barrier)
sewardj85642922008-01-14 11:54:56 +0000884{
bartbedfd232009-03-26 19:07:15 +0000885 int ret;
886 int res;
887 OrigFn fn;
888 VALGRIND_GET_ORIG_FN(fn);
889 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_DESTROY,
890 barrier, pthread_barrier, 0, 0, 0);
891 CALL_FN_W_W(ret, fn, barrier);
892 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_DESTROY,
893 barrier, pthread_barrier, 0, 0, 0);
894 return ret;
sewardj85642922008-01-14 11:54:56 +0000895}
896
bart791a0c62009-07-31 17:31:44 +0000897PTH_FUNCS(int, pthreadZubarrierZudestroy, pthread_barrier_destroy_intercept,
898 (pthread_barrier_t* barrier), (barrier));
899
900static __always_inline
901int pthread_barrier_wait_intercept(pthread_barrier_t* barrier)
sewardj85642922008-01-14 11:54:56 +0000902{
bartbedfd232009-03-26 19:07:15 +0000903 int ret;
904 int res;
905 OrigFn fn;
906 VALGRIND_GET_ORIG_FN(fn);
907 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT,
908 barrier, pthread_barrier, 0, 0, 0);
909 CALL_FN_W_W(ret, fn, barrier);
910 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT,
911 barrier, pthread_barrier,
912 ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD,
913 ret == PTHREAD_BARRIER_SERIAL_THREAD, 0);
914 return ret;
sewardj85642922008-01-14 11:54:56 +0000915}
bart791a0c62009-07-31 17:31:44 +0000916
917PTH_FUNCS(int, pthreadZubarrierZuwait, pthread_barrier_wait_intercept,
918 (pthread_barrier_t* barrier), (barrier));
njnf76d27a2009-05-28 01:53:07 +0000919#endif // HAVE_PTHREAD_BARRIER_INIT
sewardj85642922008-01-14 11:54:56 +0000920
921
bart791a0c62009-07-31 17:31:44 +0000922static __always_inline
923int sem_init_intercept(sem_t *sem, int pshared, unsigned int value)
sewardj85642922008-01-14 11:54:56 +0000924{
bartbedfd232009-03-26 19:07:15 +0000925 int ret;
926 int res;
927 OrigFn fn;
928 VALGRIND_GET_ORIG_FN(fn);
929 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_INIT,
930 sem, pshared, value, 0, 0);
931 CALL_FN_W_WWW(ret, fn, sem, pshared, value);
932 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_INIT,
933 sem, 0, 0, 0, 0);
934 return ret;
sewardj85642922008-01-14 11:54:56 +0000935}
936
bart791a0c62009-07-31 17:31:44 +0000937PTH_FUNCS(int, semZuinit, sem_init_intercept,
938 (sem_t *sem, int pshared, unsigned int value), (sem, pshared, value));
939
940static __always_inline
941int sem_destroy_intercept(sem_t *sem)
sewardj85642922008-01-14 11:54:56 +0000942{
bartbedfd232009-03-26 19:07:15 +0000943 int ret;
944 int res;
945 OrigFn fn;
946 VALGRIND_GET_ORIG_FN(fn);
947 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_DESTROY,
948 sem, 0, 0, 0, 0);
949 CALL_FN_W_W(ret, fn, sem);
950 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_DESTROY,
951 sem, 0, 0, 0, 0);
952 return ret;
sewardj85642922008-01-14 11:54:56 +0000953}
954
bart791a0c62009-07-31 17:31:44 +0000955PTH_FUNCS(int, semZudestroy, sem_destroy_intercept, (sem_t *sem), (sem));
956
957static __always_inline
958sem_t* sem_open_intercept(const char *name, int oflag, mode_t mode,
959 unsigned int value)
bart25f9f542009-07-23 16:31:39 +0000960{
961 sem_t *ret;
962 int res;
963 OrigFn fn;
964 VALGRIND_GET_ORIG_FN(fn);
965 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_OPEN,
966 name, oflag, mode, value, 0);
967 CALL_FN_W_WWWW(ret, fn, name, oflag, mode, value);
968 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_OPEN,
969 ret != SEM_FAILED ? ret : 0,
970 name, oflag, mode, value);
971 return ret;
972}
973
bart791a0c62009-07-31 17:31:44 +0000974PTH_FUNCS(sem_t *, semZuopen, sem_open_intercept,
975 (const char *name, int oflag, mode_t mode, unsigned int value),
976 (name, oflag, mode, value));
977
978static __always_inline int sem_close_intercept(sem_t *sem)
bart25f9f542009-07-23 16:31:39 +0000979{
980 int ret;
981 int res;
982 OrigFn fn;
983 VALGRIND_GET_ORIG_FN(fn);
984 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_CLOSE,
985 sem, 0, 0, 0, 0);
986 CALL_FN_W_W(ret, fn, sem);
987 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_CLOSE,
988 sem, 0, 0, 0, 0);
989 return ret;
990}
991
bart791a0c62009-07-31 17:31:44 +0000992PTH_FUNCS(int, semZuclose, sem_close_intercept, (sem_t *sem), (sem));
993
994static __always_inline int sem_wait_intercept(sem_t *sem)
sewardj85642922008-01-14 11:54:56 +0000995{
bartbedfd232009-03-26 19:07:15 +0000996 int ret;
997 int res;
998 OrigFn fn;
999 VALGRIND_GET_ORIG_FN(fn);
1000 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
1001 sem, 0, 0, 0, 0);
1002 CALL_FN_W_W(ret, fn, sem);
1003 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
1004 sem, ret == 0, 0, 0, 0);
1005 return ret;
sewardj85642922008-01-14 11:54:56 +00001006}
1007
bart791a0c62009-07-31 17:31:44 +00001008PTH_FUNCS(int, semZuwait, sem_wait_intercept, (sem_t *sem), (sem));
1009
1010static __always_inline int sem_trywait_intercept(sem_t *sem)
sewardj85642922008-01-14 11:54:56 +00001011{
bartbedfd232009-03-26 19:07:15 +00001012 int ret;
1013 int res;
1014 OrigFn fn;
1015 VALGRIND_GET_ORIG_FN(fn);
1016 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
1017 sem, 0, 0, 0, 0);
1018 CALL_FN_W_W(ret, fn, sem);
1019 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
1020 sem, ret == 0, 0, 0, 0);
1021 return ret;
sewardj85642922008-01-14 11:54:56 +00001022}
1023
bart791a0c62009-07-31 17:31:44 +00001024PTH_FUNCS(int, semZutrywait, sem_trywait_intercept, (sem_t *sem), (sem));
1025
1026static __always_inline
1027int sem_timedwait_intercept(sem_t *sem, const struct timespec *abs_timeout)
sewardj85642922008-01-14 11:54:56 +00001028{
bartbedfd232009-03-26 19:07:15 +00001029 int ret;
1030 int res;
1031 OrigFn fn;
1032 VALGRIND_GET_ORIG_FN(fn);
1033 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
1034 sem, 0, 0, 0, 0);
1035 CALL_FN_W_WW(ret, fn, sem, abs_timeout);
1036 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
1037 sem, ret == 0, 0, 0, 0);
1038 return ret;
sewardj85642922008-01-14 11:54:56 +00001039}
1040
bart791a0c62009-07-31 17:31:44 +00001041PTH_FUNCS(int, semZutimedwait, sem_timedwait_intercept,
1042 (sem_t *sem, const struct timespec *abs_timeout),
1043 (sem, abs_timeout));
1044
1045static __always_inline int sem_post_intercept(sem_t *sem)
sewardj85642922008-01-14 11:54:56 +00001046{
bartbedfd232009-03-26 19:07:15 +00001047 int ret;
1048 int res;
1049 OrigFn fn;
1050 VALGRIND_GET_ORIG_FN(fn);
1051 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST,
1052 sem, 0, 0, 0, 0);
1053 CALL_FN_W_W(ret, fn, sem);
1054 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST,
1055 sem, ret == 0, 0, 0, 0);
1056 return ret;
sewardj85642922008-01-14 11:54:56 +00001057}
1058
bart791a0c62009-07-31 17:31:44 +00001059PTH_FUNCS(int, semZupost, sem_post_intercept, (sem_t *sem), (sem));
1060
1061static __always_inline
1062int pthread_rwlock_init_intercept(pthread_rwlock_t* rwlock,
1063 const pthread_rwlockattr_t* attr)
bart00344642008-03-01 15:27:41 +00001064{
bartbedfd232009-03-26 19:07:15 +00001065 int ret;
1066 int res;
1067 OrigFn fn;
1068 VALGRIND_GET_ORIG_FN(fn);
1069 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_INIT,
1070 rwlock, 0, 0, 0, 0);
1071 CALL_FN_W_WW(ret, fn, rwlock, attr);
1072 return ret;
bart00344642008-03-01 15:27:41 +00001073}
1074
bart791a0c62009-07-31 17:31:44 +00001075PTH_FUNCS(int,
1076 pthreadZurwlockZuinit, pthread_rwlock_init_intercept,
1077 (pthread_rwlock_t* rwlock, const pthread_rwlockattr_t* attr),
1078 (rwlock, attr));
1079
1080static __always_inline
1081int pthread_rwlock_destroy_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001082{
bartbedfd232009-03-26 19:07:15 +00001083 int ret;
1084 int res;
1085 OrigFn fn;
1086 VALGRIND_GET_ORIG_FN(fn);
1087 CALL_FN_W_W(ret, fn, rwlock);
1088 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_DESTROY,
1089 rwlock, 0, 0, 0, 0);
1090 return ret;
bart00344642008-03-01 15:27:41 +00001091}
1092
bart791a0c62009-07-31 17:31:44 +00001093PTH_FUNCS(int,
1094 pthreadZurwlockZudestroy, pthread_rwlock_destroy_intercept,
1095 (pthread_rwlock_t* rwlock), (rwlock));
1096
1097static __always_inline
1098int pthread_rwlock_rdlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001099{
bartbedfd232009-03-26 19:07:15 +00001100 int ret;
1101 int res;
1102 OrigFn fn;
1103 VALGRIND_GET_ORIG_FN(fn);
1104 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
1105 rwlock, 0, 0, 0, 0);
1106 CALL_FN_W_W(ret, fn, rwlock);
1107 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK,
1108 rwlock, ret == 0, 0, 0, 0);
1109 return ret;
bart00344642008-03-01 15:27:41 +00001110}
1111
bart791a0c62009-07-31 17:31:44 +00001112PTH_FUNCS(int,
1113 pthreadZurwlockZurdlock, pthread_rwlock_rdlock_intercept,
1114 (pthread_rwlock_t* rwlock), (rwlock));
1115
1116static __always_inline
1117int pthread_rwlock_wrlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001118{
bartbedfd232009-03-26 19:07:15 +00001119 int ret;
1120 int res;
1121 OrigFn fn;
1122 VALGRIND_GET_ORIG_FN(fn);
1123 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
1124 rwlock, 0, 0, 0, 0);
1125 CALL_FN_W_W(ret, fn, rwlock);
1126 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK,
1127 rwlock, ret == 0, 0, 0, 0);
1128 return ret;
bart00344642008-03-01 15:27:41 +00001129}
1130
bart791a0c62009-07-31 17:31:44 +00001131PTH_FUNCS(int,
1132 pthreadZurwlockZuwrlock, pthread_rwlock_wrlock_intercept,
1133 (pthread_rwlock_t* rwlock), (rwlock));
1134
1135static __always_inline
1136int pthread_rwlock_timedrdlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001137{
bartbedfd232009-03-26 19:07:15 +00001138 int ret;
1139 int res;
1140 OrigFn fn;
1141 VALGRIND_GET_ORIG_FN(fn);
1142 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
1143 rwlock, 0, 0, 0, 0);
1144 CALL_FN_W_W(ret, fn, rwlock);
1145 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK,
1146 rwlock, ret == 0, 0, 0, 0);
1147 return ret;
bart00344642008-03-01 15:27:41 +00001148}
1149
bart791a0c62009-07-31 17:31:44 +00001150PTH_FUNCS(int,
1151 pthreadZurwlockZutimedrdlock, pthread_rwlock_timedrdlock_intercept,
1152 (pthread_rwlock_t* rwlock), (rwlock));
1153
1154static __always_inline
1155int pthread_rwlock_timedwrlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001156{
bartbedfd232009-03-26 19:07:15 +00001157 int ret;
1158 int res;
1159 OrigFn fn;
1160 VALGRIND_GET_ORIG_FN(fn);
1161 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
1162 rwlock, 0, 0, 0, 0);
1163 CALL_FN_W_W(ret, fn, rwlock);
1164 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK,
1165 rwlock, ret == 0, 0, 0, 0);
1166 return ret;
bart00344642008-03-01 15:27:41 +00001167}
1168
bart791a0c62009-07-31 17:31:44 +00001169PTH_FUNCS(int,
1170 pthreadZurwlockZutimedwrlock, pthread_rwlock_timedwrlock_intercept,
1171 (pthread_rwlock_t* rwlock), (rwlock));
1172
1173static __always_inline
1174int pthread_rwlock_tryrdlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001175{
bartbedfd232009-03-26 19:07:15 +00001176 int ret;
1177 int res;
1178 OrigFn fn;
1179 VALGRIND_GET_ORIG_FN(fn);
1180 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
1181 rwlock, 0, 0, 0, 0);
1182 CALL_FN_W_W(ret, fn, rwlock);
1183 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK,
1184 rwlock, ret == 0, 0, 0, 0);
1185 return ret;
bart00344642008-03-01 15:27:41 +00001186}
1187
bart791a0c62009-07-31 17:31:44 +00001188PTH_FUNCS(int,
1189 pthreadZurwlockZutryrdlock, pthread_rwlock_tryrdlock_intercept,
1190 (pthread_rwlock_t* rwlock), (rwlock));
1191
1192static __always_inline
1193int pthread_rwlock_trywrlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001194{
bartbedfd232009-03-26 19:07:15 +00001195 int ret;
1196 int res;
1197 OrigFn fn;
1198 VALGRIND_GET_ORIG_FN(fn);
1199 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
1200 rwlock, 0, 0, 0, 0);
1201 CALL_FN_W_W(ret, fn, rwlock);
1202 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK,
1203 rwlock, ret == 0, 0, 0, 0);
1204 return ret;
bart00344642008-03-01 15:27:41 +00001205}
1206
bart791a0c62009-07-31 17:31:44 +00001207PTH_FUNCS(int,
1208 pthreadZurwlockZutrywrlock, pthread_rwlock_trywrlock_intercept,
1209 (pthread_rwlock_t* rwlock), (rwlock));
1210
1211static __always_inline
1212int pthread_rwlock_unlock_intercept(pthread_rwlock_t* rwlock)
bart00344642008-03-01 15:27:41 +00001213{
bartbedfd232009-03-26 19:07:15 +00001214 int ret;
1215 int res;
1216 OrigFn fn;
1217 VALGRIND_GET_ORIG_FN(fn);
1218 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_UNLOCK,
1219 rwlock, 0, 0, 0, 0);
1220 CALL_FN_W_W(ret, fn, rwlock);
1221 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_UNLOCK,
1222 rwlock, ret == 0, 0, 0, 0);
1223 return ret;
bart00344642008-03-01 15:27:41 +00001224}
bart791a0c62009-07-31 17:31:44 +00001225
1226PTH_FUNCS(int,
1227 pthreadZurwlockZuunlock, pthread_rwlock_unlock_intercept,
1228 (pthread_rwlock_t* rwlock), (rwlock));