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.