drd_pthread_intercepts.c revision 4f66a77e12665587f10b550fe438c3bd2f257b32
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* -*- mode: C; c-basic-offset: 3; -*- */
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*--------------------------------------------------------------------*/
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*--- Client-space code for DRD.          drd_pthread_intercepts.c ---*/
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*--------------------------------------------------------------------*/
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  This file is part of DRD, a thread error detector.
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>.
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  This program is free software; you can redistribute it and/or
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  modify it under the terms of the GNU General Public License as
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  published by the Free Software Foundation; either version 2 of the
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  License, or (at your option) any later version.
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  This program is distributed in the hope that it will be useful, but
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  WITHOUT ANY WARRANTY; without even the implied warranty of
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  General Public License for more details.
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  You should have received a copy of the GNU General Public License
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  along with this program; if not, write to the Free Software
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  02111-1307, USA.
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project  The GNU General Public License is contained in the file COPYING.
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* ---------------------------------------------------------------------
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU.
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   These functions are not called directly - they're the targets of code
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   redirection or load notifications (see pub_core_redir.h for info).
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   They're named weirdly so that the intercept code can find them when the
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   shared object is initially loaded.
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   Note that this filename has the "drd_" prefix because it can appear
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   in stack traces, and the "drd_" makes it a little clearer that it
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   originates from Valgrind.
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   ------------------------------------------------------------------ */
42bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Define _GNU_SOURCE to make sure that pthread_spinlock_t is available when
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * compiling with older glibc versions (2.3 or before).
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#ifndef _GNU_SOURCE
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define _GNU_SOURCE
49bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana#endif
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <assert.h>         /* assert() */
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <pthread.h>        /* pthread_mutex_t */
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <semaphore.h>      /* sem_t */
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h>          /* fprintf() */
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h>         /* malloc(), free() */
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h>         /* confstr() */
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "config.h"         /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP etc. */
58bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana#include "drd_basics.h"     /* DRD_() */
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "drd_clientreq.h"
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "pub_tool_redir.h" /* VG_WRAP_FUNCTION_ZZ() */
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* Defines. */
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Do not undefine the two macro's below, or the following two subtle race
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * conditions will be introduced in the data race detection algorithm:
68bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana * - sg_init() runs on the context of the created thread and copies the
691c4027b68d5938795cc536c1d45e8d942ea537a4Daniel Lehmann *   vector clock of the creator thread. This only works reliably if
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   the creator thread waits until this copy has been performed.
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * - Since DRD_(thread_compute_minimum_vc)() does not take the vector
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   clocks into account that are involved in thread creation but
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   for which the corresponding thread has not yet been created, by
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   undefining the macro below it becomes possible that segments get
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   discarded that should not yet be discarded. Or: some data races
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   are not detected.
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define WAIT_UNTIL_CREATED_THREAD_STARTED
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define ALLOCATE_THREAD_ARGS_ON_THE_STACK
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Macro for generating a Valgrind interception function.
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param[in] ret_ty Return type of the function to be generated.
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param[in] zf Z-encoded name of the interception function.
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param[in] implf Name of the function that implements the intercept.
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param[in] arg_decl Argument declaration list enclosed in parentheses.
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param[in] argl Argument list enclosed in parentheses.
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl)                    \
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl;     \
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl      \
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   { return implf argl; }
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Macro for generating three Valgrind interception functions: one with the
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Z-encoded name zf, one with ZAZa ("@*") appended to the name zf and one
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * with ZDZa ("$*") appended to the name zf. The second generated interception
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * function will intercept versioned symbols on Linux, and the third will
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * intercept versioned symbols on Darwin.
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define PTH_FUNCS(ret_ty, zf, implf, argl_decl, argl)           \
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   PTH_FUNC(ret_ty, zf, implf, argl_decl, argl);                \
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   PTH_FUNC(ret_ty, zf ## ZAZa, implf, argl_decl, argl);        \
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   PTH_FUNC(ret_ty, zf ## ZDZa, implf, argl_decl, argl);
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Not inlining one of the intercept functions will cause the regression
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * tests to fail because this would cause an additional stackfram to appear
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the output. The __always_inline macro guarantees that inlining will
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * happen, even when compiling with optimization disabled.
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#undef __always_inline /* since already defined in <cdefs.h> */
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if __GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 2
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define __always_inline __inline__ __attribute__((always_inline))
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define __always_inline __inline__
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* Local data structures. */
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttypedef struct
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   void* (*start)(void*);
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   void* arg;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   int   detachstate;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED)
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   int   wrapper_started;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} DrdPosixThreadArgs;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* Local function declarations. */
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void DRD_(init)(void) __attribute__((constructor));
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void DRD_(check_threading_library)(void);
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void DRD_(set_main_thread_state)(void);
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* Function definitions. */
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Shared library initialization function. The function init() is called after
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * dlopen() has loaded the shared library with DRD client intercepts because
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the constructor attribute was specified in the declaration of this function.
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note: do specify the -nostdlib option to gcc when linking this code into a
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * shared library because doing so would cancel the effect of the constructor
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * attribute ! Using the gcc option -nodefaultlibs is fine because this last
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * option preserves the shared library initialization code that calls
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * constructor and destructor functions.
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void DRD_(init)(void)
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   DRD_(check_threading_library)();
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   DRD_(set_main_thread_state)();
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * POSIX threads and DRD each have their own mutex type identification.
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Convert POSIX threads' mutex type to DRD's mutex type. In the code below
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if-statements are used to test the value of 'kind' instead of a switch
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * statement because some of the PTHREAD_MUTEX_ macro's may have the same
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value.
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic MutexT DRD_(pthread_to_drd_mutex_type)(const int kind)
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   if (kind == PTHREAD_MUTEX_RECURSIVE)
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      return mutex_type_recursive_mutex;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   else if (kind == PTHREAD_MUTEX_ERRORCHECK)
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      return mutex_type_errorcheck_mutex;
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   else if (kind == PTHREAD_MUTEX_NORMAL)
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      return mutex_type_default_mutex;
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   else if (kind == PTHREAD_MUTEX_DEFAULT)
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      return mutex_type_default_mutex;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP)
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   else if (kind == PTHREAD_MUTEX_ADAPTIVE_NP)
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      return mutex_type_default_mutex;
177bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana#endif
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   else
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   {
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      return mutex_type_invalid_mutex;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   }
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Read the mutex type stored in the client memory used for the mutex
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * implementation.
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @note This function depends on the implementation of the POSIX threads
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   library -- the POSIX standard does not define the name of the member in
190bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana *   which the mutex type is stored.
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @note The function mutex_type() has been declared inline in order
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   to avoid that it shows up in call stacks (drd/tests/...exp* files).
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @note glibc stores the mutex type in the lowest two bits, and uses the
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   higher bits for flags like PTHREAD_MUTEXATTR_FLAG_ROBUST and
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   PTHREAD_MUTEXATTR_FLAG_PSHARED.
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic __always_inline MutexT DRD_(mutex_type)(pthread_mutex_t* mutex)
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
199bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana#if defined(HAVE_PTHREAD_MUTEX_T__M_KIND)
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   /* glibc + LinuxThreads. */
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   const int kind = mutex->__m_kind & 3;
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   return DRD_(pthread_to_drd_mutex_type)(kind);
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#elif defined(HAVE_PTHREAD_MUTEX_T__DATA__KIND)
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   /* glibc + NPTL. */
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   const int kind = mutex->__data.__kind & 3;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   return DRD_(pthread_to_drd_mutex_type)(kind);
207c74ee2f8d3a9f4ebd502c037623cdbaf664c28a9Mike Tsao#else
208c74ee2f8d3a9f4ebd502c037623cdbaf664c28a9Mike Tsao   /*
209c74ee2f8d3a9f4ebd502c037623cdbaf664c28a9Mike Tsao    * Another POSIX threads implementation. The mutex type won't be printed
210c74ee2f8d3a9f4ebd502c037623cdbaf664c28a9Mike Tsao    * when enabling --trace-mutex=yes.
211c74ee2f8d3a9f4ebd502c037623cdbaf664c28a9Mike Tsao    */
212c74ee2f8d3a9f4ebd502c037623cdbaf664c28a9Mike Tsao   return mutex_type_unknown;
213c74ee2f8d3a9f4ebd502c037623cdbaf664c28a9Mike Tsao#endif
214c74ee2f8d3a9f4ebd502c037623cdbaf664c28a9Mike Tsao}
215c74ee2f8d3a9f4ebd502c037623cdbaf664c28a9Mike Tsao
216c74ee2f8d3a9f4ebd502c037623cdbaf664c28a9Mike Tsao/**
217c74ee2f8d3a9f4ebd502c037623cdbaf664c28a9Mike Tsao * Tell DRD whether 'tid' is a joinable thread or a detached thread.
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void DRD_(set_joinable)(const pthread_t tid, const int joinable)
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   int res;
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   assert(joinable == 0 || joinable == 1);
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__SET_JOINABLE,
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                              tid, joinable, 0, 0, 0);
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** Tell DRD that the calling thread is about to enter pthread_create(). */
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic __always_inline void DRD_(entering_pthread_create)(void)
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   int res;
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__ENTERING_PTHREAD_CREATE,
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                              0, 0, 0, 0, 0);
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** Tell DRD that the calling thread has left pthread_create(). */
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic __always_inline void DRD_(left_pthread_create)(void)
237bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana{
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   int res;
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__LEFT_PTHREAD_CREATE,
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                              0, 0, 0, 0, 0);
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
2441276b5f29ed6f889e9691cf296fd9911958895c1Steve Pomeroy * Entry point for newly created threads. This function is called from the
2451276b5f29ed6f889e9691cf296fd9911958895c1Steve Pomeroy * thread created by pthread_create().
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void* DRD_(thread_wrapper)(void* arg)
2481276b5f29ed6f889e9691cf296fd9911958895c1Steve Pomeroy{
2491276b5f29ed6f889e9691cf296fd9911958895c1Steve Pomeroy   int res;
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   DrdPosixThreadArgs* arg_ptr;
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   DrdPosixThreadArgs arg_copy;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   arg_ptr = (DrdPosixThreadArgs*)arg;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   arg_copy = *arg_ptr;
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED)
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   arg_ptr->wrapper_started = 1;
257bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana#else
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK)
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#error Defining ALLOCATE_THREAD_ARGS_ON_THE_STACK but not \
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project       WAIT_UNTIL_CREATED_THREAD_STARTED is not supported.
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   free(arg_ptr);
2631c4027b68d5938795cc536c1d45e8d942ea537a4Daniel Lehmann#endif
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                              pthread_self(), 0, 0, 0, 0);
268bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   DRD_(set_joinable)(pthread_self(),
2701276b5f29ed6f889e9691cf296fd9911958895c1Steve Pomeroy                      arg_copy.detachstate == PTHREAD_CREATE_JOINABLE);
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   return (arg_copy.start)(arg_copy.arg);
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return 1 if the LinuxThreads implementation of POSIX Threads has been
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * detected, and 0 otherwise.
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see For more information about the confstr() function, see also
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.opengroup.org/onlinepubs/009695399/functions/confstr.html
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int DRD_(detected_linuxthreads)(void)
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(linux)
285bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana#if defined(_CS_GNU_LIBPTHREAD_VERSION)
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   /* Linux with a recent glibc. */
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   char buffer[256];
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   unsigned len;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   assert(len <= sizeof(buffer));
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   return len > 0 && buffer[0] == 'l';
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
293bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana   /* Linux without _CS_GNU_LIBPTHREAD_VERSION: most likely LinuxThreads. */
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   return 1;
2951276b5f29ed6f889e9691cf296fd9911958895c1Steve Pomeroy#endif
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   /* Another OS than Linux, hence no LinuxThreads. */
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   return 0;
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Stop and print an error message in case a non-supported threading
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * library implementation (LinuxThreads) has been detected.
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void DRD_(check_threading_library)(void)
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   if (DRD_(detected_linuxthreads)())
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   {
310bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana      if (getenv("LD_ASSUME_KERNEL"))
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      {
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         fprintf(stderr,
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project"after having unset the environment variable LD_ASSUME_KERNEL. Giving up.\n"
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project);
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      }
318bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana      else
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      {
3201276b5f29ed6f889e9691cf296fd9911958895c1Steve Pomeroy         fprintf(stderr,
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project"after having upgraded to a newer version of your Linux distribution.\n"
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project"Giving up.\n"
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project);
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      }
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      abort();
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   }
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The main thread is the only thread not created by pthread_create().
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Update DRD's state information about the main thread.
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
335bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintanastatic void DRD_(set_main_thread_state)(void)
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   int res;
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   // Make sure that DRD knows about the main thread's POSIX thread ID.
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                              pthread_self(), 0, 0, 0, 0);
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
343bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana}
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3451276b5f29ed6f889e9691cf296fd9911958895c1Steve Pomeroy
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note: as of today there exist three different versions of pthread_create
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in Linux:
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * - pthread_create@GLIBC_2.0
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * - pthread_create@@GLIBC_2.1
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * - pthread_create@@GLIBC_2.2.5
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * As an example, in libpthread-2.3.4 both pthread_create@GLIBC_2.0 and
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * pthread_create@@GLIBC_2.1 are defined, while in libpthread-2.9 all three
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * versions have been implemented. In any glibc version where more than one
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * pthread_create function has been implemented, older versions call the
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * newer versions. Or: the pthread_create* wrapper defined below can be
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * called recursively. Any code in this wrapper should take this in account.
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * As an example, it is not safe to invoke the DRD_STOP_RECORDING
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * / DRD_START_RECORDING client requests from the pthread_create wrapper.
360bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana * See also the implementation of pthread_create@GLIBC_2.0 in
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * glibc-2.9/nptl/pthread_create.c.
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic __always_inline
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint pthread_create_intercept(pthread_t* thread, const pthread_attr_t* attr,
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             void* (*start)(void*), void* arg)
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
368bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana   int    res;
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   int    ret;
3701276b5f29ed6f889e9691cf296fd9911958895c1Steve Pomeroy   OrigFn fn;
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK)
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   DrdPosixThreadArgs thread_args;
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   DrdPosixThreadArgs* thread_args_p;
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   VALGRIND_GET_ORIG_FN(fn);
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK)
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   thread_args_p = &thread_args;
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   thread_args_p = malloc(sizeof(*thread_args_p));
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   assert(thread_args_p);
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
385bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana   thread_args_p->start           = start;
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   thread_args_p->arg             = arg;
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED)
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   DRD_IGNORE_VAR(thread_args_p->wrapper_started);
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   thread_args_p->wrapper_started = 0;
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   /*
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    * Find out whether the thread will be started as a joinable thread
393bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana    * or as a detached thread. If no thread attributes have been specified,
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    * this means that the new thread will be started as a joinable thread.
3951276b5f29ed6f889e9691cf296fd9911958895c1Steve Pomeroy    */
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   thread_args_p->detachstate = PTHREAD_CREATE_JOINABLE;
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   if (attr)
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   {
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      if (pthread_attr_getdetachstate(attr, &thread_args_p->detachstate) != 0)
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      {
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         assert(0);
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      }
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   }
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   assert(thread_args_p->detachstate == PTHREAD_CREATE_JOINABLE
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project          || thread_args_p->detachstate == PTHREAD_CREATE_DETACHED);
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   DRD_(entering_pthread_create)();
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   CALL_FN_W_WWWW(ret, fn, thread, attr, DRD_(thread_wrapper), thread_args_p);
410bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana   DRD_(left_pthread_create)();
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED)
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   if (ret == 0)
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   {
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      /*
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project       * Wait until the thread wrapper started.
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project       * @todo Find out why some regression tests fail if thread arguments are
418bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana       *   passed via dynamically allocated memory and if the loop below is
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project       *   removed.
4201276b5f29ed6f889e9691cf296fd9911958895c1Steve Pomeroy       */
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      while (! thread_args_p->wrapper_started)
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      {
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         sched_yield();
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      }
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   }
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if defined(ALLOCATE_THREAD_ARGS_DYNAMICALLY)
428794cf190aa38dffdad9e82fc86dbd94940b175b1Michael Wright   free(thread_args_p);
429794cf190aa38dffdad9e82fc86dbd94940b175b1Michael Wright#endif
430794cf190aa38dffdad9e82fc86dbd94940b175b1Michael Wright
431794cf190aa38dffdad9e82fc86dbd94940b175b1Michael Wright#endif
432794cf190aa38dffdad9e82fc86dbd94940b175b1Michael Wright
433d208c3a68b96cf0c1dde5cdeab0e8464b9e52018Jeff Hamilton   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_START_NEW_SEGMENT,
434d208c3a68b96cf0c1dde5cdeab0e8464b9e52018Jeff Hamilton                              pthread_self(), 0, 0, 0, 0);
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
436bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana   return ret;
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectPTH_FUNCS(int, pthreadZucreate, pthread_create_intercept,
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project          (pthread_t *thread, const pthread_attr_t *attr,
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project           void *(*start) (void *), void *arg),
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project          (thread, attr, start, arg));
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic __always_inline
445bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintanaint pthread_join_intercept(pthread_t pt_joinee, void **thread_return)
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4471276b5f29ed6f889e9691cf296fd9911958895c1Steve Pomeroy   int      ret;
4481276b5f29ed6f889e9691cf296fd9911958895c1Steve Pomeroy   int      res;
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   OrigFn   fn;
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   VALGRIND_GET_ORIG_FN(fn);
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   CALL_FN_W_WW(ret, fn, pt_joinee, thread_return);
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   if (ret == 0)
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   {
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_JOIN,
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                 pt_joinee, 0, 0, 0, 0);
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   }
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   return ret;
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
461bda8874a2990a864f32f8d2d916f7a05f33f797bFred QuintanaPTH_FUNCS(int, pthreadZujoin, pthread_join_intercept,
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project          (pthread_t pt_joinee, void **thread_return),
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project          (pt_joinee, thread_return));
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic __always_inline
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint pthread_detach_intercept(pthread_t pt_thread)
467bda8874a2990a864f32f8d2d916f7a05f33f797bFred Quintana{
468532abb65308725c649fe94ba485abc24ece05b2eVasu Nori   int ret;
469532abb65308725c649fe94ba485abc24ece05b2eVasu Nori   OrigFn fn;
470532abb65308725c649fe94ba485abc24ece05b2eVasu Nori   VALGRIND_GET_ORIG_FN(fn);
471532abb65308725c649fe94ba485abc24ece05b2eVasu Nori   {
472532abb65308725c649fe94ba485abc24ece05b2eVasu Nori      CALL_FN_W_W(ret, fn, pt_thread);
473532abb65308725c649fe94ba485abc24ece05b2eVasu Nori      if (ret == 0)
474532abb65308725c649fe94ba485abc24ece05b2eVasu Nori      {
475532abb65308725c649fe94ba485abc24ece05b2eVasu Nori         DRD_(set_joinable)(pt_thread, 0);
476532abb65308725c649fe94ba485abc24ece05b2eVasu Nori      }
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   }
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   return ret;
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectPTH_FUNCS(int, pthreadZudetach, pthread_detach_intercept,
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project          (pthread_t thread), (thread));
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// NOTE: be careful to intercept only pthread_cancel() and not
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// pthread_cancel_init() on Linux.
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic __always_inline
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint pthread_cancel_intercept(pthread_t pt_thread)
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   int res;
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   int ret;
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   OrigFn fn;
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   VALGRIND_GET_ORIG_FN(fn);
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_THREAD_CANCEL,
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                              pt_thread, 0, 0, 0, 0);
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   CALL_FN_W_W(ret, fn, pt_thread);
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_CANCEL,
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                              pt_thread, ret==0, 0, 0, 0);
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   return ret;
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectPTH_FUNCS(int, pthreadZucancel, pthread_cancel_intercept,
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project          (pthread_t thread), (thread))
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic __always_inline
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint pthread_once_intercept(pthread_once_t *once_control,
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                           void (*init_routine)(void))
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   int ret;
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   OrigFn fn;
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   VALGRIND_GET_ORIG_FN(fn);
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   /*
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    * Ignore any data races triggered by the implementation of pthread_once().
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    * Necessary for Darwin. This is not necessary for Linux but doesn't have
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    * any known adverse effects.
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    */
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   DRD_IGNORE_VAR(*once_control);
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   CALL_FN_W_WW(ret, fn, once_control, init_routine);
519f924a513da2ec1989a06dc16d007c0eca422ea67Jeff Hamilton   DRD_STOP_IGNORING_VAR(*once_control);
520f924a513da2ec1989a06dc16d007c0eca422ea67Jeff Hamilton   return ret;
521f924a513da2ec1989a06dc16d007c0eca422ea67Jeff Hamilton}
522f924a513da2ec1989a06dc16d007c0eca422ea67Jeff Hamilton
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectPTH_FUNCS(int, pthreadZuonce, pthread_once_intercept,
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project          (pthread_once_t *once_control, void (*init_routine)(void)),
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project          (once_control, init_routine));
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic __always_inline
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint pthread_mutex_init_intercept(pthread_mutex_t *mutex,
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                 const pthread_mutexattr_t* attr)
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   int ret;
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   int res;
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project   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;
546}
547
548PTH_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)
554{
555   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;
565}
566
567PTH_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)
572{
573   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;
583}
584
585PTH_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)
590{
591   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;
601}
602
603PTH_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)
609{
610   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;
620}
621
622PTH_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)
628{
629   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;
641}
642
643PTH_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)
649{
650   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;
660}
661
662PTH_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)
668{
669   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;
679}
680
681PTH_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)
686{
687   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;
697}
698
699PTH_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)
707{
708   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;
718}
719
720PTH_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
725// 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
731static __always_inline
732int pthread_cond_signal_intercept(pthread_cond_t* cond)
733{
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
746PTH_FUNCS(int, pthreadZucondZusignal, pthread_cond_signal_intercept,
747          (pthread_cond_t* cond), (cond));
748
749static __always_inline
750int pthread_cond_broadcast_intercept(pthread_cond_t* cond)
751{
752   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;
762}
763
764PTH_FUNCS(int, pthreadZucondZubroadcast, pthread_cond_broadcast_intercept,
765          (pthread_cond_t* cond), (cond));
766
767#if defined(HAVE_PTHREAD_SPIN_LOCK)
768static __always_inline
769int pthread_spin_init_intercept(pthread_spinlock_t *spinlock, int pshared)
770{
771   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;
781}
782
783PTH_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)
788{
789   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;
799}
800
801PTH_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)
806{
807   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;
817}
818
819PTH_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)
824{
825   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;
835}
836
837PTH_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)
842{
843   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;
853}
854
855PTH_FUNCS(int, pthreadZuspinZuunlock, pthread_spin_unlock_intercept,
856          (pthread_spinlock_t *spinlock), (spinlock));
857#endif   // HAVE_PTHREAD_SPIN_LOCK
858
859
860#if defined(HAVE_PTHREAD_BARRIER_INIT)
861static __always_inline
862int pthread_barrier_init_intercept(pthread_barrier_t* barrier,
863                                   const pthread_barrierattr_t* attr,
864                                   unsigned count)
865{
866   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;
876}
877
878PTH_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)
884{
885   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;
895}
896
897PTH_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)
902{
903   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;
915}
916
917PTH_FUNCS(int, pthreadZubarrierZuwait, pthread_barrier_wait_intercept,
918          (pthread_barrier_t* barrier), (barrier));
919#endif   // HAVE_PTHREAD_BARRIER_INIT
920
921
922static __always_inline
923int sem_init_intercept(sem_t *sem, int pshared, unsigned int value)
924{
925   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;
935}
936
937PTH_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)
942{
943   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;
953}
954
955PTH_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)
960{
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
974PTH_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)
979{
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
992PTH_FUNCS(int, semZuclose, sem_close_intercept, (sem_t *sem), (sem));
993
994static __always_inline int sem_wait_intercept(sem_t *sem)
995{
996   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;
1006}
1007
1008PTH_FUNCS(int, semZuwait, sem_wait_intercept, (sem_t *sem), (sem));
1009
1010static __always_inline int sem_trywait_intercept(sem_t *sem)
1011{
1012   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;
1022}
1023
1024PTH_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)
1028{
1029   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;
1039}
1040
1041PTH_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)
1046{
1047   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;
1057}
1058
1059PTH_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)
1064{
1065   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;
1073}
1074
1075PTH_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)
1082{
1083   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;
1091}
1092
1093PTH_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)
1099{
1100   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;
1110}
1111
1112PTH_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)
1118{
1119   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;
1129}
1130
1131PTH_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)
1137{
1138   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;
1148}
1149
1150PTH_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)
1156{
1157   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;
1167}
1168
1169PTH_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)
1175{
1176   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;
1186}
1187
1188PTH_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)
1194{
1195   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;
1205}
1206
1207PTH_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)
1213{
1214   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;
1224}
1225
1226PTH_FUNCS(int,
1227          pthreadZurwlockZuunlock, pthread_rwlock_unlock_intercept,
1228          (pthread_rwlock_t* rwlock), (rwlock));
1229