1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- pthread intercepts for thread checking. ---*/ 4b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--- hg_intercepts.c ---*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Helgrind, a Valgrind tool for detecting errors 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in threaded programs. 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Copyright (C) 2007-2013 OpenWorks LLP 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown info@open-works.co.uk 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Neither the names of the U.S. Department of Energy nor the 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown University of California nor the names of its contributors may be 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown used to endorse or promote products derived from this software 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown without prior written permission. 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* RUNS ON SIMULATED CPU 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Interceptors for pthread_* functions, so that tc_main can see 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown significant thread events. 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Important: when adding a function wrapper to this file, remember to 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add a test case to tc20_verifywrap.c. A common cause of failure is 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for wrappers to not engage on different distros, and 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tc20_verifywrap essentially checks that each wrapper is really 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown doing something. 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// DDD: for Darwin, need to have non-"@*"-suffixed versions for all pthread 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// functions that currently have them. 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Note also, in the comments and code below, all Darwin symbols start 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// with a leading underscore, which is not shown either in the comments 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// nor in the redirect specs. 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_basics.h" 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_redir.h" 57436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "pub_tool_clreq.h" 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "helgrind.h" 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "config.h" 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TRACE_PTH_FNS 0 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TRACE_QT4_FNS 0 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ---*/ 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PTH_FUNC(ret_ty, f, args...) \ 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args); \ 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args) 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Do a client request. These are macros rather than a functions so 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// as to avoid having an extra frame in stack traces. 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// NB: these duplicate definitions in helgrind.h. But here, we 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// can have better typing (Word etc) and assertions, whereas 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// in helgrind.h we can't. Obviously it's important the two 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// sets of definitions are kept in sync. 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// nuke the previous definitions 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DO_CREQ_v_W 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DO_CREQ_v_WW 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DO_CREQ_W_WW 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DO_CREQ_v_WWW 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DO_CREQ_v_W(_creqF, _ty1F,_arg1F) \ 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { \ 89b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Word _arg1; \ 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(sizeof(_ty1F) == sizeof(Word)); \ 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _arg1 = (Word)(_arg1F); \ 92b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VALGRIND_DO_CLIENT_REQUEST_STMT((_creqF), \ 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _arg1, 0,0,0,0); \ 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DO_CREQ_v_WW(_creqF, _ty1F,_arg1F, _ty2F,_arg2F) \ 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { \ 98b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Word _arg1, _arg2; \ 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(sizeof(_ty1F) == sizeof(Word)); \ 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(sizeof(_ty2F) == sizeof(Word)); \ 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _arg1 = (Word)(_arg1F); \ 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _arg2 = (Word)(_arg2F); \ 103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VALGRIND_DO_CLIENT_REQUEST_STMT((_creqF), \ 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _arg1,_arg2,0,0,0); \ 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define DO_CREQ_W_WW(_resF, _creqF, _ty1F,_arg1F, \ 108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov _ty2F,_arg2F) \ 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { \ 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word _res, _arg1, _arg2; \ 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(sizeof(_ty1F) == sizeof(Word)); \ 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(sizeof(_ty2F) == sizeof(Word)); \ 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _arg1 = (Word)(_arg1F); \ 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _arg2 = (Word)(_arg2F); \ 115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov _res = VALGRIND_DO_CLIENT_REQUEST_EXPR(2, \ 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (_creqF), \ 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _arg1,_arg2,0,0,0); \ 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _resF = _res; \ 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DO_CREQ_v_WWW(_creqF, _ty1F,_arg1F, \ 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _ty2F,_arg2F, _ty3F, _arg3F) \ 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { \ 124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Word _arg1, _arg2, _arg3; \ 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(sizeof(_ty1F) == sizeof(Word)); \ 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(sizeof(_ty2F) == sizeof(Word)); \ 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(sizeof(_ty3F) == sizeof(Word)); \ 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _arg1 = (Word)(_arg1F); \ 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _arg2 = (Word)(_arg2F); \ 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _arg3 = (Word)(_arg3F); \ 131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VALGRIND_DO_CLIENT_REQUEST_STMT((_creqF), \ 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _arg1,_arg2,_arg3,0,0); \ 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DO_PthAPIerror(_fnnameF, _errF) \ 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown do { \ 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char* _fnname = (char*)(_fnnameF); \ 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown long _err = (long)(int)(_errF); \ 140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const char* _errstr = lame_strerror(_err); \ 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WWW(_VG_USERREQ__HG_PTH_API_ERROR, \ 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char*,_fnname, \ 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown long,_err, char*,_errstr); \ 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } while (0) 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Needed for older glibcs (2.3 and older, at least) who don't 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown otherwise "know" about pthread_rwlock_anything or about 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTHREAD_MUTEX_RECURSIVE (amongst things). */ 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define _GNU_SOURCE 1 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h> 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <assert.h> 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <errno.h> 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <pthread.h> 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* A standalone memcmp. */ 158436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov__attribute__((noinline)) 159436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic int my_memcmp ( const void* ptr1, const void* ptr2, size_t size) 160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 161436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov unsigned char* uchar_ptr1 = (unsigned char*) ptr1; 162436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov unsigned char* uchar_ptr2 = (unsigned char*) ptr2; 163436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov size_t i; 164436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (i = 0; i < size; ++i) { 165436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (uchar_ptr1[i] != uchar_ptr2[i]) 166436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return (uchar_ptr1[i] < uchar_ptr2[i]) ? -1 : 1; 167436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 168436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return 0; 169436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A lame version of strerror which doesn't use the real libc 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown strerror_r, since using the latter just generates endless more 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown threading errors (glibc goes off and does tons of crap w.r.t. 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown locales etc) */ 175436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic const HChar* lame_strerror ( long err ) 176436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 177436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov switch (err) { 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case EPERM: return "EPERM: Operation not permitted"; 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ENOENT: return "ENOENT: No such file or directory"; 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ESRCH: return "ESRCH: No such process"; 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case EINTR: return "EINTR: Interrupted system call"; 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case EBADF: return "EBADF: Bad file number"; 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case EAGAIN: return "EAGAIN: Try again"; 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ENOMEM: return "ENOMEM: Out of memory"; 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case EACCES: return "EACCES: Permission denied"; 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case EFAULT: return "EFAULT: Bad address"; 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case EEXIST: return "EEXIST: File exists"; 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case EINVAL: return "EINVAL: Invalid argument"; 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case EMFILE: return "EMFILE: Too many open files"; 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ENOSYS: return "ENOSYS: Function not implemented"; 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case EOVERFLOW: return "EOVERFLOW: Value too large " 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "for defined data type"; 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case EBUSY: return "EBUSY: Device or resource busy"; 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case ETIMEDOUT: return "ETIMEDOUT: Connection timed out"; 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case EDEADLK: return "EDEADLK: Resource deadlock would occur"; 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case EOPNOTSUPP: return "EOPNOTSUPP: Operation not supported on " 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "transport endpoint"; /* honest, guv */ 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: return "tc_intercepts.c: lame_strerror(): " 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "unhandled case -- please fix me!"; 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- pthread_create, pthread_join, pthread_exit ---*/ 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void* mythread_wrapper ( void* xargsV ) 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown volatile Word* xargs = (volatile Word*) xargsV; 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void*(*fn)(void*) = (void*(*)(void*))xargs[0]; 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* arg = (void*)xargs[1]; 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t me = pthread_self(); 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Tell the tool what my pthread_t is. */ 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_SET_MY_PTHREAD_T, pthread_t,me); 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* allow the parent to proceed. We can't let it proceed until 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we're ready because (1) we need to make sure it doesn't exit and 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hence deallocate xargs[] while we still need it, and (2) we 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown don't want either parent nor child to proceed until the tool has 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown been notified of the child's pthread_t. 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Note that parent and child access args[] without a lock, 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown effectively using args[2] as a spinlock in order to get the 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown parent to wait until the child passes this point. The parent 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown disables checking on xargs[] before creating the child and 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown re-enables it once the child goes past this point, so the user 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown never sees the race. The previous approach (suppressing the 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown resulting error) was flawed, because it could leave shadow 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown memory for args[] in a state in which subsequent use of it by 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the parent would report further races. */ 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xargs[2] = 0; 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Now we can no longer safely use xargs[]. */ 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (void*) fn( (void*)arg ); 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_create@GLIBC_2.0 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_create@@GLIBC_2.1 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_create@@GLIBC_2.2.5 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_create 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_create_suspended_np (trapped) 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ensure this has its own frame, so as to make it more distinguishable 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown in suppressions */ 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noinline)) 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_create_WRK(pthread_t *thread, const pthread_attr_t *attr, 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *(*start) (void *), void *arg) 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown volatile Word xargs[3]; 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_create wrapper"); fflush(stderr); 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xargs[0] = (Word)start; 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xargs[1] = (Word)arg; 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xargs[2] = 1; /* serves as a spinlock -- sigh */ 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Disable checking on the spinlock and the two words used to 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown convey args to the child. Basically we need to make it appear 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown as if the child never accessed this area, since merely 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown suppressing the resulting races does not address the issue that 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that piece of the parent's stack winds up in the "wrong" state 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and therefore may give rise to mysterious races when the parent 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown comes to re-use this piece of stack in some other frame. */ 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_HG_DISABLE_CHECKING(&xargs, sizeof(xargs)); 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WWWW(ret, fn, thread,attr,mythread_wrapper,&xargs[0]); 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0) { 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* we have to wait for the child to notify the tool of its 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t before continuing */ 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (xargs[2] != 0) { 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Do nothing. We need to spin until the child writes to 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown xargs[2]. However, that can lead to starvation in the 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown child and very long delays (eg, tc19_shadowmem on 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ppc64-linux Fedora Core 6). So yield the cpu if we can, 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to let the child run at the earliest available 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown opportunity. */ 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sched_yield(); 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_create", ret ); 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Reenable checking on the area previously used to communicate 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown with the child. */ 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_HG_ENABLE_CHECKING(&xargs, sizeof(xargs)); 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: pth_create -> %d >>\n", ret); 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZucreateZAZa, // pthread_create@* 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t *thread, const pthread_attr_t *attr, 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *(*start) (void *), void *arg) { 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_create_WRK(thread, attr, start, arg); 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZucreate, // pthread_create 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t *thread, const pthread_attr_t *attr, 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *(*start) (void *), void *arg) { 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_create_WRK(thread, attr, start, arg); 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZucreateZuZa, // pthread_create_* 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t *thread, const pthread_attr_t *attr, 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void *(*start) (void *), void *arg) { 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // trap anything else 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(0); 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_join 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_join 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_join$NOCANCEL$UNIX2003 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin pthread_join$UNIX2003 324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_join_WRK(pthread_t thread, void** value_pointer) 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_join wrapper"); fflush(stderr); 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WW(ret, fn, thread,value_pointer); 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* At least with NPTL as the thread library, this is safe because 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it is guaranteed (by NPTL) that the joiner will completely gone 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown before pthread_join (the original) returns. See email below.*/ 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 /*success*/) { 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_JOIN_POST, pthread_t,thread); 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_join", ret ); 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: pth_join -> %d >>\n", ret); 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZujoin, // pthread_join 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t thread, void** value_pointer) { 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_join_WRK(thread, value_pointer); 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZujoinZa, // pthread_join* 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t thread, void** value_pointer) { 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_join_WRK(thread, value_pointer); 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Behaviour of pthread_join on NPTL: 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMe: 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownI have a question re the NPTL pthread_join implementation. 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Suppose I am the thread 'stayer'. 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown If I call pthread_join(quitter), is it guaranteed that the 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread 'quitter' has really exited before pthread_join returns? 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown IOW, is it guaranteed that 'quitter' will not execute any further 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown instructions after pthread_join returns? 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownI believe this is true based on the following analysis of 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownglibc-2.5 sources. However am not 100% sure and would appreciate 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconfirmation. 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 'quitter' will be running start_thread() in nptl/pthread_create.c 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The last action of start_thread() is to exit via 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __exit_thread_inline(0), which simply does sys_exit 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (nptl/pthread_create.c:403) 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 'stayer' meanwhile is waiting for lll_wait_tid (pd->tid) 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (call at nptl/pthread_join.c:89) 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536, 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lll_wait_tid will not return until kernel notifies via futex 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wakeup that 'quitter' has terminated. 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Hence pthread_join cannot return until 'quitter' really has 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown completely disappeared. 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDrepper: 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown> As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536, 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown> lll_wait_tid will not return until kernel notifies via futex 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown> wakeup that 'quitter' has terminated. 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownThat's the key. The kernel resets the TID field after the thread is 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browndone. No way the joiner can return before the thread is gone. 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- pthread_mutex_t functions ---*/ 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handled: pthread_mutex_init pthread_mutex_destroy 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_lock 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_trylock pthread_mutex_timedlock 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_unlock 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_mutex_init 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_mutex_init 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZumutexZuinit, // pthread_mutex_init 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t *mutex, 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutexattr_t* attr) 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown long mbRec; 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_mxinit %p", mutex); fflush(stderr); 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mbRec = 0; 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (attr) { 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ty, zzz; 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zzz = pthread_mutexattr_gettype(attr, &ty); 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (zzz == 0 && ty == PTHREAD_MUTEX_RECURSIVE) 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mbRec = 1; 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WW(ret, fn, mutex,attr); 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 /*success*/) { 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST, 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t*,mutex, long,mbRec); 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_mutex_init", ret ); 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: mxinit -> %d >>\n", ret); 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_mutex_destroy 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_mutex_destroy 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZumutexZudestroy, // pthread_mutex_destroy 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t *mutex) 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 463436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov unsigned long mutex_is_init; 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 465436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_mxdestroy %p", mutex); fflush(stderr); 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 471436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (mutex != NULL) { 472436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov static const pthread_mutex_t mutex_init = PTHREAD_MUTEX_INITIALIZER; 473436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mutex_is_init = my_memcmp(mutex, &mutex_init, sizeof(*mutex)) == 0; 474436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 475436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov mutex_is_init = 0; 476436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 477436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 478436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE, 479436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov pthread_mutex_t*, mutex, unsigned long, mutex_is_init); 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, mutex); 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0) { 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_mutex_destroy", ret ); 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: mxdestroy -> %d >>\n", ret); 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_mutex_lock 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_mutex_lock 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t *mutex) 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_mxlock %p", mutex); fflush(stderr); 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE, 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t*,mutex, long,0/*!isTryLock*/); 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, mutex); 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There's a hole here: libpthread now knows the lock is locked, 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but the tool doesn't, so some other thread could run and detect 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that the lock has been acquired by someone (this thread). Does 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this matter? Not sure, but I don't think so. */ 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 /*success*/) { 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t*,mutex); 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_mutex_lock", ret ); 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: mxlock -> %d >>\n", ret); 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_mutex_trylock 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_mutex_trylock 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// pthread_mutex_trylock. The handling needed here is very similar 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// to that for pthread_mutex_lock, except that we need to tell 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// the pre-lock creq that this is a trylock-style operation, and 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// therefore not to complain if the lock is nonrecursive and 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// already locked by this thread -- because then it'll just fail 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// immediately with EBUSY. 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t *mutex) 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_mxtrylock %p", mutex); fflush(stderr); 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE, 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t*,mutex, long,1/*isTryLock*/); 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, mutex); 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There's a hole here: libpthread now knows the lock is locked, 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but the tool doesn't, so some other thread could run and detect 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that the lock has been acquired by someone (this thread). Does 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this matter? Not sure, but I don't think so. */ 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 /*success*/) { 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t*,mutex); 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != EBUSY) 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_mutex_trylock", ret ); 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: mxtrylock -> %d >>\n", ret); 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_mutex_timedlock 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: (doesn't appear to exist) 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// pthread_mutex_timedlock. Identical logic to pthread_mutex_trylock. 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t *mutex, 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* timeout) 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_mxtimedlock %p %p", mutex, timeout); 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE, 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t*,mutex, long,1/*isTryLock-ish*/); 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WW(ret, fn, mutex,timeout); 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There's a hole here: libpthread now knows the lock is locked, 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but the tool doesn't, so some other thread could run and detect 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that the lock has been acquired by someone (this thread). Does 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this matter? Not sure, but I don't think so. */ 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 /*success*/) { 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t*,mutex); 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != ETIMEDOUT) 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_mutex_timedlock", ret ); 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: mxtimedlock -> %d >>\n", ret); 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_mutex_unlock 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_mutex_unlock 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t *mutex) 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_mxunlk %p", mutex); fflush(stderr); 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE, 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t*,mutex); 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, mutex); 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 /*success*/) { 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST, 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t*,mutex); 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_mutex_unlock", ret ); 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " mxunlk -> %d >>\n", ret); 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- pthread_cond_t functions ---*/ 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handled: pthread_cond_wait pthread_cond_timedwait 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_signal pthread_cond_broadcast 657436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov pthread_cond_init 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_destroy 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_cond_wait@GLIBC_2.2.5 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_cond_wait@@GLIBC_2.3.2 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_wait 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_wait$NOCANCEL$UNIX2003 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_wait$UNIX2003 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_cond_wait_WRK(pthread_cond_t* cond, 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t* mutex) 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long mutex_is_valid; 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_cond_wait %p %p", cond, mutex); 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Tell the tool a cond-wait is about to happen, so it can check 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for bogus argument values. In return it tells us whether it 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thinks the mutex is valid or not. */ 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_W_WW(mutex_is_valid, 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE, 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t*,cond, pthread_mutex_t*,mutex); 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(mutex_is_valid == 1 || mutex_is_valid == 0); 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Tell the tool we're about to drop the mutex. This reflects the 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fact that in a cond_wait, we show up holding the mutex, and the 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown call atomically drops the mutex and waits for the cv to be 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signalled. */ 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mutex_is_valid) { 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE, 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t*,mutex); 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WW(ret, fn, cond,mutex); 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* these conditionals look stupid, but compare w/ same logic for 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_timedwait below */ 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 && mutex_is_valid) { 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* and now we have the mutex again */ 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t*,mutex); 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 && mutex_is_valid) { 711436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST, 712436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov pthread_cond_t*,cond, pthread_mutex_t*,mutex, long,0); 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0) { 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_cond_wait", ret ); 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " cowait -> %d >>\n", ret); 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZucondZuwaitZAZa, // pthread_cond_wait@* 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t* cond, pthread_mutex_t* mutex) { 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_cond_wait_WRK(cond, mutex); 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait* 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t* cond, pthread_mutex_t* mutex) { 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_cond_wait_WRK(cond, mutex); 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_cond_timedwait@@GLIBC_2.3.2 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_cond_timedwait@GLIBC_2.2.5 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_cond_timedwait@GLIBC_2.0 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_timedwait 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_timedwait$NOCANCEL$UNIX2003 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_timedwait$UNIX2003 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_timedwait_relative_np (trapped) 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 749b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_cond_timedwait_WRK(pthread_cond_t* cond, 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t* mutex, 752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct timespec* abstime) 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long mutex_is_valid; 757b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Bool abstime_is_valid; 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_cond_timedwait %p %p %p", 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cond, mutex, abstime); 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Tell the tool a cond-wait is about to happen, so it can check 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for bogus argument values. In return it tells us whether it 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thinks the mutex is valid or not. */ 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_W_WW(mutex_is_valid, 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE, 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t*,cond, pthread_mutex_t*,mutex); 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(mutex_is_valid == 1 || mutex_is_valid == 0); 773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 774b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov abstime_is_valid = abstime->tv_nsec >= 0 && abstime->tv_nsec < 1000000000; 775b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Tell the tool we're about to drop the mutex. This reflects the 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fact that in a cond_wait, we show up holding the mutex, and the 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown call atomically drops the mutex and waits for the cv to be 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown signalled. */ 780b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (mutex_is_valid && abstime_is_valid) { 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE, 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t*,mutex); 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WWW(ret, fn, cond,mutex,abstime); 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 787b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!abstime_is_valid && ret != EINVAL) { 788b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov DO_PthAPIerror("Bug in libpthread: pthread_cond_timedwait " 789b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "invalid abstime did not cause" 790b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov " EINVAL", ret); 791b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 792b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((ret == 0 || ret == ETIMEDOUT) && mutex_is_valid) { 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* and now we have the mutex again */ 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_mutex_t*,mutex); 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 799436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if ((ret == 0 || ret == ETIMEDOUT) && mutex_is_valid) { 800436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST, 801436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov pthread_cond_t*,cond, pthread_mutex_t*,mutex, 802436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov long,ret == ETIMEDOUT); 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0 && ret != ETIMEDOUT) { 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_cond_timedwait", ret ); 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " cotimedwait -> %d >>\n", ret); 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZucondZutimedwaitZAZa, // pthread_cond_timedwait@* 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t* cond, pthread_mutex_t* mutex, 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct timespec* abstime) { 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_cond_timedwait_WRK(cond, mutex, abstime); 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZucondZutimedwait, // pthread_cond_timedwait 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t* cond, pthread_mutex_t* mutex, 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct timespec* abstime) { 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_cond_timedwait_WRK(cond, mutex, abstime); 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZucondZutimedwaitZDZa, // pthread_cond_timedwait$* 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t* cond, pthread_mutex_t* mutex, 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct timespec* abstime) { 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_cond_timedwait_WRK(cond, mutex, abstime); 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZucondZutimedwaitZuZa, // pthread_cond_timedwait_* 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t* cond, pthread_mutex_t* mutex, 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct timespec* abstime) { 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(0); 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_cond_signal@GLIBC_2.0 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_cond_signal@GLIBC_2.2.5 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_cond_signal@@GLIBC_2.3.2 846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_signal 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_signal_thread_np (don't intercept this) 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 849b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_cond_signal_WRK(pthread_cond_t* cond) 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_cond_signal %p", cond); 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_SIGNAL_PRE, 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t*,cond); 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, cond); 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0) { 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_cond_signal", ret ); 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " cosig -> %d >>\n", ret); 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZucondZusignalZAZa, // pthread_cond_signal@* 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t* cond) { 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_cond_signal_WRK(cond); 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZucondZusignal, // pthread_cond_signal 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t* cond) { 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_cond_signal_WRK(cond); 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_cond_broadcast@GLIBC_2.0 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_cond_broadcast@GLIBC_2.2.5 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_cond_broadcast@@GLIBC_2.3.2 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_broadcast 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Note, this is pretty much identical, from a dependency-graph 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// point of view, with cond_signal, so the code is duplicated. 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Maybe it should be commoned up. 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 901b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_cond_broadcast_WRK(pthread_cond_t* cond) 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_cond_broadcast %p", cond); 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_BROADCAST_PRE, 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t*,cond); 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, cond); 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0) { 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_cond_broadcast", ret ); 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " cobro -> %d >>\n", ret); 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZucondZubroadcastZAZa, // pthread_cond_broadcast@* 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t* cond) { 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_cond_broadcast_WRK(cond); 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZucondZubroadcast, // pthread_cond_broadcast 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t* cond) { 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_cond_broadcast_WRK(cond); 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 942436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// glibc: pthread_cond_init@GLIBC_2.0 943436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// glibc: pthread_cond_init@GLIBC_2.2.5 944436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// glibc: pthread_cond_init@@GLIBC_2.3.2 945436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// darwin: pthread_cond_init 946436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// Easy way out: Handling of attr could have been messier. 947436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// It turns out that pthread_cond_init under linux ignores 948436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// all information in cond_attr, so do we. 949436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// FIXME: MacOS X? 950436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov__attribute__((noinline)) 951436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic int pthread_cond_init_WRK(pthread_cond_t* cond, pthread_condattr_t *cond_attr) 952436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 953436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov int ret; 954436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov OrigFn fn; 955436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov VALGRIND_GET_ORIG_FN(fn); 956436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 957436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (TRACE_PTH_FNS) { 958436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fprintf(stderr, "<< pthread_cond_init %p", cond); 959436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fflush(stderr); 960436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 961436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 962436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CALL_FN_W_WW(ret, fn, cond, cond_attr); 963436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 964436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (ret == 0) { 965436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_INIT_POST, 966436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov pthread_cond_t*,cond, pthread_condattr_t*, cond_attr); 967436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 968436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DO_PthAPIerror( "pthread_cond_init", ret ); 969436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 970436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 971436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (TRACE_PTH_FNS) { 972436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fprintf(stderr, " coinit -> %d >>\n", ret); 973436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 974436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 975436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return ret; 976436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 977436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#if defined(VGO_linux) 978436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov PTH_FUNC(int, pthreadZucondZuinitZAZa, // pthread_cond_init@* 979436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov pthread_cond_t* cond, pthread_condattr_t* cond_attr) { 980436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return pthread_cond_init_WRK(cond, cond_attr); 981436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 982436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#elif defined(VGO_darwin) 983436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov PTH_FUNC(int, pthreadZucondZuinit, // pthread_cond_init 984436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov pthread_cond_t* cond, pthread_condattr_t * cond_attr) { 985436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return pthread_cond_init_WRK(cond, cond_attr); 986436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 987436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#else 988436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# error "Unsupported OS" 989436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif 990436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_cond_destroy@@GLIBC_2.3.2 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_cond_destroy@GLIBC_2.2.5 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_cond_destroy@GLIBC_2.0 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_destroy 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 998b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_cond_destroy_WRK(pthread_cond_t* cond) 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1002436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov unsigned long cond_is_init; 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_cond_destroy %p", cond); 1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1012436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (cond != NULL) { 1013436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const pthread_cond_t cond_init = PTHREAD_COND_INITIALIZER; 1014436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov cond_is_init = my_memcmp(cond, &cond_init, sizeof(*cond)) == 0; 1015436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 1016436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov cond_is_init = 0; 1017436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 1018436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 1019436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_DESTROY_PRE, 1020436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov pthread_cond_t*, cond, unsigned long, cond_is_init); 1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, cond); 1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0) { 1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_cond_destroy", ret ); 1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " codestr -> %d >>\n", ret); 1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZucondZudestroyZAZa, // pthread_cond_destroy@* 1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t* cond) { 1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_cond_destroy_WRK(cond); 1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZucondZudestroy, // pthread_cond_destroy 1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_cond_t* cond) { 1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_cond_destroy_WRK(cond); 1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- pthread_barrier_t functions ---*/ 1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(HAVE_PTHREAD_BARRIER_INIT) 1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handled: pthread_barrier_init 1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_barrier_wait 1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_barrier_destroy 1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Unhandled: pthread_barrierattr_destroy 1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_barrierattr_getpshared 1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_barrierattr_init 1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_barrierattr_setpshared 1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown -- are these important? 1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_barrier_init 1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: (doesn't appear to exist) 1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init 1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_barrier_t* bar, 1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_barrierattr_t* attr, unsigned long count) 1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_barrier_init %p %p %lu", 1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bar, attr, count); 1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_BARRIER_INIT_PRE, 1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_barrier_t*, bar, 1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long, count, 1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unsigned long, 0/*!resizable*/); 1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WWW(ret, fn, bar,attr,count); 1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0) { 1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_barrier_init", ret ); 1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " pthread_barrier_init -> %d >>\n", ret); 1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_barrier_wait 1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: (doesn't appear to exist) 1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait 1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_barrier_t* bar) 1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_barrier_wait %p", bar); 1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* That this works correctly, and doesn't screw up when a thread 1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown leaving the barrier races round to the front and re-enters while 1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown other threads are still leaving it, is quite subtle. See 1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown comments in the handler for PTHREAD_BARRIER_WAIT_PRE in 1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hg_main.c. */ 1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_WAIT_PRE, 1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_barrier_t*,bar); 1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, bar); 1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) { 1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_barrier_wait", ret ); 1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " pthread_barrier_wait -> %d >>\n", ret); 1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_barrier_destroy 1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: (doesn't appear to exist) 1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy 1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_barrier_t* bar) 1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_barrier_destroy %p", bar); 1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_DESTROY_PRE, 1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_barrier_t*,bar); 1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, bar); 1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0) { 1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_barrier_destroy", ret ); 1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " pthread_barrier_destroy -> %d >>\n", ret); 1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(HAVE_PTHREAD_BARRIER_INIT) 1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- pthread_spinlock_t functions ---*/ 1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1177436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#if defined(HAVE_PTHREAD_SPIN_LOCK) \ 1178436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov && !defined(DISABLE_PTHREAD_SPINLOCK_INTERCEPT) 1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handled: pthread_spin_init pthread_spin_destroy 1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_spin_lock pthread_spin_trylock 1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_spin_unlock 1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Unhandled: 1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is a nasty kludge, in that glibc "knows" that initialising a 1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown spin lock unlocks it, and pthread_spin_{init,unlock} are names for 1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the same function. Hence we have to have a wrapper which does both 1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown things, without knowing which the user intended to happen. */ 1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_spin_init 1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_spin_unlock 1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: (doesn't appear to exist) 1196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_spin_init_or_unlock_WRK(pthread_spinlock_t* lock, 1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int pshared) { 1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_spin_iORu %p", lock); fflush(stderr); 1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE, 1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_spinlock_t*, lock); 1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WW(ret, fn, lock,pshared); 1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 /*success*/) { 1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST, 1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_spinlock_t*,lock); 1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_spinlock_{init,unlock}", ret ); 1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: spiniORu -> %d >>\n", ret); 1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init 1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_spinlock_t* lock, int pshared) { 1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_spin_init_or_unlock_WRK(lock, pshared); 1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock 1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_spinlock_t* lock) { 1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* this is never actually called */ 1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_spin_init_or_unlock_WRK(lock, 0/*pshared*/); 1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_spin_destroy 1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: (doesn't appear to exist) 1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy 1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_spinlock_t* lock) 1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_spin_destroy %p", lock); 1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_DESTROY_PRE, 1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_spinlock_t*,lock); 1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, lock); 1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0) { 1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_spin_destroy", ret ); 1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: spindestroy -> %d >>\n", ret); 1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_spin_lock 1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: (doesn't appear to exist) 1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock 1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_spinlock_t* lock) 1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_spinlock %p", lock); 1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE, 1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_spinlock_t*,lock, long,0/*!isTryLock*/); 1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, lock); 1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There's a hole here: libpthread now knows the lock is locked, 1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but the tool doesn't, so some other thread could run and detect 1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that the lock has been acquired by someone (this thread). Does 1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this matter? Not sure, but I don't think so. */ 1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 /*success*/) { 1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST, 1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_spinlock_t*,lock); 1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_spin_lock", ret ); 1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: spinlock -> %d >>\n", ret); 1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_spin_trylock 1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: (doesn't appear to exist) 1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock 1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_spinlock_t* lock) 1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_spin_trylock %p", lock); 1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE, 1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_spinlock_t*,lock, long,1/*isTryLock*/); 1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, lock); 1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There's a hole here: libpthread now knows the lock is locked, 1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but the tool doesn't, so some other thread could run and detect 1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that the lock has been acquired by someone (this thread). Does 1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this matter? Not sure, but I don't think so. */ 1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 /*success*/) { 1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST, 1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_spinlock_t*,lock); 1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != EBUSY) 1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_spin_trylock", ret ); 1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: spin_trylock -> %d >>\n", ret); 1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(HAVE_PTHREAD_SPIN_LOCK) 1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- pthread_rwlock_t functions ---*/ 1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Android's pthread.h doesn't say anything about rwlocks, hence these 1374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov functions have to be conditionally compiled. */ 1375b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(HAVE_PTHREAD_RWLOCK_T) 1376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handled: pthread_rwlock_init pthread_rwlock_destroy 1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_rdlock 1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_wrlock 1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_unlock 1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Unhandled: pthread_rwlock_timedrdlock 1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_tryrdlock 1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_timedwrlock 1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_trywrlock 1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_rwlock_init 1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_init 1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_init$UNIX2003 1393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_rwlock_init_WRK(pthread_rwlock_t *rwl, 1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlockattr_t* attr) 1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_rwl_init %p", rwl); fflush(stderr); 1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WW(ret, fn, rwl,attr); 1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 /*success*/) { 1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST, 1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t*,rwl); 1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_rwlock_init", ret ); 1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: rwl_init -> %d >>\n", ret); 1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZurwlockZuinit, // pthread_rwlock_init 1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t *rwl, 1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlockattr_t* attr) { 1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_rwlock_init_WRK(rwl, attr); 1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZurwlockZuinitZa, // pthread_rwlock_init* 1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t *rwl, 1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlockattr_t* attr) { 1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_rwlock_init_WRK(rwl, attr); 1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_rwlock_destroy 1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_destroy 1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_destroy$UNIX2003 1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_rwlock_destroy_WRK(pthread_rwlock_t* rwl) 1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_rwl_destroy %p", rwl); fflush(stderr); 1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE, 1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t*,rwl); 1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, rwl); 1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0) { 1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_rwlock_destroy", ret ); 1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: rwl_destroy -> %d >>\n", ret); 1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZurwlockZudestroy, // pthread_rwlock_destroy 1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t *rwl) { 1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_rwlock_destroy_WRK(rwl); 1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZurwlockZudestroyZa, // pthread_rwlock_destroy* 1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t *rwl) { 1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_rwlock_destroy_WRK(rwl); 1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_rwlock_wrlock 1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_wrlock 1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_wrlock$UNIX2003 1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_rwlock_wrlock_WRK(pthread_rwlock_t* rwlock) 1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_rwl_wlk %p", rwlock); fflush(stderr); 1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE, 1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t*,rwlock, 1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown long,1/*isW*/, long,0/*!isTryLock*/); 1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, rwlock); 1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 /*success*/) { 1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST, 1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t*,rwlock, long,1/*isW*/); 1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_rwlock_wrlock", ret ); 1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: rwl_wlk -> %d >>\n", ret); 1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZurwlockZuwrlock, // pthread_rwlock_wrlock 1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t* rwlock) { 1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_rwlock_wrlock_WRK(rwlock); 1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZurwlockZuwrlockZa, // pthread_rwlock_wrlock* 1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t* rwlock) { 1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_rwlock_wrlock_WRK(rwlock); 1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_rwlock_rdlock 1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_rdlock 1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_rdlock$UNIX2003 1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_rwlock_rdlock_WRK(pthread_rwlock_t* rwlock) 1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_rwl_rlk %p", rwlock); fflush(stderr); 1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE, 1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t*,rwlock, 1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown long,0/*!isW*/, long,0/*!isTryLock*/); 1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, rwlock); 1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 /*success*/) { 1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST, 1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t*,rwlock, long,0/*!isW*/); 1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_rwlock_rdlock", ret ); 1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: rwl_rlk -> %d >>\n", ret); 1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZurwlockZurdlock, // pthread_rwlock_rdlock 1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t* rwlock) { 1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_rwlock_rdlock_WRK(rwlock); 1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZurwlockZurdlockZa, // pthread_rwlock_rdlock* 1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t* rwlock) { 1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_rwlock_rdlock_WRK(rwlock); 1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_rwlock_trywrlock 1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_trywrlock 1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_trywrlock$UNIX2003 1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_rwlock_trywrlock_WRK(pthread_rwlock_t* rwlock) 1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_rwl_trywlk %p", rwlock); fflush(stderr); 1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE, 1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t*,rwlock, 1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown long,1/*isW*/, long,1/*isTryLock*/); 1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, rwlock); 1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There's a hole here: libpthread now knows the lock is locked, 1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but the tool doesn't, so some other thread could run and detect 1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that the lock has been acquired by someone (this thread). Does 1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this matter? Not sure, but I don't think so. */ 1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 /*success*/) { 1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST, 1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t*,rwlock, long,1/*isW*/); 1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != EBUSY) 1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_rwlock_trywrlock", ret ); 1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: rwl_trywlk -> %d >>\n", ret); 1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZurwlockZutrywrlock, // pthread_rwlock_trywrlock 1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t* rwlock) { 1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_rwlock_trywrlock_WRK(rwlock); 1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZurwlockZutrywrlockZa, // pthread_rwlock_trywrlock* 1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t* rwlock) { 1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_rwlock_trywrlock_WRK(rwlock); 1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_rwlock_tryrdlock 1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_trywrlock 1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_trywrlock$UNIX2003 1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_rwlock_tryrdlock_WRK(pthread_rwlock_t* rwlock) 1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_rwl_tryrlk %p", rwlock); fflush(stderr); 1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE, 1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t*,rwlock, 1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown long,0/*!isW*/, long,1/*isTryLock*/); 1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, rwlock); 1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* There's a hole here: libpthread now knows the lock is locked, 1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown but the tool doesn't, so some other thread could run and detect 1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown that the lock has been acquired by someone (this thread). Does 1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this matter? Not sure, but I don't think so. */ 1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 /*success*/) { 1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST, 1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t*,rwlock, long,0/*!isW*/); 1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != EBUSY) 1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_rwlock_tryrdlock", ret ); 1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: rwl_tryrlk -> %d >>\n", ret); 1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZurwlockZutryrdlock, // pthread_rwlock_tryrdlock 1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t* rwlock) { 1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_rwlock_tryrdlock_WRK(rwlock); 1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZurwlockZutryrdlockZa, // pthread_rwlock_tryrdlock* 1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t* rwlock) { 1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_rwlock_tryrdlock_WRK(rwlock); 1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: pthread_rwlock_unlock 1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_unlock 1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_unlock$UNIX2003 1687b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_rwlock_unlock_WRK(pthread_rwlock_t* rwlock) 1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< pthread_rwl_unlk %p", rwlock); fflush(stderr); 1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE, 1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t*,rwlock); 1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, rwlock); 1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0 /*success*/) { 1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST, 1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t*,rwlock); 1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "pthread_rwlock_unlock", ret ); 1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_PTH_FNS) { 1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: rwl_unlk -> %d >>\n", ret); 1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZurwlockZuunlock, // pthread_rwlock_unlock 1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t* rwlock) { 1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_rwlock_unlock_WRK(rwlock); 1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, pthreadZurwlockZuunlockZa, // pthread_rwlock_unlock* 1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_rwlock_t* rwlock) { 1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return pthread_rwlock_unlock_WRK(rwlock); 1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1728b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif /* defined(HAVE_PTHREAD_RWLOCK_T) */ 1729b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- POSIX semaphores ---*/ 1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <semaphore.h> 1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <fcntl.h> /* O_CREAT */ 1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TRACE_SEM_FNS 0 1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handled: 1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int sem_init(sem_t *sem, int pshared, unsigned value); 1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int sem_destroy(sem_t *sem); 1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int sem_wait(sem_t *sem); 1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int sem_post(sem_t *sem); 1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sem_t* sem_open(const char *name, int oflag, 1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ... [mode_t mode, unsigned value]); 1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown [complete with its idiotic semantics] 1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int sem_close(sem_t* sem); 1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Unhandled: 1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int sem_trywait(sem_t *sem); 1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int sem_timedwait(sem_t *restrict sem, 1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const struct timespec *restrict abs_timeout); 1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: sem_init@@GLIBC_2.2.5 1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: sem_init@@GLIBC_2.1 1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: sem_init@GLIBC_2.0 1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: sem_init 1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1762b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int sem_init_WRK(sem_t* sem, int pshared, unsigned long value) 1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_SEM_FNS) { 1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< sem_init(%p,%d,%lu) ", sem,pshared,value); 1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WWW(ret, fn, sem,pshared,value); 1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0) { 1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST, 1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sem_t*, sem, unsigned long, value); 1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "sem_init", errno ); 1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_SEM_FNS) { 1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " sem_init -> %d >>\n", ret); 1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, semZuinitZAZa, // sem_init@* 1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sem_t* sem, int pshared, unsigned long value) { 1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sem_init_WRK(sem, pshared, value); 1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, semZuinit, // sem_init 1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sem_t* sem, int pshared, unsigned long value) { 1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sem_init_WRK(sem, pshared, value); 1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: sem_destroy@GLIBC_2.0 1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: sem_destroy@@GLIBC_2.1 1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: sem_destroy@@GLIBC_2.2.5 1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: sem_destroy 1810b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int sem_destroy_WRK(sem_t* sem) 1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_SEM_FNS) { 1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< sem_destroy(%p) ", sem); 1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, sem_t*, sem); 1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, sem); 1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0) { 1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "sem_destroy", errno ); 1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_SEM_FNS) { 1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " sem_destroy -> %d >>\n", ret); 1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, semZudestroyZAZa, // sem_destroy* 1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sem_t* sem) { 1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sem_destroy_WRK(sem); 1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, semZudestroy, // sem_destroy 1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sem_t* sem) { 1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sem_destroy_WRK(sem); 1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: sem_wait 1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: sem_wait@GLIBC_2.0 1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: sem_wait@@GLIBC_2.1 1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: sem_wait 1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: sem_wait$NOCANCEL$UNIX2003 1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: sem_wait$UNIX2003 1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* wait: decrement semaphore - acquire lockage */ 1861b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int sem_wait_WRK(sem_t* sem) 1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_SEM_FNS) { 1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< sem_wait(%p) ", sem); 1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, sem); 1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == 0) { 1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_WAIT_POST, sem_t*,sem); 1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "sem_wait", errno ); 1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_SEM_FNS) { 1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " sem_wait -> %d >>\n", ret); 1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */ 1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sem_wait_WRK(sem); 1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, semZuwaitZAZa, sem_t* sem) { /* sem_wait@* */ 1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sem_wait_WRK(sem); 1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */ 1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sem_wait_WRK(sem); 1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, semZuwaitZDZa, sem_t* sem) { /* sem_wait$* */ 1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sem_wait_WRK(sem); 1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: sem_post 1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: sem_post@GLIBC_2.0 1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: sem_post@@GLIBC_2.1 1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: sem_post 1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* post: increment semaphore - release lockage */ 1914b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline)) 1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int sem_post_WRK(sem_t* sem) 1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_SEM_FNS) { 1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< sem_post(%p) ", sem); 1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_POST_PRE, sem_t*,sem); 1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, sem); 1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0) { 1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "sem_post", errno ); 1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_SEM_FNS) { 1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " sem_post -> %d >>\n", ret); 1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux) 1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */ 1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sem_post_WRK(sem); 1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, semZupostZAZa, sem_t* sem) { /* sem_post@* */ 1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sem_post_WRK(sem); 1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */ 1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sem_post_WRK(sem); 1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unsupported OS" 1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: sem_open 1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: sem_open 1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(sem_t*, semZuopen, 1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const char* name, long oflag, 1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown long mode, unsigned long value) 1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* A copy of sem_init_WRK (more or less). Is this correct? */ 1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sem_t* ret; 1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_SEM_FNS) { 1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< sem_open(\"%s\",%ld,%lx,%lu) ", 1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown name,oflag,mode,value); 1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WWWW(ret, fn, name,oflag,mode,value); 1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != SEM_FAILED && (oflag & O_CREAT)) { 1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST, 1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sem_t*, ret, unsigned long, value); 1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret == SEM_FAILED) { 1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "sem_open", errno ); 1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_SEM_FNS) { 1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " sem_open -> %p >>\n", ret); 1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc: sem_close 1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: sem_close 1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, sem_close, sem_t* sem) 2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int ret; 2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_SEM_FNS) { 2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< sem_close(%p) ", sem); 2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, sem_t*, sem); 2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, sem); 2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret != 0) { 2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_PthAPIerror( "sem_close", errno ); 2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_SEM_FNS) { 2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " close -> %d >>\n", ret); 2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Qt 4 threading functions (w/ GNU name mangling) ---*/ 2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/ 2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handled: 2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QMutex::lock() 2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QMutex::unlock() 2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QMutex::tryLock() 2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QMutex::tryLock(int) 2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QMutex::QMutex(QMutex::RecursionMode) _ZN6QMutexC1ENS_13RecursionModeE 2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QMutex::QMutex(QMutex::RecursionMode) _ZN6QMutexC2ENS_13RecursionModeE 2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QMutex::~QMutex() _ZN6QMutexD1Ev 2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QMutex::~QMutex() _ZN6QMutexD2Ev 2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Unhandled: 2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QReadWriteLock::lockForRead() 2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QReadWriteLock::lockForWrite() 2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QReadWriteLock::unlock() 2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QReadWriteLock::tryLockForRead(int) 2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QReadWriteLock::tryLockForRead() 2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QReadWriteLock::tryLockForWrite(int) 2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QReadWriteLock::tryLockForWrite() 2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QWaitCondition::wait(QMutex*, unsigned long) 2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QWaitCondition::wakeAll() 2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QWaitCondition::wakeOne() 2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QSemaphore::* 2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* More comments, 19 Nov 08, based on assessment of qt-4.5.0TP1, 2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown at least on Unix: 2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown It's apparently only necessary to intercept QMutex, since that is 2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown not implemented using pthread_mutex_t; instead Qt4 has its own 2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown implementation based on atomics (to check the non-contended case) 2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and pthread_cond_wait (to wait in the contended case). 2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QReadWriteLock is built on top of QMutex, counters, and a wait 2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown queue. So we don't need to handle it specially once QMutex 2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown handling is correct -- presumably the dependencies through QMutex 2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown are sufficient to avoid any false race reports. On the other hand, 2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it is an open question whether too many dependencies are observed 2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown -- in which case we may miss races (false negatives). I suspect 2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this is likely to be the case, unfortunately. 2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QWaitCondition is built on pthread_cond_t, pthread_mutex_t, QMutex 2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and QReadWriteLock. Same compositional-correctness justificiation 2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and limitations as fro QReadWriteLock. 2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Ditto QSemaphore (from cursory examination). 2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Does it matter that only QMutex is handled directly? Open 2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown question. From testing with drd/tests/qt4_* and with KDE4 apps, it 2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown appears that no false errors are reported; however it is not clear 2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if this is causing false negatives. 2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Another problem with Qt4 is thread exiting. Threads are created 2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown with pthread_create (fine); but they detach and simply exit when 2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown done. There is no use of pthread_join, and the provided 2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wait-for-a-thread-to-exit mechanism (QThread::wait, I believe) 2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown relies on a system of mutexes and flags. I suspect this also 2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown causes too many dependencies to appear. Consequently H sometimes 2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fails to detect races at exit in some very short-lived racy 2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown programs, because it appears that a thread can exit _and_ have an 2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown observed dependency edge back to the main thread (presumably) 2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown before the main thread reaps the child (that is, calls 2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown QThread::wait). 2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This theory is supported by the observation that if all threads are 2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown made to wait at a pthread_barrier_t immediately before they exit, 2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown then H's detection of races in such programs becomes reliable; 2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown without the barrier, it is varies from run to run, depending 2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (according to investigation) on whether aforementioned 2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exit-before-reaping behaviour happens or not. 2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Finally, why is it necessary to intercept the QMutex constructors 2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and destructors? The constructors are intercepted only as a matter 2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of convenience, so H can print accurate "first observed at" 2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown clauses. However, it is actually necessary to intercept the 2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown destructors (as it is with pthread_mutex_destroy) in order that 2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown locks get removed from LAOG when they are destroyed. 2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// soname is libQtCore.so.4 ; match against libQtCore.so* 2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define QT4_FUNC(ret_ty, f, args...) \ 2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret_ty I_WRAP_SONAME_FNNAME_ZU(libQtCoreZdsoZa,f)(args); \ 2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret_ty I_WRAP_SONAME_FNNAME_ZU(libQtCoreZdsoZa,f)(args) 2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2116436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// soname is libQt5Core.so.4 ; match against libQt5Core.so* 2117436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#define QT5_FUNC(ret_ty, f, args...) \ 2118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ret_ty I_WRAP_SONAME_FNNAME_ZU(libQt5CoreZdsoZa,f)(args); \ 2119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ret_ty I_WRAP_SONAME_FNNAME_ZU(libQt5CoreZdsoZa,f)(args) 2120436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::lock() 2123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov__attribute__((noinline)) 2124436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void QMutex_lock_WRK(void* self) 2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_QT4_FNS) { 2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< QMutex::lock %p", self); fflush(stderr); 2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE, 2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void*,self, long,0/*!isTryLock*/); 2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_v_W(fn, self); 2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, 2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void*, self); 2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_QT4_FNS) { 2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: Q::lock done >>\n"); 2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2145436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovQT4_FUNC(void, _ZN6QMutex4lockEv, void* self) { 2146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov QMutex_lock_WRK(self); 2147436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 2148436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovQT5_FUNC(void, _ZN6QMutex4lockEv, void* self) { 2149436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov QMutex_lock_WRK(self); 2150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 2151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::unlock() 2154436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov__attribute__((noinline)) 2155436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void QMutex_unlock_WRK(void* self) 2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_QT4_FNS) { 2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< QMutex::unlock %p", self); fflush(stderr); 2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE, 2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void*, self); 2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_v_W(fn, self); 2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST, 2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void*, self); 2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_QT4_FNS) { 2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " Q::unlock done >>\n"); 2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2177436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovQT4_FUNC(void, _ZN6QMutex6unlockEv, void* self) { 2178436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov QMutex_unlock_WRK(self); 2179436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 2180436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovQT5_FUNC(void, _ZN6QMutex6unlockEv, void* self) { 2181436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov QMutex_unlock_WRK(self); 2182436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 2183436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// bool QMutex::tryLock() 2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// using 'long' to mimic C++ 'bool' 2187436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov__attribute__((noinline)) 2188436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic long QMutex_tryLock_WRK(void* self) 2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown long ret; 2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_QT4_FNS) { 2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< QMutex::tryLock %p", self); fflush(stderr); 2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE, 2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void*,self, long,1/*isTryLock*/); 2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, self); 2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // assumes that only the low 8 bits of the 'bool' are significant 2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret & 0xFF) { 2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, 2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void*, self); 2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_QT4_FNS) { 2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: Q::tryLock -> %lu >>\n", ret); 2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2215436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovQT4_FUNC(long, _ZN6QMutex7tryLockEv, void* self) { 2216436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return QMutex_tryLock_WRK(self); 2217436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 2218436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovQT5_FUNC(long, _ZN6QMutex7tryLockEv, void* self) { 2219436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return QMutex_tryLock_WRK(self); 2220436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 2221436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// bool QMutex::tryLock(int) 2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// using 'long' to mimic C++ 'bool' 2225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov__attribute__((noinline)) 2226436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic long QMutex_tryLock_int_WRK(void* self, long arg2) 2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown long ret; 2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_QT4_FNS) { 2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "<< QMutex::tryLock(int) %p %d", self, (int)arg2); 2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fflush(stderr); 2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE, 2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void*,self, long,1/*isTryLock*/); 2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WW(ret, fn, self,arg2); 2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // assumes that only the low 8 bits of the 'bool' are significant 2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret & 0xFF) { 2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, 2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void*, self); 2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (TRACE_QT4_FNS) { 2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, " :: Q::tryLock(int) -> %lu >>\n", ret); 2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ret; 2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2254436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovQT4_FUNC(long, _ZN6QMutex7tryLockEi, void* self, long arg2) { 2255436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return QMutex_tryLock_int_WRK(self, arg2); 2256436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 2257436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovQT5_FUNC(long, _ZN6QMutex7tryLockEi, void* self, long arg2) { 2258436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return QMutex_tryLock_int_WRK(self, arg2); 2259436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// It's not really very clear what the args are here. But from 2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// a bit of dataflow analysis of the generated machine code of 2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// the original function, it appears this takes two args, and 2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// returns nothing. Nevertheless preserve return value just in 2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// case. A bit of debug printing indicates that the first arg 2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// is that of the mutex and the second is either zero or one, 2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// probably being the recursion mode, therefore. 2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::QMutex(QMutex::RecursionMode) ("C1ENS" variant) 2270436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov__attribute__((noinline)) 2271436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void* QMutex_constructor_WRK(void* mutex, long recmode) 2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown long ret; 2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_WW(ret, fn, mutex, recmode); 2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // fprintf(stderr, "QMutex constructor 1: %p <- %p %p\n", ret, arg1, arg2); 2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST, 2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void*,mutex, long,1/*mbRec*/); 2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (void*)ret; 2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2283436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovQT4_FUNC(void*, _ZN6QMutexC1ENS_13RecursionModeE, void* self, long recmode) { 2284436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return QMutex_constructor_WRK(self, recmode); 2285436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 2286436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovQT5_FUNC(void*, _ZN6QMutexC1ENS_13RecursionModeE, void* self, long recmode) { 2287436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return QMutex_constructor_WRK(self, recmode); 2288436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 2289436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::~QMutex() ("D1Ev" variant) 2292436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov__attribute__((noinline)) 2293436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void* QMutex_destructor_WRK(void* mutex) 2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown OrigFn fn; 2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown long ret; 2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VALGRIND_GET_ORIG_FN(fn); 2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE, 2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void*,mutex); 2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown CALL_FN_W_W(ret, fn, mutex); 2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (void*)ret; 2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2304436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovQT4_FUNC(void*, _ZN6QMutexD1Ev, void* self) { 2305436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return QMutex_destructor_WRK(self); 2306436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 2307436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovQT5_FUNC(void*, _ZN6QMutexD1Ev, void* self) { 2308436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return QMutex_destructor_WRK(self); 2309436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----------------------------------------------------------- 2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::QMutex(QMutex::RecursionMode) ("C2ENS" variant) 2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4_FUNC(void*, _ZN6QMutexC2ENS_13RecursionModeE, 2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* mutex, 2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown long recmode) 2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(0); 2318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /*NOTREACHED*/ 2319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Android's gcc behaves like it doesn't know that assert(0) 2320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov never returns.