hg_intercepts.c revision b32f58018498ea2225959b0ba11c18f0c433deef
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
11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Copyright (C) 2007-2011 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"
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "valgrind.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);                \
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      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
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* A lame version of strerror which doesn't use the real libc
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   strerror_r, since using the latter just generates endless more
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   threading errors (glibc goes off and does tons of crap w.r.t.
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   locales etc) */
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char* lame_strerror ( long err )
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{   switch (err) {
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case EPERM:       return "EPERM: Operation not permitted";
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ENOENT:      return "ENOENT: No such file or directory";
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ESRCH:       return "ESRCH: No such process";
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case EINTR:       return "EINTR: Interrupted system call";
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case EBADF:       return "EBADF: Bad file number";
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case EAGAIN:      return "EAGAIN: Try again";
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ENOMEM:      return "ENOMEM: Out of memory";
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case EACCES:      return "EACCES: Permission denied";
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case EFAULT:      return "EFAULT: Bad address";
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case EEXIST:      return "EEXIST: File exists";
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case EINVAL:      return "EINVAL: Invalid argument";
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case EMFILE:      return "EMFILE: Too many open files";
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ENOSYS:      return "ENOSYS: Function not implemented";
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case EOVERFLOW:   return "EOVERFLOW: Value too large "
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               "for defined data type";
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case EBUSY:       return "EBUSY: Device or resource busy";
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case ETIMEDOUT:   return "ETIMEDOUT: Connection timed out";
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case EDEADLK:     return "EDEADLK: Resource deadlock would occur";
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case EOPNOTSUPP:  return "EOPNOTSUPP: Operation not supported on "
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               "transport endpoint"; /* honest, guv */
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:          return "tc_intercepts.c: lame_strerror(): "
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               "unhandled case -- please fix me!";
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- pthread_create, pthread_join, pthread_exit               ---*/
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void* mythread_wrapper ( void* xargsV )
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   volatile Word* xargs = (volatile Word*) xargsV;
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void*(*fn)(void*) = (void*(*)(void*))xargs[0];
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void* arg         = (void*)xargs[1];
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   pthread_t me = pthread_self();
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Tell the tool what my pthread_t is. */
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_SET_MY_PTHREAD_T, pthread_t,me);
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* allow the parent to proceed.  We can't let it proceed until
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      we're ready because (1) we need to make sure it doesn't exit and
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      hence deallocate xargs[] while we still need it, and (2) we
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      don't want either parent nor child to proceed until the tool has
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      been notified of the child's pthread_t.
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Note that parent and child access args[] without a lock,
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      effectively using args[2] as a spinlock in order to get the
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      parent to wait until the child passes this point.  The parent
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      disables checking on xargs[] before creating the child and
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      re-enables it once the child goes past this point, so the user
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      never sees the race.  The previous approach (suppressing the
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      resulting error) was flawed, because it could leave shadow
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      memory for args[] in a state in which subsequent use of it by
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the parent would report further races. */
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xargs[2] = 0;
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Now we can no longer safely use xargs[]. */
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (void*) fn( (void*)arg );
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_create@GLIBC_2.0
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_create@@GLIBC_2.1
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_create@@GLIBC_2.2.5
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_create
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_create_suspended_np (trapped)
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ensure this has its own frame, so as to make it more distinguishable
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in suppressions */
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noinline))
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_create_WRK(pthread_t *thread, const pthread_attr_t *attr,
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              void *(*start) (void *), void *arg)
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   volatile Word xargs[3];
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_create wrapper"); fflush(stderr);
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xargs[0] = (Word)start;
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xargs[1] = (Word)arg;
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   xargs[2] = 1; /* serves as a spinlock -- sigh */
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Disable checking on the spinlock and the two words used to
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      convey args to the child.  Basically we need to make it appear
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      as if the child never accessed this area, since merely
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      suppressing the resulting races does not address the issue that
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      that piece of the parent's stack winds up in the "wrong" state
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      and therefore may give rise to mysterious races when the parent
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      comes to re-use this piece of stack in some other frame. */
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_HG_DISABLE_CHECKING(&xargs, sizeof(xargs));
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_WWWW(ret, fn, thread,attr,mythread_wrapper,&xargs[0]);
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0) {
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* we have to wait for the child to notify the tool of its
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pthread_t before continuing */
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (xargs[2] != 0) {
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Do nothing.  We need to spin until the child writes to
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            xargs[2].  However, that can lead to starvation in the
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            child and very long delays (eg, tc19_shadowmem on
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ppc64-linux Fedora Core 6).  So yield the cpu if we can,
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            to let the child run at the earliest available
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            opportunity. */
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sched_yield();
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_create", ret );
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Reenable checking on the area previously used to communicate
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      with the child. */
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_HG_ENABLE_CHECKING(&xargs, sizeof(xargs));
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: pth_create -> %d >>\n", ret);
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZucreateZAZa, // pthread_create@*
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_t *thread, const pthread_attr_t *attr,
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 void *(*start) (void *), void *arg) {
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_create_WRK(thread, attr, start, arg);
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZucreate, // pthread_create
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_t *thread, const pthread_attr_t *attr,
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 void *(*start) (void *), void *arg) {
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_create_WRK(thread, attr, start, arg);
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZucreateZuZa, // pthread_create_*
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_t *thread, const pthread_attr_t *attr,
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 void *(*start) (void *), void *arg) {
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // trap anything else
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assert(0);
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_join
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_join
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_join$NOCANCEL$UNIX2003
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin  pthread_join$UNIX2003
310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_join_WRK(pthread_t thread, void** value_pointer)
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int ret;
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_join wrapper"); fflush(stderr);
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_WW(ret, fn, thread,value_pointer);
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* At least with NPTL as the thread library, this is safe because
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      it is guaranteed (by NPTL) that the joiner will completely gone
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      before pthread_join (the original) returns.  See email below.*/
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 /*success*/) {
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_JOIN_POST, pthread_t,thread);
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_join", ret );
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: pth_join -> %d >>\n", ret);
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZujoin, // pthread_join
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pthread_t thread, void** value_pointer) {
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_join_WRK(thread, value_pointer);
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZujoinZa, // pthread_join*
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pthread_t thread, void** value_pointer) {
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_join_WRK(thread, value_pointer);
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Behaviour of pthread_join on NPTL:
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMe:
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownI have a question re the NPTL pthread_join implementation.
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Suppose I am the thread 'stayer'.
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  If I call pthread_join(quitter), is it guaranteed that the
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  thread 'quitter' has really exited before pthread_join returns?
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  IOW, is it guaranteed that 'quitter' will not execute any further
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  instructions after pthread_join returns?
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownI believe this is true based on the following analysis of
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownglibc-2.5 sources.  However am not 100% sure and would appreciate
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconfirmation.
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  'quitter' will be running start_thread() in nptl/pthread_create.c
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  The last action of start_thread() is to exit via
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  __exit_thread_inline(0), which simply does sys_exit
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (nptl/pthread_create.c:403)
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  'stayer' meanwhile is waiting for lll_wait_tid (pd->tid)
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (call at nptl/pthread_join.c:89)
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536,
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  lll_wait_tid will not return until kernel notifies via futex
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  wakeup that 'quitter' has terminated.
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Hence pthread_join cannot return until 'quitter' really has
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  completely disappeared.
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDrepper:
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown>   As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536,
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown>   lll_wait_tid will not return until kernel notifies via futex
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown>   wakeup that 'quitter' has terminated.
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownThat's the key.  The kernel resets the TID field after the thread is
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browndone.  No way the joiner can return before the thread is gone.
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- pthread_mutex_t functions                                ---*/
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handled:   pthread_mutex_init pthread_mutex_destroy
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_mutex_lock
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_mutex_trylock pthread_mutex_timedlock
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_mutex_unlock
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_mutex_init
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_mutex_init
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZumutexZuinit, // pthread_mutex_init
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_mutex_t *mutex,
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_mutexattr_t* attr)
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   long   mbRec;
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_mxinit %p", mutex); fflush(stderr);
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mbRec = 0;
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (attr) {
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      int ty, zzz;
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      zzz = pthread_mutexattr_gettype(attr, &ty);
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (zzz == 0 && ty == PTHREAD_MUTEX_RECURSIVE)
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mbRec = 1;
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_WW(ret, fn, mutex,attr);
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 /*success*/) {
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST,
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   pthread_mutex_t*,mutex, long,mbRec);
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_mutex_init", ret );
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: mxinit -> %d >>\n", ret);
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_mutex_destroy
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_mutex_destroy
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZumutexZudestroy, // pthread_mutex_destroy
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_mutex_t *mutex)
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_mxdestroy %p", mutex); fflush(stderr);
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE,
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               pthread_mutex_t*,mutex);
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, mutex);
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret != 0) {
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_mutex_destroy", ret );
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: mxdestroy -> %d >>\n", ret);
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_mutex_lock
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_mutex_lock
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_mutex_t *mutex)
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_mxlock %p", mutex); fflush(stderr);
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pthread_mutex_t*,mutex, long,0/*!isTryLock*/);
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, mutex);
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* There's a hole here: libpthread now knows the lock is locked,
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      but the tool doesn't, so some other thread could run and detect
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      that the lock has been acquired by someone (this thread).  Does
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this matter?  Not sure, but I don't think so. */
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 /*success*/) {
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  pthread_mutex_t*,mutex);
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_mutex_lock", ret );
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: mxlock -> %d >>\n", ret);
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_mutex_trylock
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_mutex_trylock
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// pthread_mutex_trylock.  The handling needed here is very similar
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// to that for pthread_mutex_lock, except that we need to tell
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// the pre-lock creq that this is a trylock-style operation, and
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// therefore not to complain if the lock is nonrecursive and
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// already locked by this thread -- because then it'll just fail
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// immediately with EBUSY.
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_mutex_t *mutex)
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_mxtrylock %p", mutex); fflush(stderr);
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pthread_mutex_t*,mutex, long,1/*isTryLock*/);
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, mutex);
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* There's a hole here: libpthread now knows the lock is locked,
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      but the tool doesn't, so some other thread could run and detect
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      that the lock has been acquired by someone (this thread).  Does
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this matter?  Not sure, but I don't think so. */
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 /*success*/) {
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  pthread_mutex_t*,mutex);
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ret != EBUSY)
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DO_PthAPIerror( "pthread_mutex_trylock", ret );
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: mxtrylock -> %d >>\n", ret);
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_mutex_timedlock
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: (doesn't appear to exist)
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// pthread_mutex_timedlock.  Identical logic to pthread_mutex_trylock.
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pthread_mutex_t *mutex,
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         void* timeout)
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_mxtimedlock %p %p", mutex, timeout);
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pthread_mutex_t*,mutex, long,1/*isTryLock-ish*/);
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_WW(ret, fn, mutex,timeout);
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* There's a hole here: libpthread now knows the lock is locked,
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      but the tool doesn't, so some other thread could run and detect
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      that the lock has been acquired by someone (this thread).  Does
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this matter?  Not sure, but I don't think so. */
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 /*success*/) {
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  pthread_mutex_t*,mutex);
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ret != ETIMEDOUT)
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DO_PthAPIerror( "pthread_mutex_timedlock", ret );
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: mxtimedlock -> %d >>\n", ret);
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_mutex_unlock
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_mutex_unlock
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_mutex_t *mutex)
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_mxunlk %p", mutex); fflush(stderr);
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               pthread_mutex_t*,mutex);
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, mutex);
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 /*success*/) {
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST,
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  pthread_mutex_t*,mutex);
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_mutex_unlock", ret );
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " mxunlk -> %d >>\n", ret);
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- pthread_cond_t functions                                 ---*/
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handled:   pthread_cond_wait pthread_cond_timedwait
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_cond_signal pthread_cond_broadcast
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_cond_destroy
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Unhandled: pthread_cond_init
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              -- is this important?
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_cond_wait@GLIBC_2.2.5
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_cond_wait@@GLIBC_2.3.2
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_wait
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_wait$NOCANCEL$UNIX2003
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_wait$UNIX2003
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_cond_wait_WRK(pthread_cond_t* cond,
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 pthread_mutex_t* mutex)
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int ret;
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned long mutex_is_valid;
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_cond_wait %p %p", cond, mutex);
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Tell the tool a cond-wait is about to happen, so it can check
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for bogus argument values.  In return it tells us whether it
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      thinks the mutex is valid or not. */
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_W_WW(mutex_is_valid,
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE,
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pthread_cond_t*,cond, pthread_mutex_t*,mutex);
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assert(mutex_is_valid == 1 || mutex_is_valid == 0);
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Tell the tool we're about to drop the mutex.  This reflects the
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fact that in a cond_wait, we show up holding the mutex, and the
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      call atomically drops the mutex and waits for the cv to be
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      signalled. */
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mutex_is_valid) {
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  pthread_mutex_t*,mutex);
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_WW(ret, fn, cond,mutex);
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* these conditionals look stupid, but compare w/ same logic for
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pthread_cond_timedwait below */
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 && mutex_is_valid) {
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* and now we have the mutex again */
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  pthread_mutex_t*,mutex);
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 && mutex_is_valid) {
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST,
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   pthread_cond_t*,cond, pthread_mutex_t*,mutex);
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret != 0) {
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_cond_wait", ret );
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " cowait -> %d >>\n", ret);
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZucondZuwaitZAZa, // pthread_cond_wait@*
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_cond_t* cond, pthread_mutex_t* mutex) {
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_cond_wait_WRK(cond, mutex);
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait*
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_cond_t* cond, pthread_mutex_t* mutex) {
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_cond_wait_WRK(cond, mutex);
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_cond_timedwait@@GLIBC_2.3.2
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_cond_timedwait@GLIBC_2.2.5
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_cond_timedwait@GLIBC_2.0
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_timedwait
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_timedwait$NOCANCEL$UNIX2003
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_timedwait$UNIX2003
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_timedwait_relative_np (trapped)
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
728b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_cond_timedwait_WRK(pthread_cond_t* cond,
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      pthread_mutex_t* mutex,
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      struct timespec* abstime)
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int ret;
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   unsigned long mutex_is_valid;
736b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Bool abstime_is_valid;
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_cond_timedwait %p %p %p",
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      cond, mutex, abstime);
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Tell the tool a cond-wait is about to happen, so it can check
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for bogus argument values.  In return it tells us whether it
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      thinks the mutex is valid or not. */
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_W_WW(mutex_is_valid,
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE,
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pthread_cond_t*,cond, pthread_mutex_t*,mutex);
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assert(mutex_is_valid == 1 || mutex_is_valid == 0);
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
753b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   abstime_is_valid = abstime->tv_nsec >= 0 && abstime->tv_nsec < 1000000000;
754b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Tell the tool we're about to drop the mutex.  This reflects the
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fact that in a cond_wait, we show up holding the mutex, and the
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      call atomically drops the mutex and waits for the cv to be
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      signalled. */
759b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (mutex_is_valid && abstime_is_valid) {
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  pthread_mutex_t*,mutex);
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_WWW(ret, fn, cond,mutex,abstime);
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
766b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (!abstime_is_valid && ret != EINVAL) {
767b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DO_PthAPIerror("Bug in libpthread: pthread_cond_timedwait "
768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     "invalid abstime did not cause"
769b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     " EINVAL", ret);
770b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((ret == 0 || ret == ETIMEDOUT) && mutex_is_valid) {
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* and now we have the mutex again */
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  pthread_mutex_t*,mutex);
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 && mutex_is_valid) {
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST,
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   pthread_cond_t*,cond, pthread_mutex_t*,mutex);
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret != 0 && ret != ETIMEDOUT) {
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_cond_timedwait", ret );
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " cotimedwait -> %d >>\n", ret);
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZucondZutimedwaitZAZa, // pthread_cond_timedwait@*
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_cond_t* cond, pthread_mutex_t* mutex,
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 struct timespec* abstime) {
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_cond_timedwait_WRK(cond, mutex, abstime);
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZucondZutimedwait, // pthread_cond_timedwait
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_cond_t* cond, pthread_mutex_t* mutex,
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 struct timespec* abstime) {
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_cond_timedwait_WRK(cond, mutex, abstime);
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZucondZutimedwaitZDZa, // pthread_cond_timedwait$*
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_cond_t* cond, pthread_mutex_t* mutex,
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 struct timespec* abstime) {
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_cond_timedwait_WRK(cond, mutex, abstime);
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZucondZutimedwaitZuZa, // pthread_cond_timedwait_*
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_cond_t* cond, pthread_mutex_t* mutex,
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 struct timespec* abstime) {
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assert(0);
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_cond_signal@GLIBC_2.0
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_cond_signal@GLIBC_2.2.5
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_cond_signal@@GLIBC_2.3.2
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_signal
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_signal_thread_np (don't intercept this)
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
827b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_cond_signal_WRK(pthread_cond_t* cond)
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int ret;
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_cond_signal %p", cond);
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_SIGNAL_PRE,
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               pthread_cond_t*,cond);
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, cond);
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret != 0) {
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_cond_signal", ret );
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " cosig -> %d >>\n", ret);
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZucondZusignalZAZa, // pthread_cond_signal@*
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_cond_t* cond) {
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_cond_signal_WRK(cond);
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZucondZusignal, // pthread_cond_signal
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_cond_t* cond) {
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_cond_signal_WRK(cond);
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_cond_broadcast@GLIBC_2.0
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_cond_broadcast@GLIBC_2.2.5
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_cond_broadcast@@GLIBC_2.3.2
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_broadcast
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Note, this is pretty much identical, from a dependency-graph
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// point of view, with cond_signal, so the code is duplicated.
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Maybe it should be commoned up.
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
879b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_cond_broadcast_WRK(pthread_cond_t* cond)
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int ret;
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_cond_broadcast %p", cond);
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_BROADCAST_PRE,
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               pthread_cond_t*,cond);
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, cond);
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret != 0) {
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_cond_broadcast", ret );
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " cobro -> %d >>\n", ret);
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZucondZubroadcastZAZa, // pthread_cond_broadcast@*
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_cond_t* cond) {
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_cond_broadcast_WRK(cond);
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZucondZubroadcast, // pthread_cond_broadcast
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_cond_t* cond) {
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_cond_broadcast_WRK(cond);
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#   error "Unsupported OS"
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_cond_destroy@@GLIBC_2.3.2
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_cond_destroy@GLIBC_2.2.5
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_cond_destroy@GLIBC_2.0
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_cond_destroy
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
927b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_cond_destroy_WRK(pthread_cond_t* cond)
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int ret;
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_cond_destroy %p", cond);
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_DESTROY_PRE,
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               pthread_cond_t*,cond);
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, cond);
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret != 0) {
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_cond_destroy", ret );
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " codestr -> %d >>\n", ret);
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZucondZudestroyZAZa, // pthread_cond_destroy@*
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_cond_t* cond) {
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_cond_destroy_WRK(cond);
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZucondZudestroy, // pthread_cond_destroy
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_cond_t* cond) {
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_cond_destroy_WRK(cond);
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- pthread_barrier_t functions                              ---*/
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(HAVE_PTHREAD_BARRIER_INIT)
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handled:   pthread_barrier_init
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_barrier_wait
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_barrier_destroy
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Unhandled: pthread_barrierattr_destroy
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_barrierattr_getpshared
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_barrierattr_init
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_barrierattr_setpshared
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              -- are these important?
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_barrier_init
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: (doesn't appear to exist)
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pthread_barrier_t* bar,
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pthread_barrierattr_t* attr, unsigned long count)
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int ret;
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_barrier_init %p %p %lu",
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      bar, attr, count);
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_BARRIER_INIT_PRE,
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_barrier_t*, bar,
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned long, count,
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned long, 0/*!resizable*/);
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_WWW(ret, fn, bar,attr,count);
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret != 0) {
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_barrier_init", ret );
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "  pthread_barrier_init -> %d >>\n", ret);
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_barrier_wait
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: (doesn't appear to exist)
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_barrier_t* bar)
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int ret;
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_barrier_wait %p", bar);
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* That this works correctly, and doesn't screw up when a thread
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      leaving the barrier races round to the front and re-enters while
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      other threads are still leaving it, is quite subtle.  See
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      comments in the handler for PTHREAD_BARRIER_WAIT_PRE in
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      hg_main.c. */
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_WAIT_PRE,
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               pthread_barrier_t*,bar);
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, bar);
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_barrier_wait", ret );
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "  pthread_barrier_wait -> %d >>\n", ret);
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_barrier_destroy
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: (doesn't appear to exist)
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pthread_barrier_t* bar)
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int ret;
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_barrier_destroy %p", bar);
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_DESTROY_PRE,
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               pthread_barrier_t*,bar);
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, bar);
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret != 0) {
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_barrier_destroy", ret );
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "  pthread_barrier_destroy -> %d >>\n", ret);
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif   // defined(HAVE_PTHREAD_BARRIER_INIT)
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- pthread_spinlock_t functions                             ---*/
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(HAVE_PTHREAD_SPIN_LOCK)
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handled:   pthread_spin_init pthread_spin_destroy
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_spin_lock pthread_spin_trylock
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_spin_unlock
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Unhandled:
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This is a nasty kludge, in that glibc "knows" that initialising a
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   spin lock unlocks it, and pthread_spin_{init,unlock} are names for
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the same function.  Hence we have to have a wrapper which does both
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   things, without knowing which the user intended to happen. */
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_spin_init
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_spin_unlock
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: (doesn't appear to exist)
1116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_spin_init_or_unlock_WRK(pthread_spinlock_t* lock,
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           int pshared) {
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_spin_iORu %p", lock); fflush(stderr);
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE,
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               pthread_spinlock_t*, lock);
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_WW(ret, fn, lock,pshared);
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 /*success*/) {
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST,
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  pthread_spinlock_t*,lock);
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_spinlock_{init,unlock}", ret );
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: spiniORu -> %d >>\n", ret);
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pthread_spinlock_t* lock, int pshared) {
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_spin_init_or_unlock_WRK(lock, pshared);
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pthread_spinlock_t* lock) {
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* this is never actually called */
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_spin_init_or_unlock_WRK(lock, 0/*pshared*/);
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_spin_destroy
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: (doesn't appear to exist)
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_spinlock_t* lock)
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_spin_destroy %p", lock);
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_DESTROY_PRE,
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               pthread_spinlock_t*,lock);
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, lock);
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret != 0) {
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_spin_destroy", ret );
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: spindestroy -> %d >>\n", ret);
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_spin_lock
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: (doesn't appear to exist)
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_spinlock_t* lock)
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_spinlock %p", lock);
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE,
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pthread_spinlock_t*,lock, long,0/*!isTryLock*/);
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, lock);
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* There's a hole here: libpthread now knows the lock is locked,
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      but the tool doesn't, so some other thread could run and detect
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      that the lock has been acquired by someone (this thread).  Does
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this matter?  Not sure, but I don't think so. */
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 /*success*/) {
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST,
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  pthread_spinlock_t*,lock);
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_spin_lock", ret );
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: spinlock -> %d >>\n", ret);
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_spin_trylock
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: (doesn't appear to exist)
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_spinlock_t* lock)
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_spin_trylock %p", lock);
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE,
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                pthread_spinlock_t*,lock, long,1/*isTryLock*/);
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, lock);
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* There's a hole here: libpthread now knows the lock is locked,
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      but the tool doesn't, so some other thread could run and detect
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      that the lock has been acquired by someone (this thread).  Does
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this matter?  Not sure, but I don't think so. */
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 /*success*/) {
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST,
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  pthread_spinlock_t*,lock);
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ret != EBUSY)
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DO_PthAPIerror( "pthread_spin_trylock", ret );
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: spin_trylock -> %d >>\n", ret);
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(HAVE_PTHREAD_SPIN_LOCK)
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- pthread_rwlock_t functions                               ---*/
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Android's pthread.h doesn't say anything about rwlocks, hence these
1294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   functions have to be conditionally compiled. */
1295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(HAVE_PTHREAD_RWLOCK_T)
1296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handled:   pthread_rwlock_init pthread_rwlock_destroy
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_rwlock_rdlock
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_rwlock_wrlock
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_rwlock_unlock
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Unhandled: pthread_rwlock_timedrdlock
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_rwlock_tryrdlock
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_rwlock_timedwrlock
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              pthread_rwlock_trywrlock
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_rwlock_init
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_init
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_init$UNIX2003
1313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_rwlock_init_WRK(pthread_rwlock_t *rwl,
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   pthread_rwlockattr_t* attr)
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_rwl_init %p", rwl); fflush(stderr);
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_WW(ret, fn, rwl,attr);
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 /*success*/) {
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST,
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  pthread_rwlock_t*,rwl);
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_rwlock_init", ret );
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: rwl_init -> %d >>\n", ret);
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZurwlockZuinit, // pthread_rwlock_init
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t *rwl,
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlockattr_t* attr) {
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_rwlock_init_WRK(rwl, attr);
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZurwlockZuinitZa, // pthread_rwlock_init*
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t *rwl,
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlockattr_t* attr) {
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_rwlock_init_WRK(rwl, attr);
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_rwlock_destroy
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_destroy
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_destroy$UNIX2003
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_rwlock_destroy_WRK(pthread_rwlock_t* rwl)
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_rwl_destroy %p", rwl); fflush(stderr);
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE,
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               pthread_rwlock_t*,rwl);
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, rwl);
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret != 0) {
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_rwlock_destroy", ret );
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: rwl_destroy -> %d >>\n", ret);
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZurwlockZudestroy, // pthread_rwlock_destroy
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t *rwl) {
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_rwlock_destroy_WRK(rwl);
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZurwlockZudestroyZa, // pthread_rwlock_destroy*
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t *rwl) {
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_rwlock_destroy_WRK(rwl);
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_rwlock_wrlock
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_wrlock
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_wrlock$UNIX2003
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_rwlock_wrlock_WRK(pthread_rwlock_t* rwlock)
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_rwl_wlk %p", rwlock); fflush(stderr);
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t*,rwlock,
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 long,1/*isW*/, long,0/*!isTryLock*/);
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, rwlock);
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 /*success*/) {
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   pthread_rwlock_t*,rwlock, long,1/*isW*/);
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_rwlock_wrlock", ret );
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: rwl_wlk -> %d >>\n", ret);
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZurwlockZuwrlock, // pthread_rwlock_wrlock
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t* rwlock) {
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_rwlock_wrlock_WRK(rwlock);
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZurwlockZuwrlockZa, // pthread_rwlock_wrlock*
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t* rwlock) {
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_rwlock_wrlock_WRK(rwlock);
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_rwlock_rdlock
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_rdlock
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_rdlock$UNIX2003
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_rwlock_rdlock_WRK(pthread_rwlock_t* rwlock)
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_rwl_rlk %p", rwlock); fflush(stderr);
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t*,rwlock,
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 long,0/*!isW*/, long,0/*!isTryLock*/);
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, rwlock);
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 /*success*/) {
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   pthread_rwlock_t*,rwlock, long,0/*!isW*/);
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_rwlock_rdlock", ret );
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: rwl_rlk -> %d >>\n", ret);
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZurwlockZurdlock, // pthread_rwlock_rdlock
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t* rwlock) {
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_rwlock_rdlock_WRK(rwlock);
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZurwlockZurdlockZa, // pthread_rwlock_rdlock*
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t* rwlock) {
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_rwlock_rdlock_WRK(rwlock);
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_rwlock_trywrlock
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_trywrlock
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_trywrlock$UNIX2003
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_rwlock_trywrlock_WRK(pthread_rwlock_t* rwlock)
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_rwl_trywlk %p", rwlock); fflush(stderr);
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t*,rwlock,
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 long,1/*isW*/, long,1/*isTryLock*/);
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, rwlock);
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* There's a hole here: libpthread now knows the lock is locked,
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      but the tool doesn't, so some other thread could run and detect
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      that the lock has been acquired by someone (this thread).  Does
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this matter?  Not sure, but I don't think so. */
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 /*success*/) {
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   pthread_rwlock_t*,rwlock, long,1/*isW*/);
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ret != EBUSY)
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DO_PthAPIerror( "pthread_rwlock_trywrlock", ret );
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: rwl_trywlk -> %d >>\n", ret);
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZurwlockZutrywrlock, // pthread_rwlock_trywrlock
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t* rwlock) {
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_rwlock_trywrlock_WRK(rwlock);
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZurwlockZutrywrlockZa, // pthread_rwlock_trywrlock*
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t* rwlock) {
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_rwlock_trywrlock_WRK(rwlock);
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_rwlock_tryrdlock
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_trywrlock
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_trywrlock$UNIX2003
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_rwlock_tryrdlock_WRK(pthread_rwlock_t* rwlock)
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_rwl_tryrlk %p", rwlock); fflush(stderr);
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t*,rwlock,
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 long,0/*!isW*/, long,1/*isTryLock*/);
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, rwlock);
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* There's a hole here: libpthread now knows the lock is locked,
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      but the tool doesn't, so some other thread could run and detect
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      that the lock has been acquired by someone (this thread).  Does
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this matter?  Not sure, but I don't think so. */
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 /*success*/) {
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   pthread_rwlock_t*,rwlock, long,0/*!isW*/);
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ret != EBUSY)
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DO_PthAPIerror( "pthread_rwlock_tryrdlock", ret );
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: rwl_tryrlk -> %d >>\n", ret);
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZurwlockZutryrdlock, // pthread_rwlock_tryrdlock
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t* rwlock) {
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_rwlock_tryrdlock_WRK(rwlock);
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZurwlockZutryrdlockZa, // pthread_rwlock_tryrdlock*
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t* rwlock) {
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_rwlock_tryrdlock_WRK(rwlock);
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  pthread_rwlock_unlock
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_unlock
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: pthread_rwlock_unlock$UNIX2003
1607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int pthread_rwlock_unlock_WRK(pthread_rwlock_t* rwlock)
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< pthread_rwl_unlk %p", rwlock); fflush(stderr);
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE,
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               pthread_rwlock_t*,rwlock);
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, rwlock);
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0 /*success*/) {
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST,
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  pthread_rwlock_t*,rwlock);
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "pthread_rwlock_unlock", ret );
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_PTH_FNS) {
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: rwl_unlk -> %d >>\n", ret);
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZurwlockZuunlock, // pthread_rwlock_unlock
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t* rwlock) {
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_rwlock_unlock_WRK(rwlock);
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, pthreadZurwlockZuunlockZa, // pthread_rwlock_unlock*
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 pthread_rwlock_t* rwlock) {
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return pthread_rwlock_unlock_WRK(rwlock);
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif /* defined(HAVE_PTHREAD_RWLOCK_T) */
1649b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- POSIX semaphores                                         ---*/
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <semaphore.h>
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <fcntl.h>       /* O_CREAT */
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define TRACE_SEM_FNS 0
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handled:
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     int sem_init(sem_t *sem, int pshared, unsigned value);
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     int sem_destroy(sem_t *sem);
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     int sem_wait(sem_t *sem);
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     int sem_post(sem_t *sem);
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     sem_t* sem_open(const char *name, int oflag,
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ... [mode_t mode, unsigned value]);
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        [complete with its idiotic semantics]
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     int sem_close(sem_t* sem);
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Unhandled:
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     int sem_trywait(sem_t *sem);
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     int sem_timedwait(sem_t *restrict sem,
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       const struct timespec *restrict abs_timeout);
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  sem_init@@GLIBC_2.2.5
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  sem_init@@GLIBC_2.1
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  sem_init@GLIBC_2.0
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: sem_init
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int sem_init_WRK(sem_t* sem, int pshared, unsigned long value)
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_SEM_FNS) {
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< sem_init(%p,%d,%lu) ", sem,pshared,value);
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_WWW(ret, fn, sem,pshared,value);
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0) {
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST,
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   sem_t*, sem, unsigned long, value);
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "sem_init", errno );
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_SEM_FNS) {
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " sem_init -> %d >>\n", ret);
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, semZuinitZAZa, // sem_init@*
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 sem_t* sem, int pshared, unsigned long value) {
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return sem_init_WRK(sem, pshared, value);
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, semZuinit, // sem_init
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 sem_t* sem, int pshared, unsigned long value) {
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return sem_init_WRK(sem, pshared, value);
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  sem_destroy@GLIBC_2.0
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  sem_destroy@@GLIBC_2.1
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  sem_destroy@@GLIBC_2.2.5
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: sem_destroy
1730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int sem_destroy_WRK(sem_t* sem)
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_SEM_FNS) {
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< sem_destroy(%p) ", sem);
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, sem_t*, sem);
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, sem);
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret != 0) {
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "sem_destroy", errno );
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_SEM_FNS) {
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " sem_destroy -> %d >>\n", ret);
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, semZudestroyZAZa,  // sem_destroy*
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 sem_t* sem) {
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return sem_destroy_WRK(sem);
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, semZudestroy,  // sem_destroy
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 sem_t* sem) {
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return sem_destroy_WRK(sem);
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  sem_wait
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  sem_wait@GLIBC_2.0
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  sem_wait@@GLIBC_2.1
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: sem_wait
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: sem_wait$NOCANCEL$UNIX2003
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: sem_wait$UNIX2003
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* wait: decrement semaphore - acquire lockage */
1781b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int sem_wait_WRK(sem_t* sem)
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_SEM_FNS) {
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< sem_wait(%p) ", sem);
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, sem);
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == 0) {
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_WAIT_POST, sem_t*,sem);
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "sem_wait", errno );
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_SEM_FNS) {
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " sem_wait -> %d >>\n", ret);
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return sem_wait_WRK(sem);
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, semZuwaitZAZa, sem_t* sem) { /* sem_wait@* */
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return sem_wait_WRK(sem);
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return sem_wait_WRK(sem);
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, semZuwaitZDZa, sem_t* sem) { /* sem_wait$* */
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return sem_wait_WRK(sem);
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  sem_post
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  sem_post@GLIBC_2.0
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  sem_post@@GLIBC_2.1
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: sem_post
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* post: increment semaphore - release lockage */
1834b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov__attribute__((noinline))
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int sem_post_WRK(sem_t* sem)
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_SEM_FNS) {
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< sem_post(%p) ", sem);
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_POST_PRE, sem_t*,sem);
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, sem);
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret != 0) {
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "sem_post", errno );
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_SEM_FNS) {
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " sem_post -> %d >>\n", ret);
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return sem_post_WRK(sem);
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, semZupostZAZa, sem_t* sem) { /* sem_post@* */
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return sem_post_WRK(sem);
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin)
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return sem_post_WRK(sem);
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  error "Unsupported OS"
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  sem_open
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: sem_open
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(sem_t*, semZuopen,
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 const char* name, long oflag,
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 long mode, unsigned long value)
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* A copy of sem_init_WRK (more or less).  Is this correct? */
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sem_t* ret;
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_SEM_FNS) {
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< sem_open(\"%s\",%ld,%lx,%lu) ",
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      name,oflag,mode,value);
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_WWWW(ret, fn, name,oflag,mode,value);
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret != SEM_FAILED && (oflag & O_CREAT)) {
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST,
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   sem_t*, ret, unsigned long, value);
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret == SEM_FAILED) {
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "sem_open", errno );
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_SEM_FNS) {
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " sem_open -> %p >>\n", ret);
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// glibc:  sem_close
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// darwin: sem_close
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPTH_FUNC(int, sem_close, sem_t* sem)
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int    ret;
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_SEM_FNS) {
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< sem_close(%p) ", sem);
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, sem_t*, sem);
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, sem);
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret != 0) {
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_PthAPIerror( "sem_close", errno );
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_SEM_FNS) {
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " close -> %d >>\n", ret);
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Qt 4 threading functions (w/ GNU name mangling)          ---*/
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Handled:
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QMutex::lock()
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QMutex::unlock()
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QMutex::tryLock()
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QMutex::tryLock(int)
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QMutex::QMutex(QMutex::RecursionMode)  _ZN6QMutexC1ENS_13RecursionModeE
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QMutex::QMutex(QMutex::RecursionMode)  _ZN6QMutexC2ENS_13RecursionModeE
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QMutex::~QMutex()                      _ZN6QMutexD1Ev
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QMutex::~QMutex()                      _ZN6QMutexD2Ev
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Unhandled:
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QReadWriteLock::lockForRead()
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QReadWriteLock::lockForWrite()
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QReadWriteLock::unlock()
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QReadWriteLock::tryLockForRead(int)
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QReadWriteLock::tryLockForRead()
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QReadWriteLock::tryLockForWrite(int)
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QReadWriteLock::tryLockForWrite()
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QWaitCondition::wait(QMutex*, unsigned long)
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QWaitCondition::wakeAll()
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QWaitCondition::wakeOne()
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      QSemaphore::*
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* More comments, 19 Nov 08, based on assessment of qt-4.5.0TP1,
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   at least on Unix:
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   It's apparently only necessary to intercept QMutex, since that is
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   not implemented using pthread_mutex_t; instead Qt4 has its own
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   implementation based on atomics (to check the non-contended case)
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and pthread_cond_wait (to wait in the contended case).
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   QReadWriteLock is built on top of QMutex, counters, and a wait
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   queue.  So we don't need to handle it specially once QMutex
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   handling is correct -- presumably the dependencies through QMutex
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   are sufficient to avoid any false race reports.  On the other hand,
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it is an open question whether too many dependencies are observed
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   -- in which case we may miss races (false negatives).  I suspect
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   this is likely to be the case, unfortunately.
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   QWaitCondition is built on pthread_cond_t, pthread_mutex_t, QMutex
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and QReadWriteLock.  Same compositional-correctness justificiation
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and limitations as fro QReadWriteLock.
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ditto QSemaphore (from cursory examination).
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Does it matter that only QMutex is handled directly?  Open
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   question.  From testing with drd/tests/qt4_* and with KDE4 apps, it
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   appears that no false errors are reported; however it is not clear
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if this is causing false negatives.
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Another problem with Qt4 is thread exiting.  Threads are created
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   with pthread_create (fine); but they detach and simply exit when
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   done.  There is no use of pthread_join, and the provided
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wait-for-a-thread-to-exit mechanism (QThread::wait, I believe)
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   relies on a system of mutexes and flags.  I suspect this also
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   causes too many dependencies to appear.  Consequently H sometimes
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fails to detect races at exit in some very short-lived racy
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   programs, because it appears that a thread can exit _and_ have an
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   observed dependency edge back to the main thread (presumably)
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   before the main thread reaps the child (that is, calls
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   QThread::wait).
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This theory is supported by the observation that if all threads are
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   made to wait at a pthread_barrier_t immediately before they exit,
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   then H's detection of races in such programs becomes reliable;
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   without the barrier, it is varies from run to run, depending
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (according to investigation) on whether aforementioned
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   exit-before-reaping behaviour happens or not.
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Finally, why is it necessary to intercept the QMutex constructors
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and destructors?  The constructors are intercepted only as a matter
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of convenience, so H can print accurate "first observed at"
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clauses.  However, it is actually necessary to intercept the
2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   destructors (as it is with pthread_mutex_destroy) in order that
2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   locks get removed from LAOG when they are destroyed.
2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// soname is libQtCore.so.4 ; match against libQtCore.so*
2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define QT4_FUNC(ret_ty, f, args...) \
2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ret_ty I_WRAP_SONAME_FNNAME_ZU(libQtCoreZdsoZa,f)(args); \
2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ret_ty I_WRAP_SONAME_FNNAME_ZU(libQtCoreZdsoZa,f)(args)
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::lock()
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4_FUNC(void, _ZN6QMutex4lockEv, void* self)
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_QT4_FNS) {
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< QMutex::lock %p", self); fflush(stderr);
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                void*,self, long,0/*!isTryLock*/);
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_v_W(fn, self);
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               void*, self);
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_QT4_FNS) {
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: Q::lock done >>\n");
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::unlock()
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4_FUNC(void, _ZN6QMutex6unlockEv, void* self)
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_QT4_FNS) {
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< QMutex::unlock %p", self); fflush(stderr);
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               void*, self);
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_v_W(fn, self);
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST,
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               void*, self);
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_QT4_FNS) {
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " Q::unlock done >>\n");
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// bool QMutex::tryLock()
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// using 'long' to mimic C++ 'bool'
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4_FUNC(long, _ZN6QMutex7tryLockEv, void* self)
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   long   ret;
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_QT4_FNS) {
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< QMutex::tryLock %p", self); fflush(stderr);
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                void*,self, long,1/*isTryLock*/);
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, self);
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // assumes that only the low 8 bits of the 'bool' are significant
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret & 0xFF) {
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  void*, self);
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_QT4_FNS) {
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: Q::tryLock -> %lu >>\n", ret);
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// bool QMutex::tryLock(int)
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// using 'long' to mimic C++ 'bool'
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4_FUNC(long, _ZN6QMutex7tryLockEi, void* self, long arg2)
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   long   ret;
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_QT4_FNS) {
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, "<< QMutex::tryLock(int) %p %d", self, (int)arg2);
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fflush(stderr);
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                void*,self, long,1/*isTryLock*/);
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_WW(ret, fn, self,arg2);
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // assumes that only the low 8 bits of the 'bool' are significant
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ret & 0xFF) {
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  void*, self);
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TRACE_QT4_FNS) {
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, " :: Q::tryLock(int) -> %lu >>\n", ret);
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// It's not really very clear what the args are here.  But from
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// a bit of dataflow analysis of the generated machine code of
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// the original function, it appears this takes two args, and
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// returns nothing.  Nevertheless preserve return value just in
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// case.  A bit of debug printing indicates that the first arg
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// is that of the mutex and the second is either zero or one,
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// probably being the recursion mode, therefore.
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::QMutex(QMutex::RecursionMode)  ("C1ENS" variant)
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4_FUNC(void*, _ZN6QMutexC1ENS_13RecursionModeE,
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         void* mutex,
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         long  recmode)
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   long   ret;
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_WW(ret, fn, mutex, recmode);
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //   fprintf(stderr, "QMutex constructor 1: %p <- %p %p\n", ret, arg1, arg2);
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST,
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                void*,mutex, long,1/*mbRec*/);
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (void*)ret;
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::~QMutex()  ("D1Ev" variant)
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4_FUNC(void*, _ZN6QMutexD1Ev, void* mutex)
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   OrigFn fn;
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   long   ret;
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VALGRIND_GET_ORIG_FN(fn);
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE,
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               void*,mutex);
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CALL_FN_W_W(ret, fn, mutex);
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (void*)ret;
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::QMutex(QMutex::RecursionMode)  ("C2ENS" variant)
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4_FUNC(void*, _ZN6QMutexC2ENS_13RecursionModeE,
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         void* mutex,
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         long  recmode)
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assert(0);
2189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*NOTREACHED*/
2190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Android's gcc behaves like it doesn't know that assert(0)
2191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      never returns.  Hence: */
2192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return NULL;
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//-----------------------------------------------------------
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QMutex::~QMutex()  ("D2Ev" variant)
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownQT4_FUNC(void*, _ZN6QMutexD2Ev, void* mutex)
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assert(0);
2201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Android's gcc behaves like it doesn't know that assert(0)
2202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      never returns.  Hence: */
2203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return NULL;
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// QReadWriteLock is not intercepted directly.  See comments
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// above.
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//// QReadWriteLock::lockForRead()
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//// _ZN14QReadWriteLock11lockForReadEv == QReadWriteLock::lockForRead()
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//QT4_FUNC(void, ZuZZN14QReadWriteLock11lockForReadEv,
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//               // _ZN14QReadWriteLock11lockForReadEv
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//               void* self)
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//{
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   OrigFn fn;
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   VALGRIND_GET_ORIG_FN(fn);
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   if (TRACE_QT4_FNS) {
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      fprintf(stderr, "<< QReadWriteLock::lockForRead %p", self);
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      fflush(stderr);
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   }
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                 void*,self,
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                 long,0/*!isW*/, long,0/*!isTryLock*/);
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   CALL_FN_v_W(fn, self);
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                void*,self, long,0/*!isW*/);
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   if (TRACE_QT4_FNS) {
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      fprintf(stderr, " :: Q::lockForRead :: done >>\n");
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   }
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//}
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//// QReadWriteLock::lockForWrite()
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//// _ZN14QReadWriteLock12lockForWriteEv == QReadWriteLock::lockForWrite()
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//QT4_FUNC(void, ZuZZN14QReadWriteLock12lockForWriteEv,
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//               // _ZN14QReadWriteLock12lockForWriteEv
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//               void* self)
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//{
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   OrigFn fn;
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   VALGRIND_GET_ORIG_FN(fn);
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   if (TRACE_QT4_FNS) {
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      fprintf(stderr, "<< QReadWriteLock::lockForWrite %p", self);
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      fflush(stderr);
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   }
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                 void*,self,
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                 long,1/*isW*/, long,0/*!isTryLock*/);
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   CALL_FN_v_W(fn, self);
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                void*,self, long,1/*isW*/);
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   if (TRACE_QT4_FNS) {
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      fprintf(stderr, " :: Q::lockForWrite :: done >>\n");
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   }
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//}
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//// QReadWriteLock::unlock()
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//// _ZN14QReadWriteLock6unlockEv == QReadWriteLock::unlock()
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//QT4_FUNC(void, ZuZZN14QReadWriteLock6unlockEv,
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//               // _ZN14QReadWriteLock6unlockEv
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//               void* self)
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//{
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   OrigFn fn;
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   VALGRIND_GET_ORIG_FN(fn);
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   if (TRACE_QT4_FNS) {
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      fprintf(stderr, "<< QReadWriteLock::unlock %p", self);
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      fflush(stderr);
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   }
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE,
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//               void*,self);
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   CALL_FN_v_W(fn, self);
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST,
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//               void*,self);
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   if (TRACE_QT4_FNS) {
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      fprintf(stderr, " :: Q::unlock :: done >>\n");
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   }
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//}
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Replacements for basic string functions, that don't      ---*/
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- overrun the input arrays.                                ---*/
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------------------*/
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Copied verbatim from memcheck/mc_replace_strmem.c.  When copying
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   new functions, please keep them in the same order as they appear in
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mc_replace_strmem.c. */
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRCHR(soname, fnname) \
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar  ch = (UChar)((UInt)c); \
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* p  = (UChar*)s; \
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (True) { \
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (*p == ch) return p; \
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (*p == 0) return NULL; \
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         p++; \
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Apparently index() is the same thing as strchr()
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
2316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LIBC_SONAME,          strchr)
2317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LIBC_SONAME,          index)
2318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LD_LINUX_SO_2,        strchr)
2319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LD_LINUX_SO_2,        index)
2320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
2321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
2322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
2323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LIBC_SONAME,          strchr)
2324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCHR(VG_Z_LIBC_SONAME,          index)
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Note that this replacement often doesn't get used because gcc inlines
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// calls to strlen() with its own built-in version.  This can be very
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// confusing if you aren't expecting it.  Other small functions in this file
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// may also be inline by gcc.
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRLEN(soname, fnname) \
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SizeT i = 0; \
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (str[i] != 0) i++; \
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return i; \
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
2342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLEN(VG_Z_LIBC_SONAME,          strlen)
2343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLEN(VG_Z_LD_LINUX_SO_2,        strlen)
2344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
2345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
2346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRLEN(VG_Z_LIBC_SONAME,          strlen)
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRCPY(soname, fnname) \
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      const Char* dst_orig = dst; \
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (*src) *dst++ = *src++; \
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *dst = 0; \
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return (char*)dst_orig; \
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux)
2363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCPY(VG_Z_LIBC_SONAME, strcpy)
2364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
2365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCPY(VG_Z_LIBC_SONAME, strcpy)
2366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define STRCMP(soname, fnname) \
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ( const char* s1, const char* s2 ); \
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ( const char* s1, const char* s2 ) \
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register unsigned char c1; \
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register unsigned char c2; \
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      while (True) { \
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         c1 = *(unsigned char *)s1; \
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         c2 = *(unsigned char *)s2; \
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (c1 != c2) break; \
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (c1 == 0) break; \
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         s1++; s2++; \
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((unsigned char)c1 < (unsigned char)c2) return -1; \
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((unsigned char)c1 > (unsigned char)c2) return 1; \
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return 0; \
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
2390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCMP(VG_Z_LIBC_SONAME,          strcmp)
2391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
2392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCMP(VG_Z_LD64_SO_1,            strcmp)
2393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
2394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov STRCMP(VG_Z_LIBC_SONAME,          strcmp)
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MEMCPY(soname, fnname) \
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ( void *dst, const void *src, SizeT len ); \
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ( void *dst, const void *src, SizeT len ) \
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   { \
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register char *d; \
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      register char *s; \
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (len == 0) \
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return dst; \
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      \
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( dst > src ) { \
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = (char *)dst + len - 1; \
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         s = (char *)src + len - 1; \
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while ( len >= 4 ) { \
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *d-- = *s--; \
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *d-- = *s--; \
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *d-- = *s--; \
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *d-- = *s--; \
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len -= 4; \
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } \
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while ( len-- ) { \
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *d-- = *s--; \
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } \
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else if ( dst < src ) { \
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = (char *)dst; \
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         s = (char *)src; \
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while ( len >= 4 ) { \
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *d++ = *s++; \
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *d++ = *s++; \
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *d++ = *s++; \
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *d++ = *s++; \
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            len -= 4; \
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } \
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         while ( len-- ) { \
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            *d++ = *s++; \
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } \
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } \
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return dst; \
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_linux)
2441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LIBC_SONAME,    memcpy)
2442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LD_SO_1,        memcpy) /* ld.so.1 */
2443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LD64_SO_1,      memcpy) /* ld64.so.1 */
2444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* icc9 blats these around all over the place.  Not only in the main
2445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    executable but various .so's.  They are highly tuned and read
2446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    memory beyond the source boundary (although work correctly and
2447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    never go across page boundaries), so give errors when run
2448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    natively, at least for misaligned source arg.  Just intercepting
2449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    in the exe only until we understand more about the problem.  See
2450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    http://bugs.kde.org/show_bug.cgi?id=139776
24519bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root */
2452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(NONE, _intel_fast_memcpy)
2453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#elif defined(VGO_darwin)
2454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MEMCPY(VG_Z_LIBC_SONAME,    memcpy)
2455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
2459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*--- end                                          hg_intercepts.c ---*/
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
2461