| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1 |  | 
 | 2 | /*--------------------------------------------------------------------*/ | 
 | 3 | /*--- pthread intercepts for thread checking.                      ---*/ | 
| sewardj | 3c94445 | 2011-09-05 20:39:57 +0000 | [diff] [blame] | 4 | /*---                                              hg_intercepts.c ---*/ | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 5 | /*--------------------------------------------------------------------*/ | 
 | 6 |  | 
 | 7 | /* | 
 | 8 |    This file is part of Helgrind, a Valgrind tool for detecting errors | 
 | 9 |    in threaded programs. | 
 | 10 |  | 
| sewardj | b3a1e4b | 2015-08-21 11:32:26 +0000 | [diff] [blame] | 11 |    Copyright (C) 2007-2015 OpenWorks LLP | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 12 |       info@open-works.co.uk | 
 | 13 |  | 
 | 14 |    This program is free software; you can redistribute it and/or | 
 | 15 |    modify it under the terms of the GNU General Public License as | 
 | 16 |    published by the Free Software Foundation; either version 2 of the | 
 | 17 |    License, or (at your option) any later version. | 
 | 18 |  | 
 | 19 |    This program is distributed in the hope that it will be useful, but | 
 | 20 |    WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 21 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 | 22 |    General Public License for more details. | 
 | 23 |  | 
 | 24 |    You should have received a copy of the GNU General Public License | 
 | 25 |    along with this program; if not, write to the Free Software | 
 | 26 |    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | 
 | 27 |    02111-1307, USA. | 
 | 28 |  | 
 | 29 |    The GNU General Public License is contained in the file COPYING. | 
 | 30 |  | 
 | 31 |    Neither the names of the U.S. Department of Energy nor the | 
 | 32 |    University of California nor the names of its contributors may be | 
 | 33 |    used to endorse or promote products derived from this software | 
 | 34 |    without prior written permission. | 
 | 35 | */ | 
 | 36 |  | 
 | 37 | /* RUNS ON SIMULATED CPU | 
 | 38 |    Interceptors for pthread_* functions, so that tc_main can see | 
 | 39 |    significant thread events.  | 
 | 40 |  | 
 | 41 |    Important: when adding a function wrapper to this file, remember to | 
 | 42 |    add a test case to tc20_verifywrap.c.  A common cause of failure is | 
 | 43 |    for wrappers to not engage on different distros, and | 
 | 44 |    tc20_verifywrap essentially checks that each wrapper is really | 
 | 45 |    doing something. | 
 | 46 | */ | 
 | 47 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 48 | // DDD: for Darwin, need to have non-"@*"-suffixed versions for all pthread | 
 | 49 | // functions that currently have them. | 
 | 50 | // Note also, in the comments and code below, all Darwin symbols start | 
 | 51 | // with a leading underscore, which is not shown either in the comments | 
 | 52 | // nor in the redirect specs. | 
 | 53 |  | 
 | 54 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 55 | #include "pub_tool_basics.h" | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 56 | #include "pub_tool_redir.h" | 
| florian | 1a046d5 | 2013-09-16 20:56:35 +0000 | [diff] [blame] | 57 | #include "pub_tool_clreq.h" | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 58 | #include "helgrind.h" | 
| bart | 870f745 | 2009-12-29 16:56:18 +0000 | [diff] [blame] | 59 | #include "config.h" | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 60 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 61 |  | 
 | 62 | #if defined(VGO_solaris) | 
 | 63 | /* See porting comments in drd/drd_pthread_intercepts.c | 
 | 64 |    However when a POSIX threads API function (for example pthread_cond_init) | 
 | 65 |    is built upon the Solaris one (cond_init), intercept only the bottom one. | 
 | 66 |    Helgrind does not contain generic synchronization nesting like DRD | 
 | 67 |    and double intercept confuses it. */ | 
 | 68 | #include <synch.h> | 
 | 69 | #include <thread.h> | 
 | 70 | #endif /* VGO_solaris */ | 
 | 71 |  | 
 | 72 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 73 | #define TRACE_PTH_FNS 0 | 
 | 74 | #define TRACE_QT4_FNS 0 | 
| philippe | d40aff5 | 2014-06-16 20:00:14 +0000 | [diff] [blame] | 75 | #define TRACE_GNAT_FNS 0 | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 76 |  | 
 | 77 |  | 
 | 78 | /*----------------------------------------------------------------*/ | 
 | 79 | /*---                                                          ---*/ | 
 | 80 | /*----------------------------------------------------------------*/ | 
 | 81 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 82 | #if defined(VGO_solaris) | 
 | 83 | /* On Solaris, libpthread is just a filter library on top of libc. | 
 | 84 |  * Threading and synchronization functions in runtime linker are not | 
 | 85 |  * intercepted. | 
 | 86 |  */ | 
 | 87 | #define PTH_FUNC(ret_ty, f, args...) \ | 
 | 88 |    ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBC_SONAME,f)(args); \ | 
 | 89 |    ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBC_SONAME,f)(args) | 
 | 90 |  | 
 | 91 | /* pthread_t is typedef'd to 'unsigned int' but in DO_CREQ_* macros | 
 | 92 |    sizeof(Word) is expected. */ | 
 | 93 | #define CREQ_PTHREAD_T Word | 
 | 94 | #define SEM_ERROR ret | 
 | 95 | #else | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 96 | #define PTH_FUNC(ret_ty, f, args...) \ | 
| njn | 5f5ef2a | 2009-05-11 08:01:09 +0000 | [diff] [blame] | 97 |    ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args); \ | 
 | 98 |    ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args) | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 99 | #define CREQ_PTHREAD_T pthread_t | 
 | 100 | #define SEM_ERROR errno | 
 | 101 | #endif /* VGO_solaris */ | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 102 |  | 
| sewardj | 406bac8 | 2010-03-03 23:03:40 +0000 | [diff] [blame] | 103 | // Do a client request.  These are macros rather than a functions so | 
 | 104 | // as to avoid having an extra frame in stack traces. | 
 | 105 |  | 
 | 106 | // NB: these duplicate definitions in helgrind.h.  But here, we | 
 | 107 | // can have better typing (Word etc) and assertions, whereas | 
 | 108 | // in helgrind.h we can't.  Obviously it's important the two | 
 | 109 | // sets of definitions are kept in sync. | 
 | 110 |  | 
 | 111 | // nuke the previous definitions | 
 | 112 | #undef DO_CREQ_v_W | 
 | 113 | #undef DO_CREQ_v_WW | 
 | 114 | #undef DO_CREQ_W_WW | 
 | 115 | #undef DO_CREQ_v_WWW | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 116 |  | 
 | 117 | #define DO_CREQ_v_W(_creqF, _ty1F,_arg1F)                \ | 
 | 118 |    do {                                                  \ | 
| sewardj | c7ffc94 | 2011-03-28 16:26:42 +0000 | [diff] [blame] | 119 |       Word _arg1;                                        \ | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 120 |       assert(sizeof(_ty1F) == sizeof(Word));             \ | 
 | 121 |       _arg1 = (Word)(_arg1F);                            \ | 
| sewardj | 4b3a742 | 2011-10-24 13:21:57 +0000 | [diff] [blame] | 122 |       VALGRIND_DO_CLIENT_REQUEST_STMT((_creqF),          \ | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 123 |                                  _arg1, 0,0,0,0);        \ | 
 | 124 |    } while (0) | 
 | 125 |  | 
 | 126 | #define DO_CREQ_v_WW(_creqF, _ty1F,_arg1F, _ty2F,_arg2F) \ | 
 | 127 |    do {                                                  \ | 
| sewardj | c7ffc94 | 2011-03-28 16:26:42 +0000 | [diff] [blame] | 128 |       Word _arg1, _arg2;                                 \ | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 129 |       assert(sizeof(_ty1F) == sizeof(Word));             \ | 
 | 130 |       assert(sizeof(_ty2F) == sizeof(Word));             \ | 
 | 131 |       _arg1 = (Word)(_arg1F);                            \ | 
 | 132 |       _arg2 = (Word)(_arg2F);                            \ | 
| sewardj | 4b3a742 | 2011-10-24 13:21:57 +0000 | [diff] [blame] | 133 |       VALGRIND_DO_CLIENT_REQUEST_STMT((_creqF),          \ | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 134 |                                  _arg1,_arg2,0,0,0);     \ | 
 | 135 |    } while (0) | 
 | 136 |  | 
| sewardj | c7ffc94 | 2011-03-28 16:26:42 +0000 | [diff] [blame] | 137 | #define DO_CREQ_W_WW(_resF, _creqF, _ty1F,_arg1F,        \ | 
 | 138 |                      _ty2F,_arg2F)                       \ | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 139 |    do {                                                  \ | 
 | 140 |       Word _res, _arg1, _arg2;                           \ | 
 | 141 |       assert(sizeof(_ty1F) == sizeof(Word));             \ | 
 | 142 |       assert(sizeof(_ty2F) == sizeof(Word));             \ | 
 | 143 |       _arg1 = (Word)(_arg1F);                            \ | 
 | 144 |       _arg2 = (Word)(_arg2F);                            \ | 
| bart | 575ce8e | 2011-05-15 07:04:03 +0000 | [diff] [blame] | 145 |       _res = VALGRIND_DO_CLIENT_REQUEST_EXPR(2,          \ | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 146 |                                  (_creqF),               \ | 
 | 147 |                                  _arg1,_arg2,0,0,0);     \ | 
 | 148 |       _resF = _res;                                      \ | 
 | 149 |    } while (0) | 
 | 150 |  | 
 | 151 | #define DO_CREQ_v_WWW(_creqF, _ty1F,_arg1F,              \ | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 152 |                       _ty2F,_arg2F, _ty3F, _arg3F)       \ | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 153 |    do {                                                  \ | 
| sewardj | c7ffc94 | 2011-03-28 16:26:42 +0000 | [diff] [blame] | 154 |       Word _arg1, _arg2, _arg3;                          \ | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 155 |       assert(sizeof(_ty1F) == sizeof(Word));             \ | 
 | 156 |       assert(sizeof(_ty2F) == sizeof(Word));             \ | 
 | 157 |       assert(sizeof(_ty3F) == sizeof(Word));             \ | 
 | 158 |       _arg1 = (Word)(_arg1F);                            \ | 
 | 159 |       _arg2 = (Word)(_arg2F);                            \ | 
 | 160 |       _arg3 = (Word)(_arg3F);                            \ | 
| sewardj | 4b3a742 | 2011-10-24 13:21:57 +0000 | [diff] [blame] | 161 |       VALGRIND_DO_CLIENT_REQUEST_STMT((_creqF),          \ | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 162 |                                  _arg1,_arg2,_arg3,0,0); \ | 
 | 163 |    } while (0) | 
 | 164 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 165 | #define DO_CREQ_v_WWWW(_creqF, _ty1F,_arg1F,             \ | 
 | 166 |                        _ty2F, _arg2F, _ty3F, _arg3F,     \ | 
 | 167 |                        _ty4F, _arg4F)                    \ | 
 | 168 |    do {                                                  \ | 
 | 169 |       Word _arg1, _arg2, _arg3, _arg4;                   \ | 
 | 170 |       assert(sizeof(_ty1F) == sizeof(Word));             \ | 
 | 171 |       assert(sizeof(_ty2F) == sizeof(Word));             \ | 
 | 172 |       assert(sizeof(_ty3F) == sizeof(Word));             \ | 
 | 173 |       assert(sizeof(_ty4F) == sizeof(Word));             \ | 
 | 174 |       _arg1 = (Word)(_arg1F);                            \ | 
 | 175 |       _arg2 = (Word)(_arg2F);                            \ | 
 | 176 |       _arg3 = (Word)(_arg3F);                            \ | 
 | 177 |       _arg4 = (Word)(_arg4F);                            \ | 
 | 178 |       VALGRIND_DO_CLIENT_REQUEST_STMT((_creqF),          \ | 
 | 179 |                              _arg1,_arg2,_arg3,_arg4,0); \ | 
 | 180 |    } while (0) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 181 |  | 
 | 182 | #define DO_PthAPIerror(_fnnameF, _errF)                  \ | 
 | 183 |    do {                                                  \ | 
| florian | 09041e4 | 2014-10-21 17:15:14 +0000 | [diff] [blame] | 184 |       const char* _fnname = (_fnnameF);                  \ | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 185 |       long  _err    = (long)(int)(_errF);                \ | 
| florian | 654b542 | 2012-11-18 00:36:15 +0000 | [diff] [blame] | 186 |       const char* _errstr = lame_strerror(_err);         \ | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 187 |       DO_CREQ_v_WWW(_VG_USERREQ__HG_PTH_API_ERROR,       \ | 
 | 188 |                     char*,_fnname,                       \ | 
 | 189 |                     long,_err, char*,_errstr);           \ | 
 | 190 |    } while (0) | 
 | 191 |  | 
 | 192 |  | 
 | 193 | /* Needed for older glibcs (2.3 and older, at least) who don't | 
 | 194 |    otherwise "know" about pthread_rwlock_anything or about | 
 | 195 |    PTHREAD_MUTEX_RECURSIVE (amongst things). */ | 
 | 196 | #define _GNU_SOURCE 1 | 
 | 197 |  | 
 | 198 | #include <stdio.h> | 
 | 199 | #include <assert.h> | 
 | 200 | #include <errno.h> | 
 | 201 | #include <pthread.h> | 
 | 202 |  | 
| sewardj | c02f6c4 | 2013-10-14 13:51:25 +0000 | [diff] [blame] | 203 | /* A standalone memcmp. */ | 
 | 204 | __attribute__((noinline)) | 
 | 205 | static int my_memcmp ( const void* ptr1, const void* ptr2, size_t size) | 
 | 206 | { | 
| florian | 8eebf23 | 2014-09-18 18:35:47 +0000 | [diff] [blame] | 207 |    const unsigned char* uchar_ptr1 = (const unsigned char*) ptr1; | 
 | 208 |    const unsigned char* uchar_ptr2 = (const unsigned char*) ptr2; | 
| sewardj | c02f6c4 | 2013-10-14 13:51:25 +0000 | [diff] [blame] | 209 |    size_t i; | 
 | 210 |    for (i = 0; i < size; ++i) { | 
 | 211 |       if (uchar_ptr1[i] != uchar_ptr2[i]) | 
 | 212 |          return (uchar_ptr1[i] < uchar_ptr2[i]) ? -1 : 1; | 
 | 213 |    } | 
 | 214 |    return 0; | 
 | 215 | } | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 216 |  | 
 | 217 | /* A lame version of strerror which doesn't use the real libc | 
 | 218 |    strerror_r, since using the latter just generates endless more | 
 | 219 |    threading errors (glibc goes off and does tons of crap w.r.t. | 
 | 220 |    locales etc) */ | 
| florian | 654b542 | 2012-11-18 00:36:15 +0000 | [diff] [blame] | 221 | static const HChar* lame_strerror ( long err ) | 
| sewardj | c02f6c4 | 2013-10-14 13:51:25 +0000 | [diff] [blame] | 222 | { | 
 | 223 |    switch (err) { | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 224 |       case EPERM:       return "EPERM: Operation not permitted"; | 
 | 225 |       case ENOENT:      return "ENOENT: No such file or directory"; | 
 | 226 |       case ESRCH:       return "ESRCH: No such process"; | 
 | 227 |       case EINTR:       return "EINTR: Interrupted system call"; | 
 | 228 |       case EBADF:       return "EBADF: Bad file number"; | 
 | 229 |       case EAGAIN:      return "EAGAIN: Try again"; | 
 | 230 |       case ENOMEM:      return "ENOMEM: Out of memory"; | 
 | 231 |       case EACCES:      return "EACCES: Permission denied"; | 
 | 232 |       case EFAULT:      return "EFAULT: Bad address"; | 
 | 233 |       case EEXIST:      return "EEXIST: File exists"; | 
 | 234 |       case EINVAL:      return "EINVAL: Invalid argument"; | 
 | 235 |       case EMFILE:      return "EMFILE: Too many open files"; | 
 | 236 |       case ENOSYS:      return "ENOSYS: Function not implemented"; | 
 | 237 |       case EOVERFLOW:   return "EOVERFLOW: Value too large " | 
 | 238 |                                "for defined data type"; | 
 | 239 |       case EBUSY:       return "EBUSY: Device or resource busy"; | 
 | 240 |       case ETIMEDOUT:   return "ETIMEDOUT: Connection timed out"; | 
 | 241 |       case EDEADLK:     return "EDEADLK: Resource deadlock would occur"; | 
 | 242 |       case EOPNOTSUPP:  return "EOPNOTSUPP: Operation not supported on " | 
 | 243 |                                "transport endpoint"; /* honest, guv */ | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 244 |       case ETIME:       return "ETIME: Timer expired"; | 
 | 245 |       default:          return "hg_intercepts.c: lame_strerror(): " | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 246 |                                "unhandled case -- please fix me!"; | 
 | 247 |    } | 
 | 248 | } | 
 | 249 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 250 | #if defined(VGO_solaris) | 
 | 251 | /* | 
 | 252 |  * Solaris provides higher throughput, parallelism and scalability than other | 
 | 253 |  * operating systems, at the cost of more fine-grained locking activity. | 
 | 254 |  * This means for example that when a thread is created under Linux, just one | 
 | 255 |  * big lock in glibc is used for all thread setup. Solaris libc uses several | 
 | 256 |  * fine-grained locks and the creator thread resumes its activities as soon | 
 | 257 |  * as possible, leaving for example stack and TLS setup activities to the | 
 | 258 |  * created thread. | 
 | 259 |  * | 
 | 260 |  * This situation confuses Helgrind as it assumes there is some false ordering | 
 | 261 |  * in place between creator and created thread; and therefore many types of | 
 | 262 |  * race conditions in the application would not be reported. To prevent such | 
 | 263 |  * false ordering, command line option --ignore-thread-creation is set to | 
 | 264 |  * 'yes' by default on Solaris. All activity (loads, stores, client requests) | 
 | 265 |  * is therefore ignored during: | 
 | 266 |  * - pthread_create() call in the creator thread [libc.so] | 
 | 267 |  * - thread creation phase (stack and TLS setup) in the created thread [libc.so] | 
 | 268 |  * | 
 | 269 |  * As explained in the comments for _ti_bind_guard(), whenever the runtime | 
 | 270 |  * linker has to perform any activity (such as resolving a symbol), it protects | 
 | 271 |  * its data structures by calling into rt_bind_guard() which in turn invokes | 
 | 272 |  * _ti_bind_guard() in libc. Pointers to _ti_bind_guard() and _ti_bind_clear() | 
 | 273 |  * are passed from libc to runtime linker in _ld_libc() call during libc_init(). | 
 | 274 |  * All activity is also ignored during: | 
 | 275 |  * - runtime dynamic linker work between rt_bind_guard() and rt_bind_clear() | 
 | 276 |  *   calls [ld.so] | 
 | 277 |  * | 
 | 278 |  * This also means that Helgrind does not report race conditions in libc (when | 
 | 279 |  * --ignore-thread-creation=yes) and runtime linker itself (unconditionally) | 
 | 280 |  * during these ignored sequences. | 
 | 281 |  */ | 
 | 282 |  | 
 | 283 | #include "pub_tool_libcassert.h" | 
 | 284 | #include "pub_tool_vki.h" | 
 | 285 |  | 
 | 286 | /* | 
 | 287 |  * Original function pointers for _ti_bind_guard() and _ti_bind_clear() | 
 | 288 |  * from libc. They are intercepted in function wrapper of _ld_libc(). | 
 | 289 |  */ | 
 | 290 | typedef int (*hg_rtld_guard_fn)(int flags); | 
 | 291 | static hg_rtld_guard_fn hg_rtld_bind_guard = NULL; | 
 | 292 | static hg_rtld_guard_fn hg_rtld_bind_clear = NULL; | 
 | 293 |  | 
 | 294 | static void hg_init(void) __attribute__((constructor)); | 
 | 295 | static void hg_init(void) | 
 | 296 | { | 
 | 297 |    if ((hg_rtld_bind_guard == NULL) || (hg_rtld_bind_clear == NULL)) { | 
 | 298 |       fprintf(stderr, | 
 | 299 | "Bind guard functions for the runtime linker (ld.so.1) were not intercepted.\n" | 
 | 300 | "This means the interface between libc and runtime linker changed\n" | 
 | 301 | "and Helgrind needs to be ported properly. Giving up.\n"); | 
 | 302 |       tl_assert(0); | 
 | 303 |    } | 
 | 304 | } | 
 | 305 |  | 
 | 306 | /* | 
 | 307 |  * Intercepts for _ti_bind_guard() and _ti_bind_clear() functions from libc. | 
 | 308 |  * These are intercepted during _ld_libc() call by identifying CI_BIND_GUARD | 
 | 309 |  * and CI_BIND_CLEAR, to provide resilience against function renaming. | 
 | 310 |  */ | 
 | 311 | static int _ti_bind_guard_intercept_WRK(int flags) | 
 | 312 | { | 
 | 313 |    VALGRIND_DO_CLIENT_REQUEST_STMT(_VG_USERREQ__HG_RTLD_BIND_GUARD, | 
 | 314 |                                    flags, 0, 0, 0, 0); | 
 | 315 |    return hg_rtld_bind_guard(flags); | 
 | 316 | } | 
 | 317 |  | 
 | 318 | static int _ti_bind_clear_intercept_WRK(int flags) | 
 | 319 | { | 
 | 320 |    int ret = hg_rtld_bind_clear(flags); | 
 | 321 |    VALGRIND_DO_CLIENT_REQUEST_STMT(_VG_USERREQ__HG_RTLD_BIND_CLEAR, | 
 | 322 |                                    flags, 0, 0, 0, 0); | 
 | 323 |    return ret; | 
 | 324 | } | 
 | 325 |  | 
 | 326 | /* | 
 | 327 |  * Wrapped _ld_libc() from the runtime linker ld.so.1. | 
 | 328 |  */ | 
 | 329 | void I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LD_SO_1, ZuldZulibc)(vki_Lc_interface *ptr); | 
 | 330 | void I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LD_SO_1, ZuldZulibc)(vki_Lc_interface *ptr) | 
 | 331 | { | 
 | 332 |    OrigFn fn; | 
 | 333 |    int    tag; | 
 | 334 |  | 
 | 335 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 336 |  | 
 | 337 |    vki_Lc_interface *funcs = ptr; | 
 | 338 |    for (tag = funcs->ci_tag; tag != 0; tag = (++funcs)->ci_tag) { | 
 | 339 |       switch (tag) { | 
 | 340 |       case VKI_CI_BIND_GUARD: | 
 | 341 |          if (funcs->vki_ci_un.ci_func != _ti_bind_guard_intercept_WRK) { | 
 | 342 |             hg_rtld_bind_guard = funcs->vki_ci_un.ci_func; | 
 | 343 |             funcs->vki_ci_un.ci_func = _ti_bind_guard_intercept_WRK; | 
 | 344 |          } | 
 | 345 |          break; | 
 | 346 |       case VKI_CI_BIND_CLEAR: | 
 | 347 |          if (funcs->vki_ci_un.ci_func != _ti_bind_clear_intercept_WRK) { | 
 | 348 |             hg_rtld_bind_clear = funcs->vki_ci_un.ci_func; | 
 | 349 |             funcs->vki_ci_un.ci_func = _ti_bind_clear_intercept_WRK; | 
 | 350 |          } | 
 | 351 |          break; | 
 | 352 |       } | 
 | 353 |    } | 
 | 354 |  | 
 | 355 |    CALL_FN_v_W(fn, ptr); | 
 | 356 | } | 
 | 357 | #endif /* VGO_solaris */ | 
 | 358 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 359 |  | 
 | 360 | /*----------------------------------------------------------------*/ | 
 | 361 | /*--- pthread_create, pthread_join, pthread_exit               ---*/ | 
 | 362 | /*----------------------------------------------------------------*/ | 
 | 363 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 364 | static void* mythread_wrapper ( void* xargsV ) | 
 | 365 | { | 
| bart | 31277bf | 2008-07-29 17:04:31 +0000 | [diff] [blame] | 366 |    volatile Word* xargs = (volatile Word*) xargsV; | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 367 |    void*(*fn)(void*) = (void*(*)(void*))xargs[0]; | 
 | 368 |    void* arg         = (void*)xargs[1]; | 
 | 369 |    pthread_t me = pthread_self(); | 
 | 370 |    /* Tell the tool what my pthread_t is. */ | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 371 |    DO_CREQ_v_W(_VG_USERREQ__HG_SET_MY_PTHREAD_T, CREQ_PTHREAD_T, me); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 372 |    /* allow the parent to proceed.  We can't let it proceed until | 
 | 373 |       we're ready because (1) we need to make sure it doesn't exit and | 
 | 374 |       hence deallocate xargs[] while we still need it, and (2) we | 
 | 375 |       don't want either parent nor child to proceed until the tool has | 
| sewardj | f38a74e | 2010-04-12 19:53:05 +0000 | [diff] [blame] | 376 |       been notified of the child's pthread_t. | 
 | 377 |  | 
 | 378 |       Note that parent and child access args[] without a lock, | 
 | 379 |       effectively using args[2] as a spinlock in order to get the | 
 | 380 |       parent to wait until the child passes this point.  The parent | 
 | 381 |       disables checking on xargs[] before creating the child and | 
 | 382 |       re-enables it once the child goes past this point, so the user | 
 | 383 |       never sees the race.  The previous approach (suppressing the | 
 | 384 |       resulting error) was flawed, because it could leave shadow | 
 | 385 |       memory for args[] in a state in which subsequent use of it by | 
 | 386 |       the parent would report further races. */ | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 387 |    xargs[2] = 0; | 
 | 388 |    /* Now we can no longer safely use xargs[]. */ | 
 | 389 |    return (void*) fn( (void*)arg ); | 
 | 390 | } | 
 | 391 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 392 | //----------------------------------------------------------- | 
 | 393 | // glibc:  pthread_create@GLIBC_2.0 | 
 | 394 | // glibc:  pthread_create@@GLIBC_2.1 | 
 | 395 | // glibc:  pthread_create@@GLIBC_2.2.5 | 
 | 396 | // darwin: pthread_create | 
 | 397 | // darwin: pthread_create_suspended_np (trapped) | 
| njn | f76d27a | 2009-05-28 01:53:07 +0000 | [diff] [blame] | 398 | // | 
| sewardj | 28a7f7d | 2009-07-26 20:15:37 +0000 | [diff] [blame] | 399 | /* ensure this has its own frame, so as to make it more distinguishable | 
 | 400 |    in suppressions */ | 
 | 401 | __attribute__((noinline)) | 
| njn | f76d27a | 2009-05-28 01:53:07 +0000 | [diff] [blame] | 402 | static int pthread_create_WRK(pthread_t *thread, const pthread_attr_t *attr, | 
 | 403 |                               void *(*start) (void *), void *arg) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 404 | { | 
 | 405 |    int    ret; | 
 | 406 |    OrigFn fn; | 
 | 407 |    volatile Word xargs[3]; | 
 | 408 |  | 
 | 409 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 410 |    if (TRACE_PTH_FNS) { | 
 | 411 |       fprintf(stderr, "<< pthread_create wrapper"); fflush(stderr); | 
 | 412 |    } | 
 | 413 |    xargs[0] = (Word)start; | 
 | 414 |    xargs[1] = (Word)arg; | 
 | 415 |    xargs[2] = 1; /* serves as a spinlock -- sigh */ | 
| sewardj | f38a74e | 2010-04-12 19:53:05 +0000 | [diff] [blame] | 416 |    /* Disable checking on the spinlock and the two words used to | 
 | 417 |       convey args to the child.  Basically we need to make it appear | 
 | 418 |       as if the child never accessed this area, since merely | 
 | 419 |       suppressing the resulting races does not address the issue that | 
 | 420 |       that piece of the parent's stack winds up in the "wrong" state | 
 | 421 |       and therefore may give rise to mysterious races when the parent | 
 | 422 |       comes to re-use this piece of stack in some other frame. */ | 
 | 423 |    VALGRIND_HG_DISABLE_CHECKING(&xargs, sizeof(xargs)); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 424 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 425 |    VALGRIND_DO_CLIENT_REQUEST_STMT(_VG_USERREQ__HG_PTHREAD_CREATE_BEGIN, | 
 | 426 |                                    0, 0, 0, 0, 0); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 427 |    CALL_FN_W_WWWW(ret, fn, thread,attr,mythread_wrapper,&xargs[0]); | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 428 |    VALGRIND_DO_CLIENT_REQUEST_STMT(_VG_USERREQ__HG_PTHREAD_CREATE_END, | 
 | 429 |                                    0, 0, 0, 0, 0); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 430 |  | 
 | 431 |    if (ret == 0) { | 
 | 432 |       /* we have to wait for the child to notify the tool of its | 
 | 433 |          pthread_t before continuing */ | 
 | 434 |       while (xargs[2] != 0) { | 
| sewardj | eafad3b | 2007-11-18 01:16:52 +0000 | [diff] [blame] | 435 |          /* Do nothing.  We need to spin until the child writes to | 
 | 436 |             xargs[2].  However, that can lead to starvation in the | 
 | 437 |             child and very long delays (eg, tc19_shadowmem on | 
 | 438 |             ppc64-linux Fedora Core 6).  So yield the cpu if we can, | 
 | 439 |             to let the child run at the earliest available | 
 | 440 |             opportunity. */ | 
 | 441 |          sched_yield(); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 442 |       } | 
 | 443 |    } else {  | 
 | 444 |       DO_PthAPIerror( "pthread_create", ret ); | 
 | 445 |    } | 
 | 446 |  | 
| sewardj | f38a74e | 2010-04-12 19:53:05 +0000 | [diff] [blame] | 447 |    /* Reenable checking on the area previously used to communicate | 
 | 448 |       with the child. */ | 
 | 449 |    VALGRIND_HG_ENABLE_CHECKING(&xargs, sizeof(xargs)); | 
 | 450 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 451 |    if (TRACE_PTH_FNS) { | 
 | 452 |       fprintf(stderr, " :: pth_create -> %d >>\n", ret); | 
 | 453 |    } | 
 | 454 |    return ret; | 
 | 455 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 456 | #if defined(VGO_linux) | 
 | 457 |    PTH_FUNC(int, pthreadZucreateZAZa, // pthread_create@* | 
 | 458 |                  pthread_t *thread, const pthread_attr_t *attr, | 
 | 459 |                  void *(*start) (void *), void *arg) { | 
 | 460 |       return pthread_create_WRK(thread, attr, start, arg); | 
 | 461 |    } | 
 | 462 | #elif defined(VGO_darwin) | 
 | 463 |    PTH_FUNC(int, pthreadZucreate, // pthread_create | 
 | 464 |                  pthread_t *thread, const pthread_attr_t *attr, | 
 | 465 |                  void *(*start) (void *), void *arg) { | 
 | 466 |       return pthread_create_WRK(thread, attr, start, arg); | 
 | 467 |    } | 
 | 468 |    PTH_FUNC(int, pthreadZucreateZuZa, // pthread_create_* | 
 | 469 |                  pthread_t *thread, const pthread_attr_t *attr, | 
 | 470 |                  void *(*start) (void *), void *arg) { | 
 | 471 |       // trap anything else | 
 | 472 |       assert(0); | 
 | 473 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 474 | #elif defined(VGO_solaris) | 
 | 475 |    PTH_FUNC(int, pthreadZucreate, // pthread_create | 
 | 476 |                  pthread_t *thread, const pthread_attr_t *attr, | 
 | 477 |                  void *(*start) (void *), void *arg) { | 
 | 478 |       return pthread_create_WRK(thread, attr, start, arg); | 
 | 479 |    } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 480 | #else | 
 | 481 | #  error "Unsupported OS" | 
 | 482 | #endif | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 483 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 484 | #if defined(VGO_solaris) | 
 | 485 | /* Solaris also provides thr_create() in addition to pthread_create(). | 
 | 486 |  * Both pthread_create(3C) and thr_create(3C) are based on private | 
 | 487 |  * _thrp_create(). | 
 | 488 |  */ | 
 | 489 | __attribute__((noinline)) | 
 | 490 | static int thr_create_WRK(void *stk, size_t stksize, void *(*start)(void *), | 
 | 491 |                           void *arg, long flags, thread_t *new_thread) | 
 | 492 | { | 
 | 493 |    int    ret; | 
 | 494 |    OrigFn fn; | 
 | 495 |    volatile Word xargs[3]; | 
 | 496 |  | 
 | 497 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 498 |    if (TRACE_PTH_FNS) { | 
 | 499 |       fprintf(stderr, "<< thr_create wrapper"); fflush(stderr); | 
 | 500 |    } | 
 | 501 |    xargs[0] = (Word)start; | 
 | 502 |    xargs[1] = (Word)arg; | 
 | 503 |    xargs[2] = 1; /* serves as a spinlock -- sigh */ | 
 | 504 |    /* See comments in pthread_create_WRK() */ | 
 | 505 |    VALGRIND_HG_DISABLE_CHECKING(&xargs, sizeof(xargs)); | 
 | 506 |  | 
 | 507 |    VALGRIND_DO_CLIENT_REQUEST_STMT(_VG_USERREQ__HG_PTHREAD_CREATE_BEGIN, | 
 | 508 |                                    0, 0, 0, 0, 0); | 
 | 509 |    CALL_FN_W_6W(ret, fn, stk, stksize, mythread_wrapper, start, flags, | 
 | 510 |                 new_thread); | 
 | 511 |    VALGRIND_DO_CLIENT_REQUEST_STMT(_VG_USERREQ__HG_PTHREAD_CREATE_END, | 
 | 512 |                                    0, 0, 0, 0, 0); | 
 | 513 |  | 
 | 514 |    if (ret == 0) { | 
 | 515 |       while (xargs[2] != 0) { | 
 | 516 |          /* See comments in pthread_create_WRK(). */ | 
 | 517 |          sched_yield(); | 
 | 518 |       } | 
 | 519 |    } else { | 
 | 520 |       DO_PthAPIerror("thr_create", ret); | 
 | 521 |    } | 
 | 522 |  | 
 | 523 |    VALGRIND_HG_ENABLE_CHECKING(&xargs, sizeof(xargs)); | 
 | 524 |  | 
 | 525 |    if (TRACE_PTH_FNS) { | 
 | 526 |       fprintf(stderr, " :: thr_create -> %d >>\n", ret); | 
 | 527 |    } | 
 | 528 |    return ret; | 
 | 529 | } | 
 | 530 |    PTH_FUNC(int, thrZucreate, // thr_create | 
 | 531 |                  void *stk, size_t stksize, void *(*start)(void *), | 
 | 532 |                  void *arg, long flags, thread_t *new_thread) { | 
 | 533 |       return thr_create_WRK(stk, stksize, start, arg, flags, new_thread); | 
 | 534 |    } | 
 | 535 | #endif /* VGO_solaris */ | 
 | 536 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 537 |  | 
 | 538 | //----------------------------------------------------------- | 
 | 539 | // glibc:  pthread_join | 
 | 540 | // darwin: pthread_join | 
 | 541 | // darwin: pthread_join$NOCANCEL$UNIX2003 | 
 | 542 | // darwin  pthread_join$UNIX2003 | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 543 | __attribute__((noinline)) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 544 | static int pthread_join_WRK(pthread_t thread, void** value_pointer) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 545 | { | 
 | 546 |    int ret; | 
 | 547 |    OrigFn fn; | 
 | 548 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 549 |    if (TRACE_PTH_FNS) { | 
 | 550 |       fprintf(stderr, "<< pthread_join wrapper"); fflush(stderr); | 
 | 551 |    } | 
 | 552 |  | 
 | 553 |    CALL_FN_W_WW(ret, fn, thread,value_pointer); | 
 | 554 |  | 
 | 555 |    /* At least with NPTL as the thread library, this is safe because | 
 | 556 |       it is guaranteed (by NPTL) that the joiner will completely gone | 
 | 557 |       before pthread_join (the original) returns.  See email below.*/ | 
 | 558 |    if (ret == 0 /*success*/) { | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 559 |       DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_JOIN_POST, CREQ_PTHREAD_T, thread); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 560 |    } else {  | 
 | 561 |       DO_PthAPIerror( "pthread_join", ret ); | 
 | 562 |    } | 
 | 563 |  | 
 | 564 |    if (TRACE_PTH_FNS) { | 
 | 565 |       fprintf(stderr, " :: pth_join -> %d >>\n", ret); | 
 | 566 |    } | 
 | 567 |    return ret; | 
 | 568 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 569 | #if defined(VGO_linux) | 
 | 570 |    PTH_FUNC(int, pthreadZujoin, // pthread_join | 
 | 571 |             pthread_t thread, void** value_pointer) { | 
 | 572 |       return pthread_join_WRK(thread, value_pointer); | 
 | 573 |    } | 
 | 574 | #elif defined(VGO_darwin) | 
 | 575 |    PTH_FUNC(int, pthreadZujoinZa, // pthread_join* | 
 | 576 |             pthread_t thread, void** value_pointer) { | 
 | 577 |       return pthread_join_WRK(thread, value_pointer); | 
 | 578 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 579 | #elif defined(VGO_solaris) | 
 | 580 |    PTH_FUNC(int, pthreadZujoin, // pthread_join | 
 | 581 |             pthread_t thread, void** value_pointer) { | 
 | 582 |       return pthread_join_WRK(thread, value_pointer); | 
 | 583 |    } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 584 | #else | 
 | 585 | #  error "Unsupported OS" | 
 | 586 | #endif | 
 | 587 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 588 |  | 
 | 589 | /* Behaviour of pthread_join on NPTL: | 
 | 590 |  | 
 | 591 | Me: | 
 | 592 | I have a question re the NPTL pthread_join implementation. | 
 | 593 |  | 
 | 594 |   Suppose I am the thread 'stayer'.   | 
 | 595 |  | 
 | 596 |   If I call pthread_join(quitter), is it guaranteed that the | 
 | 597 |   thread 'quitter' has really exited before pthread_join returns? | 
 | 598 |  | 
 | 599 |   IOW, is it guaranteed that 'quitter' will not execute any further | 
 | 600 |   instructions after pthread_join returns? | 
 | 601 |  | 
 | 602 | I believe this is true based on the following analysis of | 
 | 603 | glibc-2.5 sources.  However am not 100% sure and would appreciate | 
 | 604 | confirmation. | 
 | 605 |  | 
 | 606 |   'quitter' will be running start_thread() in nptl/pthread_create.c | 
 | 607 |  | 
 | 608 |   The last action of start_thread() is to exit via | 
 | 609 |   __exit_thread_inline(0), which simply does sys_exit  | 
 | 610 |   (nptl/pthread_create.c:403) | 
 | 611 |  | 
 | 612 |   'stayer' meanwhile is waiting for lll_wait_tid (pd->tid)  | 
 | 613 |   (call at nptl/pthread_join.c:89) | 
 | 614 |  | 
 | 615 |   As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536, | 
 | 616 |   lll_wait_tid will not return until kernel notifies via futex | 
 | 617 |   wakeup that 'quitter' has terminated. | 
 | 618 |  | 
 | 619 |   Hence pthread_join cannot return until 'quitter' really has | 
 | 620 |   completely disappeared. | 
 | 621 |  | 
 | 622 | Drepper: | 
 | 623 | >   As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536, | 
 | 624 | >   lll_wait_tid will not return until kernel notifies via futex | 
 | 625 | >   wakeup that 'quitter' has terminated. | 
 | 626 | That's the key.  The kernel resets the TID field after the thread is | 
 | 627 | done.  No way the joiner can return before the thread is gone. | 
 | 628 | */ | 
 | 629 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 630 | #if defined(VGO_solaris) | 
 | 631 | /* Solaris also provides thr_join() in addition to pthread_join(). | 
 | 632 |  * Both pthread_join(3C) and thr_join(3C) are based on private _thrp_join(). | 
 | 633 |  * | 
 | 634 |  * :TODO: No functionality is currently provided for joinee == 0 and departed. | 
 | 635 |  *        This would require another client request, of course. | 
 | 636 |  */ | 
 | 637 | __attribute__((noinline)) | 
 | 638 | static int thr_join_WRK(thread_t joinee, thread_t *departed, void **thread_return) | 
 | 639 | { | 
 | 640 |    int ret; | 
 | 641 |    OrigFn fn; | 
 | 642 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 643 |    if (TRACE_PTH_FNS) { | 
 | 644 |       fprintf(stderr, "<< thr_join wrapper"); fflush(stderr); | 
 | 645 |    } | 
 | 646 |  | 
 | 647 |    CALL_FN_W_WWW(ret, fn, joinee, departed, thread_return); | 
 | 648 |  | 
 | 649 |    if (ret == 0 /*success*/) { | 
 | 650 |       DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_JOIN_POST, CREQ_PTHREAD_T, joinee); | 
 | 651 |    } else { | 
 | 652 |       DO_PthAPIerror("thr_join", ret); | 
 | 653 |    } | 
 | 654 |  | 
 | 655 |    if (TRACE_PTH_FNS) { | 
 | 656 |       fprintf(stderr, " :: thr_join -> %d >>\n", ret); | 
 | 657 |    } | 
 | 658 |    return ret; | 
 | 659 | } | 
 | 660 |    PTH_FUNC(int, thrZujoin, // thr_join | 
 | 661 |             thread_t joinee, thread_t *departed, void **thread_return) { | 
 | 662 |       return thr_join_WRK(joinee, departed, thread_return); | 
 | 663 |    } | 
 | 664 | #endif /* VGO_solaris */ | 
 | 665 |  | 
 | 666 |  | 
| philippe | d40aff5 | 2014-06-16 20:00:14 +0000 | [diff] [blame] | 667 | //----------------------------------------------------------- | 
 | 668 | // Ada gcc gnat runtime: | 
 | 669 | // The gnat gcc Ada runtime does not use pthread_join. Instead, it uses | 
 | 670 | // a combination of other pthread primitives to ensure a child thread | 
 | 671 | // is gone. This combination is somewhat functionally equivalent to a | 
 | 672 | // pthread_join. | 
 | 673 | // We wrap two hook procedures called by the gnat gcc Ada runtime | 
 | 674 | // that allows helgrind to understand the semantic of Ada task dependencies | 
 | 675 | // and termination. | 
 | 676 |  | 
 | 677 | // System.Tasking.Debug.Master_Hook is called by a task Dependent to | 
 | 678 | // indicate that its master is identified by master+master_level. | 
 | 679 | void I_WRAP_SONAME_FNNAME_ZU | 
 | 680 |    (Za, | 
 | 681 |     system__tasking__debug__master_hook) | 
 | 682 |      (void *dependent, void *master, int master_level); | 
 | 683 | void I_WRAP_SONAME_FNNAME_ZU | 
 | 684 |    (Za, | 
 | 685 |     system__tasking__debug__master_hook) | 
 | 686 |      (void *dependent, void *master, int master_level) | 
 | 687 | { | 
 | 688 |    OrigFn fn; | 
 | 689 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 690 |    if (TRACE_GNAT_FNS) { | 
 | 691 |      fprintf(stderr, "<< GNAT master_hook wrapper " | 
 | 692 |              "dependent %p master %p master_level %d\n", | 
 | 693 |              dependent, master, master_level); fflush(stderr); | 
 | 694 |    } | 
 | 695 |  | 
 | 696 |    // We call the wrapped function, even if it is a null body. | 
 | 697 |    CALL_FN_v_WWW(fn, dependent, master, master_level); | 
 | 698 |  | 
 | 699 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_GNAT_MASTER_HOOK, | 
 | 700 |                  void*,dependent, void*,master,  | 
 | 701 |                  Word, (Word)master_level); | 
 | 702 |  | 
 | 703 |    if (TRACE_GNAT_FNS) { | 
 | 704 |       fprintf(stderr, " :: GNAT master_hook >>\n"); | 
 | 705 |    } | 
 | 706 | } | 
 | 707 |  | 
 | 708 | // System.Tasking.Debug.Master_Completed_Hook is called by a task to | 
 | 709 | // indicate that it has completed a master. | 
 | 710 | // This indicates that all its Dependent tasks (that identified themselves | 
 | 711 | // with the Master_Hook call) are terminated. Helgrind can consider | 
 | 712 | // at this point that the equivalent of a 'pthread_join' has been done | 
 | 713 | // between self_id and all dependent tasks at master_level. | 
 | 714 | void I_WRAP_SONAME_FNNAME_ZU | 
 | 715 |    (Za, | 
 | 716 |     system__tasking__debug__master_completed_hook) | 
 | 717 |      (void *self_id, int master_level); | 
 | 718 | void I_WRAP_SONAME_FNNAME_ZU | 
 | 719 |    (Za, | 
 | 720 |     system__tasking__debug__master_completed_hook) | 
 | 721 |      (void *self_id, int master_level) | 
 | 722 | { | 
 | 723 |    OrigFn fn; | 
 | 724 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 725 |    if (TRACE_GNAT_FNS) { | 
 | 726 |      fprintf(stderr, "<< GNAT master_completed_hook wrapper " | 
 | 727 |              "self_id %p master_level %d\n", | 
 | 728 |              self_id, master_level); fflush(stderr); | 
 | 729 |    } | 
 | 730 |  | 
 | 731 |    // We call the wrapped function, even if it is a null body. | 
 | 732 |    CALL_FN_v_WW(fn, self_id, master_level); | 
 | 733 |  | 
 | 734 |    DO_CREQ_v_WW(_VG_USERREQ__HG_GNAT_MASTER_COMPLETED_HOOK, | 
 | 735 |                  void*,self_id, Word,(Word)master_level); | 
 | 736 |  | 
 | 737 |    if (TRACE_GNAT_FNS) { | 
 | 738 |       fprintf(stderr, " :: GNAT master_completed_hook >>\n"); | 
 | 739 |    } | 
 | 740 | } | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 741 |  | 
 | 742 | /*----------------------------------------------------------------*/ | 
 | 743 | /*--- pthread_mutex_t functions                                ---*/ | 
 | 744 | /*----------------------------------------------------------------*/ | 
 | 745 |  | 
 | 746 | /* Handled:   pthread_mutex_init pthread_mutex_destroy | 
 | 747 |               pthread_mutex_lock | 
 | 748 |               pthread_mutex_trylock pthread_mutex_timedlock | 
 | 749 |               pthread_mutex_unlock | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 750 | */ | 
 | 751 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 752 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 753 | #if !defined(VGO_solaris) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 754 | // glibc:  pthread_mutex_init | 
 | 755 | // darwin: pthread_mutex_init | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 756 | PTH_FUNC(int, pthreadZumutexZuinit, // pthread_mutex_init | 
 | 757 |               pthread_mutex_t *mutex, | 
 | 758 |               pthread_mutexattr_t* attr) | 
 | 759 | { | 
 | 760 |    int    ret; | 
 | 761 |    long   mbRec; | 
 | 762 |    OrigFn fn; | 
 | 763 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 764 |    if (TRACE_PTH_FNS) { | 
 | 765 |       fprintf(stderr, "<< pthread_mxinit %p", mutex); fflush(stderr); | 
 | 766 |    } | 
 | 767 |  | 
 | 768 |    mbRec = 0; | 
 | 769 |    if (attr) { | 
 | 770 |       int ty, zzz; | 
 | 771 |       zzz = pthread_mutexattr_gettype(attr, &ty); | 
 | 772 |       if (zzz == 0 && ty == PTHREAD_MUTEX_RECURSIVE) | 
 | 773 |          mbRec = 1; | 
 | 774 |    } | 
 | 775 |  | 
 | 776 |    CALL_FN_W_WW(ret, fn, mutex,attr); | 
 | 777 |  | 
 | 778 |    if (ret == 0 /*success*/) { | 
 | 779 |       DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST, | 
 | 780 |                    pthread_mutex_t*,mutex, long,mbRec); | 
 | 781 |    } else {  | 
 | 782 |       DO_PthAPIerror( "pthread_mutex_init", ret ); | 
 | 783 |    } | 
 | 784 |  | 
 | 785 |    if (TRACE_PTH_FNS) { | 
 | 786 |       fprintf(stderr, " :: mxinit -> %d >>\n", ret); | 
 | 787 |    } | 
 | 788 |    return ret; | 
 | 789 | } | 
 | 790 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 791 | #else /* VGO_solaris */ | 
 | 792 |  | 
 | 793 | // Solaris: mutex_init (pthread_mutex_init calls here) | 
 | 794 | PTH_FUNC(int, mutexZuinit, // mutex_init | 
 | 795 |               mutex_t *mutex, int type, void *arg) | 
 | 796 | { | 
 | 797 |    int    ret; | 
 | 798 |    long   mbRec; | 
 | 799 |    OrigFn fn; | 
 | 800 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 801 |    if (TRACE_PTH_FNS) { | 
 | 802 |       fprintf(stderr, "<< mxinit %p", mutex); fflush(stderr); | 
 | 803 |    } | 
 | 804 |  | 
 | 805 |    mbRec = ((type & LOCK_RECURSIVE) != 0) ? 1 : 0; | 
 | 806 |  | 
 | 807 |    CALL_FN_W_WWW(ret, fn, mutex, type, arg); | 
 | 808 |  | 
 | 809 |    if (ret == 0 /*success*/) { | 
 | 810 |       DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST, | 
 | 811 |                    mutex_t *, mutex, long, mbRec); | 
 | 812 |    } else { | 
 | 813 |       DO_PthAPIerror("mutex_init", ret); | 
 | 814 |    } | 
 | 815 |  | 
 | 816 |    if (TRACE_PTH_FNS) { | 
 | 817 |       fprintf(stderr, " :: mxinit -> %d >>\n", ret); | 
 | 818 |    } | 
 | 819 |    return ret; | 
 | 820 | } | 
 | 821 | #endif /* VGO_solaris */ | 
 | 822 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 823 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 824 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 825 | // glibc:   pthread_mutex_destroy | 
 | 826 | // darwin:  pthread_mutex_destroy | 
 | 827 | // Solaris: mutex_destroy (pthread_mutex_destroy is a weak alias) | 
 | 828 | __attribute__((noinline)) | 
 | 829 | static int mutex_destroy_WRK(pthread_mutex_t *mutex) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 830 | { | 
 | 831 |    int    ret; | 
| sewardj | c02f6c4 | 2013-10-14 13:51:25 +0000 | [diff] [blame] | 832 |    unsigned long mutex_is_init; | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 833 |    OrigFn fn; | 
| sewardj | c02f6c4 | 2013-10-14 13:51:25 +0000 | [diff] [blame] | 834 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 835 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 836 |    if (TRACE_PTH_FNS) { | 
 | 837 |       fprintf(stderr, "<< pthread_mxdestroy %p", mutex); fflush(stderr); | 
 | 838 |    } | 
 | 839 |  | 
| sewardj | c02f6c4 | 2013-10-14 13:51:25 +0000 | [diff] [blame] | 840 |    if (mutex != NULL) { | 
 | 841 |       static const pthread_mutex_t mutex_init = PTHREAD_MUTEX_INITIALIZER; | 
 | 842 |       mutex_is_init = my_memcmp(mutex, &mutex_init, sizeof(*mutex)) == 0; | 
 | 843 |    } else { | 
 | 844 |       mutex_is_init = 0; | 
 | 845 |    } | 
 | 846 |  | 
 | 847 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE, | 
 | 848 |                 pthread_mutex_t*, mutex, unsigned long, mutex_is_init); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 849 |  | 
 | 850 |    CALL_FN_W_W(ret, fn, mutex); | 
 | 851 |  | 
 | 852 |    if (ret != 0) { | 
 | 853 |       DO_PthAPIerror( "pthread_mutex_destroy", ret ); | 
 | 854 |    } | 
 | 855 |  | 
 | 856 |    if (TRACE_PTH_FNS) { | 
 | 857 |       fprintf(stderr, " :: mxdestroy -> %d >>\n", ret); | 
 | 858 |    } | 
 | 859 |    return ret; | 
 | 860 | } | 
 | 861 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 862 | #if defined(VGO_linux) || defined(VGO_darwin) | 
 | 863 |    PTH_FUNC(int, pthreadZumutexZudestroy, // pthread_mutex_destroy | 
 | 864 |             pthread_mutex_t *mutex) { | 
 | 865 |       return mutex_destroy_WRK(mutex); | 
 | 866 |    } | 
 | 867 | #elif defined(VGO_solaris) | 
 | 868 |    PTH_FUNC(int, mutexZudestroy, // mutex_destroy | 
 | 869 |             pthread_mutex_t *mutex) { | 
 | 870 |       return mutex_destroy_WRK(mutex); | 
 | 871 |    } | 
 | 872 | #else | 
 | 873 | #  error "Unsupported OS" | 
 | 874 | #endif | 
 | 875 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 876 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 877 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 878 | // glibc:   pthread_mutex_lock | 
 | 879 | // darwin:  pthread_mutex_lock | 
 | 880 | // Solaris: mutex_lock (pthread_mutex_lock is a weak alias) | 
 | 881 | __attribute__((noinline)) | 
 | 882 | static int mutex_lock_WRK(pthread_mutex_t *mutex) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 883 | { | 
 | 884 |    int    ret; | 
 | 885 |    OrigFn fn; | 
 | 886 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 887 |    if (TRACE_PTH_FNS) { | 
 | 888 |       fprintf(stderr, "<< pthread_mxlock %p", mutex); fflush(stderr); | 
 | 889 |    } | 
 | 890 |  | 
 | 891 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE, | 
 | 892 |                 pthread_mutex_t*,mutex, long,0/*!isTryLock*/); | 
 | 893 |  | 
 | 894 |    CALL_FN_W_W(ret, fn, mutex); | 
 | 895 |  | 
 | 896 |    /* There's a hole here: libpthread now knows the lock is locked, | 
 | 897 |       but the tool doesn't, so some other thread could run and detect | 
 | 898 |       that the lock has been acquired by someone (this thread).  Does | 
 | 899 |       this matter?  Not sure, but I don't think so. */ | 
 | 900 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 901 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, | 
 | 902 |                 pthread_mutex_t *, mutex, long, (ret == 0) ? True : False); | 
 | 903 |  | 
 | 904 |    if (ret != 0) { | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 905 |       DO_PthAPIerror( "pthread_mutex_lock", ret ); | 
 | 906 |    } | 
 | 907 |  | 
 | 908 |    if (TRACE_PTH_FNS) { | 
 | 909 |       fprintf(stderr, " :: mxlock -> %d >>\n", ret); | 
 | 910 |    } | 
 | 911 |    return ret; | 
 | 912 | } | 
 | 913 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 914 | #if defined(VGO_linux) || defined(VGO_darwin) | 
 | 915 |    PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock | 
 | 916 |             pthread_mutex_t *mutex) { | 
 | 917 |       return mutex_lock_WRK(mutex); | 
 | 918 |    } | 
 | 919 | #elif defined(VGO_solaris) | 
 | 920 |    PTH_FUNC(int, mutexZulock, // mutex_lock | 
 | 921 |             pthread_mutex_t *mutex) { | 
 | 922 |       return mutex_lock_WRK(mutex); | 
 | 923 |    } | 
 | 924 | #else | 
 | 925 | #  error "Unsupported OS" | 
 | 926 | #endif | 
 | 927 |  | 
 | 928 | #if defined(VGO_solaris) | 
 | 929 | /* Internal to libc. Mutex is usually initialized only implicitly, | 
 | 930 |  * by zeroing mutex_t structure. | 
 | 931 |  */ | 
 | 932 | __attribute__((noinline)) | 
 | 933 | PTH_FUNC(void, lmutexZulock, // lmutex_lock | 
 | 934 |                mutex_t *mutex) | 
 | 935 | { | 
 | 936 |    OrigFn fn; | 
 | 937 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 938 |    if (TRACE_PTH_FNS) { | 
 | 939 |       fprintf(stderr, "<< lmxlock %p", mutex); fflush(stderr); | 
 | 940 |    } | 
 | 941 |  | 
 | 942 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE, | 
 | 943 |                 mutex_t *, mutex, long, 0 /*!isTryLock*/); | 
 | 944 |    CALL_FN_v_W(fn, mutex); | 
 | 945 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, | 
 | 946 |                 mutex_t *, mutex, long, True); | 
 | 947 |  | 
 | 948 |    if (TRACE_PTH_FNS) { | 
 | 949 |       fprintf(stderr, " :: lmxlock >>\n"); | 
 | 950 |    } | 
 | 951 | } | 
 | 952 | #endif /* VGO_solaris */ | 
 | 953 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 954 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 955 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 956 | // glibc:   pthread_mutex_trylock | 
 | 957 | // darwin:  pthread_mutex_trylock | 
 | 958 | // Solaris: mutex_trylock (pthread_mutex_trylock is a weak alias) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 959 | // | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 960 | // pthread_mutex_trylock.  The handling needed here is very similar | 
 | 961 | // to that for pthread_mutex_lock, except that we need to tell | 
 | 962 | // the pre-lock creq that this is a trylock-style operation, and | 
 | 963 | // therefore not to complain if the lock is nonrecursive and  | 
 | 964 | // already locked by this thread -- because then it'll just fail | 
 | 965 | // immediately with EBUSY. | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 966 | __attribute__((noinline)) | 
 | 967 | static int mutex_trylock_WRK(pthread_mutex_t *mutex) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 968 | { | 
 | 969 |    int    ret; | 
 | 970 |    OrigFn fn; | 
 | 971 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 972 |    if (TRACE_PTH_FNS) { | 
 | 973 |       fprintf(stderr, "<< pthread_mxtrylock %p", mutex); fflush(stderr); | 
 | 974 |    } | 
 | 975 |  | 
 | 976 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE, | 
 | 977 |                 pthread_mutex_t*,mutex, long,1/*isTryLock*/); | 
 | 978 |  | 
 | 979 |    CALL_FN_W_W(ret, fn, mutex); | 
 | 980 |  | 
 | 981 |    /* There's a hole here: libpthread now knows the lock is locked, | 
 | 982 |       but the tool doesn't, so some other thread could run and detect | 
 | 983 |       that the lock has been acquired by someone (this thread).  Does | 
 | 984 |       this matter?  Not sure, but I don't think so. */ | 
 | 985 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 986 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, | 
 | 987 |                pthread_mutex_t *, mutex, long, (ret == 0) ? True : False); | 
 | 988 |  | 
 | 989 |    if (ret != 0) { | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 990 |       if (ret != EBUSY) | 
 | 991 |          DO_PthAPIerror( "pthread_mutex_trylock", ret ); | 
 | 992 |    } | 
 | 993 |  | 
 | 994 |    if (TRACE_PTH_FNS) { | 
 | 995 |       fprintf(stderr, " :: mxtrylock -> %d >>\n", ret); | 
 | 996 |    } | 
 | 997 |    return ret; | 
 | 998 | } | 
 | 999 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1000 | #if defined(VGO_linux) || defined(VGO_darwin) | 
 | 1001 |    PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock | 
 | 1002 |             pthread_mutex_t *mutex) { | 
 | 1003 |       return mutex_trylock_WRK(mutex); | 
 | 1004 |    } | 
 | 1005 | #elif defined(VGO_solaris) | 
 | 1006 |    PTH_FUNC(int, mutexZutrylock, // mutex_trylock | 
 | 1007 |             pthread_mutex_t *mutex) { | 
 | 1008 |       return mutex_trylock_WRK(mutex); | 
 | 1009 |    } | 
 | 1010 | #else | 
 | 1011 | #  error "Unsupported OS" | 
 | 1012 | #endif | 
 | 1013 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1014 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1015 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1016 | // glibc:   pthread_mutex_timedlock | 
 | 1017 | // darwin:  (doesn't appear to exist) | 
 | 1018 | // Solaris: pthread_mutex_timedlock | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1019 | // | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1020 | // pthread_mutex_timedlock.  Identical logic to pthread_mutex_trylock. | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1021 | __attribute__((noinline)) | 
 | 1022 | static int mutex_timedlock_WRK(pthread_mutex_t *mutex, | 
 | 1023 |                                void *timeout) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1024 | { | 
 | 1025 |    int    ret; | 
 | 1026 |    OrigFn fn; | 
 | 1027 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1028 |    if (TRACE_PTH_FNS) { | 
 | 1029 |       fprintf(stderr, "<< pthread_mxtimedlock %p %p", mutex, timeout);  | 
 | 1030 |       fflush(stderr); | 
 | 1031 |    } | 
 | 1032 |  | 
 | 1033 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE, | 
 | 1034 |                 pthread_mutex_t*,mutex, long,1/*isTryLock-ish*/); | 
 | 1035 |  | 
 | 1036 |    CALL_FN_W_WW(ret, fn, mutex,timeout); | 
 | 1037 |  | 
 | 1038 |    /* There's a hole here: libpthread now knows the lock is locked, | 
 | 1039 |       but the tool doesn't, so some other thread could run and detect | 
 | 1040 |       that the lock has been acquired by someone (this thread).  Does | 
 | 1041 |       this matter?  Not sure, but I don't think so. */ | 
 | 1042 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1043 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, | 
 | 1044 |                 pthread_mutex_t *, mutex, long, (ret == 0) ? True : False); | 
 | 1045 |  | 
 | 1046 |    if (ret != 0) { | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1047 |       if (ret != ETIMEDOUT) | 
 | 1048 |          DO_PthAPIerror( "pthread_mutex_timedlock", ret ); | 
 | 1049 |    } | 
 | 1050 |  | 
 | 1051 |    if (TRACE_PTH_FNS) { | 
 | 1052 |       fprintf(stderr, " :: mxtimedlock -> %d >>\n", ret); | 
 | 1053 |    } | 
 | 1054 |    return ret; | 
 | 1055 | } | 
 | 1056 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1057 | PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock | 
 | 1058 |          pthread_mutex_t *mutex, | 
 | 1059 |          void *timeout) { | 
 | 1060 |    return mutex_timedlock_WRK(mutex, timeout); | 
 | 1061 | } | 
 | 1062 | #if defined(VGO_solaris) | 
 | 1063 | PTH_FUNC(int, pthreadZumutexZureltimedlock, // pthread_mutex_reltimedlock | 
 | 1064 |          pthread_mutex_t *mutex, | 
 | 1065 |          void *timeout) { | 
 | 1066 |    return mutex_timedlock_WRK(mutex, timeout); | 
 | 1067 | } | 
 | 1068 | #endif | 
 | 1069 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1070 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1071 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1072 | // glibc:   pthread_mutex_unlock | 
 | 1073 | // darwin:  pthread_mutex_unlock | 
 | 1074 | // Solaris: mutex_unlock (pthread_mutex_unlock is a weak alias) | 
 | 1075 | __attribute__((noinline)) | 
 | 1076 | static int mutex_unlock_WRK(pthread_mutex_t *mutex) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1077 | { | 
 | 1078 |    int    ret; | 
 | 1079 |    OrigFn fn; | 
 | 1080 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1081 |  | 
 | 1082 |    if (TRACE_PTH_FNS) { | 
 | 1083 |       fprintf(stderr, "<< pthread_mxunlk %p", mutex); fflush(stderr); | 
 | 1084 |    } | 
 | 1085 |  | 
 | 1086 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE, | 
 | 1087 |                pthread_mutex_t*,mutex); | 
 | 1088 |  | 
 | 1089 |    CALL_FN_W_W(ret, fn, mutex); | 
 | 1090 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1091 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST, | 
 | 1092 |                pthread_mutex_t*,mutex); | 
 | 1093 |  | 
 | 1094 |    if (ret != 0) { | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1095 |       DO_PthAPIerror( "pthread_mutex_unlock", ret ); | 
 | 1096 |    } | 
 | 1097 |  | 
 | 1098 |    if (TRACE_PTH_FNS) { | 
 | 1099 |       fprintf(stderr, " mxunlk -> %d >>\n", ret); | 
 | 1100 |    } | 
 | 1101 |    return ret; | 
 | 1102 | } | 
 | 1103 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1104 | #if defined(VGO_linux) || defined(VGO_darwin) | 
 | 1105 |    PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock | 
 | 1106 |             pthread_mutex_t *mutex) { | 
 | 1107 |       return mutex_unlock_WRK(mutex); | 
 | 1108 |    } | 
 | 1109 | #elif defined(VGO_solaris) | 
 | 1110 |    PTH_FUNC(int, mutexZuunlock, // mutex_unlock | 
 | 1111 |             pthread_mutex_t *mutex) { | 
 | 1112 |       return mutex_unlock_WRK(mutex); | 
 | 1113 |    } | 
 | 1114 | #else | 
 | 1115 | #  error "Unsupported OS" | 
 | 1116 | #endif | 
 | 1117 |  | 
 | 1118 |  | 
 | 1119 | #if defined(VGO_solaris) | 
 | 1120 | /* Internal to libc. */ | 
 | 1121 | __attribute__((noinline)) | 
 | 1122 | PTH_FUNC(void, lmutexZuunlock, // lmutex_unlock | 
 | 1123 |                mutex_t *mutex) | 
 | 1124 | { | 
 | 1125 |    OrigFn fn; | 
 | 1126 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1127 |  | 
 | 1128 |    if (TRACE_PTH_FNS) { | 
 | 1129 |       fprintf(stderr, "<< lmxunlk %p", mutex); fflush(stderr); | 
 | 1130 |    } | 
 | 1131 |  | 
 | 1132 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE, | 
 | 1133 |                mutex_t *, mutex); | 
 | 1134 |    CALL_FN_v_W(fn, mutex); | 
 | 1135 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST, | 
 | 1136 |                mutex_t*, mutex); | 
 | 1137 |  | 
 | 1138 |    if (TRACE_PTH_FNS) { | 
 | 1139 |       fprintf(stderr, " lmxunlk >>\n"); | 
 | 1140 |    } | 
 | 1141 | } | 
 | 1142 | #endif /* VGO_solaris */ | 
 | 1143 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1144 |  | 
 | 1145 | /*----------------------------------------------------------------*/ | 
 | 1146 | /*--- pthread_cond_t functions                                 ---*/ | 
 | 1147 | /*----------------------------------------------------------------*/ | 
 | 1148 |  | 
 | 1149 | /* Handled:   pthread_cond_wait pthread_cond_timedwait | 
 | 1150 |               pthread_cond_signal pthread_cond_broadcast | 
| philippe | 19dfe03 | 2013-03-24 20:10:23 +0000 | [diff] [blame] | 1151 |               pthread_cond_init | 
| sewardj | f98e1c0 | 2008-10-25 16:22:41 +0000 | [diff] [blame] | 1152 |               pthread_cond_destroy | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1153 | */ | 
 | 1154 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1155 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1156 | // glibc:   pthread_cond_wait@GLIBC_2.2.5 | 
 | 1157 | // glibc:   pthread_cond_wait@@GLIBC_2.3.2 | 
 | 1158 | // darwin:  pthread_cond_wait | 
 | 1159 | // darwin:  pthread_cond_wait$NOCANCEL$UNIX2003 | 
 | 1160 | // darwin:  pthread_cond_wait$UNIX2003 | 
 | 1161 | // Solaris: cond_wait (pthread_cond_wait is built atop of cond_wait) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1162 | // | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 1163 | __attribute__((noinline)) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1164 | static int pthread_cond_wait_WRK(pthread_cond_t* cond, | 
 | 1165 |                                  pthread_mutex_t* mutex) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1166 | { | 
 | 1167 |    int ret; | 
 | 1168 |    OrigFn fn; | 
 | 1169 |    unsigned long mutex_is_valid; | 
 | 1170 |  | 
 | 1171 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1172 |  | 
 | 1173 |    if (TRACE_PTH_FNS) { | 
 | 1174 |       fprintf(stderr, "<< pthread_cond_wait %p %p", cond, mutex); | 
 | 1175 |       fflush(stderr); | 
 | 1176 |    } | 
 | 1177 |  | 
 | 1178 |    /* Tell the tool a cond-wait is about to happen, so it can check | 
 | 1179 |       for bogus argument values.  In return it tells us whether it | 
 | 1180 |       thinks the mutex is valid or not. */ | 
 | 1181 |    DO_CREQ_W_WW(mutex_is_valid, | 
 | 1182 |                 _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE, | 
 | 1183 |                 pthread_cond_t*,cond, pthread_mutex_t*,mutex); | 
 | 1184 |    assert(mutex_is_valid == 1 || mutex_is_valid == 0); | 
 | 1185 |  | 
 | 1186 |    /* Tell the tool we're about to drop the mutex.  This reflects the | 
 | 1187 |       fact that in a cond_wait, we show up holding the mutex, and the | 
 | 1188 |       call atomically drops the mutex and waits for the cv to be | 
 | 1189 |       signalled. */ | 
 | 1190 |    if (mutex_is_valid) { | 
 | 1191 |       DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE, | 
 | 1192 |                   pthread_mutex_t*,mutex); | 
 | 1193 |    } | 
 | 1194 |  | 
 | 1195 |    CALL_FN_W_WW(ret, fn, cond,mutex); | 
 | 1196 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1197 |    /* this conditional look stupid, but compare w/ same logic for | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1198 |       pthread_cond_timedwait below */ | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1199 |    if (mutex_is_valid) { | 
 | 1200 |       /* and now we have the mutex again if (ret == 0) */ | 
 | 1201 |       DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, | 
 | 1202 |                    pthread_mutex_t *, mutex, long, (ret == 0) ? True : False); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1203 |    } | 
 | 1204 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1205 |    DO_CREQ_v_WWWW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST, | 
 | 1206 |                   pthread_cond_t*,cond, pthread_mutex_t*,mutex, long,0, | 
 | 1207 |                   long, (ret == 0 && mutex_is_valid) ? True : False); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1208 |  | 
 | 1209 |    if (ret != 0) { | 
 | 1210 |       DO_PthAPIerror( "pthread_cond_wait", ret ); | 
 | 1211 |    } | 
 | 1212 |  | 
 | 1213 |    if (TRACE_PTH_FNS) { | 
 | 1214 |       fprintf(stderr, " cowait -> %d >>\n", ret); | 
 | 1215 |    } | 
 | 1216 |  | 
 | 1217 |    return ret; | 
 | 1218 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1219 | #if defined(VGO_linux) | 
 | 1220 |    PTH_FUNC(int, pthreadZucondZuwaitZAZa, // pthread_cond_wait@* | 
 | 1221 |                  pthread_cond_t* cond, pthread_mutex_t* mutex) { | 
 | 1222 |       return pthread_cond_wait_WRK(cond, mutex); | 
 | 1223 |    } | 
 | 1224 | #elif defined(VGO_darwin) | 
 | 1225 |    PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait* | 
 | 1226 |                  pthread_cond_t* cond, pthread_mutex_t* mutex) { | 
 | 1227 |       return pthread_cond_wait_WRK(cond, mutex); | 
 | 1228 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1229 | #elif defined(VGO_solaris) | 
 | 1230 |    PTH_FUNC(int, condZuwait, // cond_wait | 
 | 1231 |                  pthread_cond_t *cond, pthread_mutex_t *mutex) { | 
 | 1232 |       return pthread_cond_wait_WRK(cond, mutex); | 
 | 1233 |    } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1234 | #else | 
 | 1235 | #  error "Unsupported OS" | 
 | 1236 | #endif | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1237 |  | 
 | 1238 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1239 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1240 | // glibc:   pthread_cond_timedwait@@GLIBC_2.3.2 | 
 | 1241 | // glibc:   pthread_cond_timedwait@GLIBC_2.2.5 | 
 | 1242 | // glibc:   pthread_cond_timedwait@GLIBC_2.0 | 
 | 1243 | // darwin:  pthread_cond_timedwait | 
 | 1244 | // darwin:  pthread_cond_timedwait$NOCANCEL$UNIX2003 | 
 | 1245 | // darwin:  pthread_cond_timedwait$UNIX2003 | 
 | 1246 | // darwin:  pthread_cond_timedwait_relative_np (trapped) | 
 | 1247 | // Solaris: cond_timedwait (pthread_cond_timedwait is built on cond_timedwait) | 
 | 1248 | // Solaris: cond_reltimedwait (pthread_cond_reltimedwait_np is built on this) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1249 | // | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 1250 | __attribute__((noinline)) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1251 | static int pthread_cond_timedwait_WRK(pthread_cond_t* cond, | 
 | 1252 |                                       pthread_mutex_t* mutex,  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1253 |                                       struct timespec* abstime, | 
 | 1254 |                                       int timeout_error) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1255 | { | 
 | 1256 |    int ret; | 
 | 1257 |    OrigFn fn; | 
 | 1258 |    unsigned long mutex_is_valid; | 
| sewardj | 6aeadaa | 2011-10-19 05:41:34 +0000 | [diff] [blame] | 1259 |    Bool abstime_is_valid; | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1260 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1261 |  | 
 | 1262 |    if (TRACE_PTH_FNS) { | 
 | 1263 |       fprintf(stderr, "<< pthread_cond_timedwait %p %p %p",  | 
 | 1264 |                       cond, mutex, abstime); | 
 | 1265 |       fflush(stderr); | 
 | 1266 |    } | 
 | 1267 |  | 
 | 1268 |    /* Tell the tool a cond-wait is about to happen, so it can check | 
 | 1269 |       for bogus argument values.  In return it tells us whether it | 
 | 1270 |       thinks the mutex is valid or not. */ | 
 | 1271 |    DO_CREQ_W_WW(mutex_is_valid, | 
 | 1272 |                 _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE, | 
 | 1273 |                 pthread_cond_t*,cond, pthread_mutex_t*,mutex); | 
 | 1274 |    assert(mutex_is_valid == 1 || mutex_is_valid == 0); | 
 | 1275 |  | 
| sewardj | 6aeadaa | 2011-10-19 05:41:34 +0000 | [diff] [blame] | 1276 |    abstime_is_valid = abstime->tv_nsec >= 0 && abstime->tv_nsec < 1000000000; | 
 | 1277 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1278 |    /* Tell the tool we're about to drop the mutex.  This reflects the | 
 | 1279 |       fact that in a cond_wait, we show up holding the mutex, and the | 
 | 1280 |       call atomically drops the mutex and waits for the cv to be | 
 | 1281 |       signalled. */ | 
| sewardj | 6aeadaa | 2011-10-19 05:41:34 +0000 | [diff] [blame] | 1282 |    if (mutex_is_valid && abstime_is_valid) { | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1283 |       DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE, | 
 | 1284 |                   pthread_mutex_t*,mutex); | 
 | 1285 |    } | 
 | 1286 |  | 
 | 1287 |    CALL_FN_W_WWW(ret, fn, cond,mutex,abstime); | 
 | 1288 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1289 |    if (mutex_is_valid && !abstime_is_valid && ret != EINVAL) { | 
| sewardj | 6aeadaa | 2011-10-19 05:41:34 +0000 | [diff] [blame] | 1290 |       DO_PthAPIerror("Bug in libpthread: pthread_cond_timedwait " | 
 | 1291 |                      "invalid abstime did not cause" | 
 | 1292 |                      " EINVAL", ret); | 
 | 1293 |    } | 
 | 1294 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1295 |    if (mutex_is_valid && abstime_is_valid) { | 
 | 1296 |       /* and now we have the mutex again if (ret == 0 || ret == timeout) */ | 
 | 1297 |       DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, | 
 | 1298 |                    pthread_mutex_t *, mutex, | 
 | 1299 |                    long, (ret == 0 || ret == timeout_error) ? True : False); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1300 |    } | 
 | 1301 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1302 |    DO_CREQ_v_WWWW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST, | 
 | 1303 |                   pthread_cond_t*,cond, pthread_mutex_t*,mutex, | 
 | 1304 |                   long,ret == timeout_error, | 
 | 1305 |                   long, (ret == 0 || ret == timeout_error) && mutex_is_valid | 
 | 1306 |                         ? True : False); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1307 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1308 |    if (ret != 0 && ret != timeout_error) { | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1309 |       DO_PthAPIerror( "pthread_cond_timedwait", ret ); | 
 | 1310 |    } | 
 | 1311 |  | 
 | 1312 |    if (TRACE_PTH_FNS) { | 
 | 1313 |       fprintf(stderr, " cotimedwait -> %d >>\n", ret); | 
 | 1314 |    } | 
 | 1315 |  | 
 | 1316 |    return ret; | 
 | 1317 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1318 | #if defined(VGO_linux) | 
 | 1319 |    PTH_FUNC(int, pthreadZucondZutimedwaitZAZa, // pthread_cond_timedwait@* | 
 | 1320 |                  pthread_cond_t* cond, pthread_mutex_t* mutex,  | 
 | 1321 |                  struct timespec* abstime) { | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1322 |       return pthread_cond_timedwait_WRK(cond, mutex, abstime, ETIMEDOUT); | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1323 |    } | 
 | 1324 | #elif defined(VGO_darwin) | 
 | 1325 |    PTH_FUNC(int, pthreadZucondZutimedwait, // pthread_cond_timedwait | 
 | 1326 |                  pthread_cond_t* cond, pthread_mutex_t* mutex,  | 
 | 1327 |                  struct timespec* abstime) { | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1328 |       return pthread_cond_timedwait_WRK(cond, mutex, abstime, ETIMEDOUT); | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1329 |    } | 
 | 1330 |    PTH_FUNC(int, pthreadZucondZutimedwaitZDZa, // pthread_cond_timedwait$* | 
 | 1331 |                  pthread_cond_t* cond, pthread_mutex_t* mutex,  | 
 | 1332 |                  struct timespec* abstime) { | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1333 |       return pthread_cond_timedwait_WRK(cond, mutex, abstime, ETIMEDOUT); | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1334 |    } | 
 | 1335 |    PTH_FUNC(int, pthreadZucondZutimedwaitZuZa, // pthread_cond_timedwait_* | 
 | 1336 |                  pthread_cond_t* cond, pthread_mutex_t* mutex,  | 
 | 1337 |                  struct timespec* abstime) { | 
 | 1338 |       assert(0); | 
 | 1339 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1340 | #elif defined(VGO_solaris) | 
 | 1341 |    PTH_FUNC(int, condZutimedwait, // cond_timedwait | 
 | 1342 |                  pthread_cond_t *cond, pthread_mutex_t *mutex, | 
 | 1343 |                  struct timespec *abstime) { | 
 | 1344 |       return pthread_cond_timedwait_WRK(cond, mutex, abstime, ETIME); | 
 | 1345 |    } | 
 | 1346 |    PTH_FUNC(int, condZureltimedwait, // cond_reltimedwait | 
 | 1347 |                  pthread_cond_t *cond, pthread_mutex_t *mutex, | 
 | 1348 |                  struct timespec *reltime) { | 
 | 1349 |       return pthread_cond_timedwait_WRK(cond, mutex, reltime, ETIME); | 
 | 1350 |    } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1351 | #else | 
 | 1352 | #  error "Unsupported OS" | 
 | 1353 | #endif | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1354 |  | 
 | 1355 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1356 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1357 | // glibc:   pthread_cond_signal@GLIBC_2.0 | 
 | 1358 | // glibc:   pthread_cond_signal@GLIBC_2.2.5 | 
 | 1359 | // glibc:   pthread_cond_signal@@GLIBC_2.3.2 | 
 | 1360 | // darwin:  pthread_cond_signal | 
 | 1361 | // darwin:  pthread_cond_signal_thread_np (don't intercept this) | 
 | 1362 | // Solaris: cond_signal (pthread_cond_signal is a weak alias) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1363 | // | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 1364 | __attribute__((noinline)) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1365 | static int pthread_cond_signal_WRK(pthread_cond_t* cond) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1366 | { | 
 | 1367 |    int ret; | 
 | 1368 |    OrigFn fn; | 
 | 1369 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1370 |  | 
 | 1371 |    if (TRACE_PTH_FNS) { | 
 | 1372 |       fprintf(stderr, "<< pthread_cond_signal %p", cond); | 
 | 1373 |       fflush(stderr); | 
 | 1374 |    } | 
 | 1375 |  | 
 | 1376 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_SIGNAL_PRE, | 
 | 1377 |                pthread_cond_t*,cond); | 
 | 1378 |  | 
 | 1379 |    CALL_FN_W_W(ret, fn, cond); | 
 | 1380 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1381 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_SIGNAL_POST, | 
 | 1382 |                pthread_cond_t*,cond); | 
 | 1383 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1384 |    if (ret != 0) { | 
 | 1385 |       DO_PthAPIerror( "pthread_cond_signal", ret ); | 
 | 1386 |    } | 
 | 1387 |  | 
 | 1388 |    if (TRACE_PTH_FNS) { | 
 | 1389 |       fprintf(stderr, " cosig -> %d >>\n", ret); | 
 | 1390 |    } | 
 | 1391 |  | 
 | 1392 |    return ret; | 
 | 1393 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1394 | #if defined(VGO_linux) | 
 | 1395 |    PTH_FUNC(int, pthreadZucondZusignalZAZa, // pthread_cond_signal@* | 
 | 1396 |                  pthread_cond_t* cond) { | 
 | 1397 |       return pthread_cond_signal_WRK(cond); | 
 | 1398 |    } | 
 | 1399 | #elif defined(VGO_darwin) | 
 | 1400 |    PTH_FUNC(int, pthreadZucondZusignal, // pthread_cond_signal | 
 | 1401 |                  pthread_cond_t* cond) { | 
 | 1402 |       return pthread_cond_signal_WRK(cond); | 
 | 1403 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1404 | #elif defined(VGO_solaris) | 
 | 1405 |    PTH_FUNC(int, condZusignal, // cond_signal | 
 | 1406 |                  pthread_cond_t *cond) { | 
 | 1407 |       return pthread_cond_signal_WRK(cond); | 
 | 1408 |    } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1409 | #else | 
 | 1410 | #  error "Unsupported OS" | 
 | 1411 | #endif | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1412 |  | 
 | 1413 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1414 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1415 | // glibc:   pthread_cond_broadcast@GLIBC_2.0 | 
 | 1416 | // glibc:   pthread_cond_broadcast@GLIBC_2.2.5 | 
 | 1417 | // glibc:   pthread_cond_broadcast@@GLIBC_2.3.2 | 
 | 1418 | // darwin:  pthread_cond_broadcast | 
 | 1419 | // Solaris: cond_broadcast (pthread_cond_broadcast is a weak alias) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1420 | // | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1421 | // Note, this is pretty much identical, from a dependency-graph | 
 | 1422 | // point of view, with cond_signal, so the code is duplicated. | 
 | 1423 | // Maybe it should be commoned up. | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1424 | // | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 1425 | __attribute__((noinline)) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1426 | static int pthread_cond_broadcast_WRK(pthread_cond_t* cond) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1427 | { | 
 | 1428 |    int ret; | 
 | 1429 |    OrigFn fn; | 
 | 1430 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1431 |  | 
 | 1432 |    if (TRACE_PTH_FNS) { | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1433 |       fprintf(stderr, "<< pthread_cond_broadcast %p", cond); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1434 |       fflush(stderr); | 
 | 1435 |    } | 
 | 1436 |  | 
 | 1437 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_BROADCAST_PRE, | 
 | 1438 |                pthread_cond_t*,cond); | 
 | 1439 |  | 
 | 1440 |    CALL_FN_W_W(ret, fn, cond); | 
 | 1441 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1442 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_BROADCAST_POST, | 
 | 1443 |                pthread_cond_t*,cond); | 
 | 1444 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1445 |    if (ret != 0) {  | 
 | 1446 |       DO_PthAPIerror( "pthread_cond_broadcast", ret ); | 
 | 1447 |    } | 
 | 1448 |  | 
 | 1449 |    if (TRACE_PTH_FNS) { | 
 | 1450 |       fprintf(stderr, " cobro -> %d >>\n", ret); | 
 | 1451 |    } | 
 | 1452 |  | 
 | 1453 |    return ret; | 
 | 1454 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1455 | #if defined(VGO_linux) | 
 | 1456 |    PTH_FUNC(int, pthreadZucondZubroadcastZAZa, // pthread_cond_broadcast@* | 
 | 1457 |                  pthread_cond_t* cond) { | 
 | 1458 |       return pthread_cond_broadcast_WRK(cond); | 
 | 1459 |    } | 
 | 1460 | #elif defined(VGO_darwin) | 
 | 1461 |    PTH_FUNC(int, pthreadZucondZubroadcast, // pthread_cond_broadcast | 
 | 1462 |                  pthread_cond_t* cond) { | 
 | 1463 |       return pthread_cond_broadcast_WRK(cond); | 
 | 1464 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1465 | #elif defined(VGO_solaris) | 
 | 1466 |    PTH_FUNC(int, condZubroadcast, // cond_broadcast | 
 | 1467 |                  pthread_cond_t *cond) { | 
 | 1468 |       return pthread_cond_broadcast_WRK(cond); | 
 | 1469 |    } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1470 | #else | 
 | 1471 | #   error "Unsupported OS" | 
 | 1472 | #endif | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1473 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1474 | // glibc:   pthread_cond_init@GLIBC_2.0 | 
 | 1475 | // glibc:   pthread_cond_init@GLIBC_2.2.5 | 
 | 1476 | // glibc:   pthread_cond_init@@GLIBC_2.3.2 | 
 | 1477 | // darwin:  pthread_cond_init | 
 | 1478 | // Solaris: cond_init (pthread_cond_init is built atop on this function) | 
| philippe | 19dfe03 | 2013-03-24 20:10:23 +0000 | [diff] [blame] | 1479 | // Easy way out: Handling of attr could have been messier. | 
 | 1480 | // It turns out that pthread_cond_init under linux ignores | 
 | 1481 | // all information in cond_attr, so do we. | 
 | 1482 | // FIXME: MacOS X? | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1483 | #if !defined(VGO_solaris) | 
| philippe | 19dfe03 | 2013-03-24 20:10:23 +0000 | [diff] [blame] | 1484 | __attribute__((noinline)) | 
 | 1485 | static int pthread_cond_init_WRK(pthread_cond_t* cond, pthread_condattr_t *cond_attr) | 
 | 1486 | { | 
 | 1487 |    int ret; | 
 | 1488 |    OrigFn fn; | 
 | 1489 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1490 |  | 
 | 1491 |    if (TRACE_PTH_FNS) { | 
 | 1492 |       fprintf(stderr, "<< pthread_cond_init %p", cond); | 
 | 1493 |       fflush(stderr); | 
 | 1494 |    } | 
 | 1495 |  | 
 | 1496 |    CALL_FN_W_WW(ret, fn, cond, cond_attr); | 
 | 1497 |  | 
 | 1498 |    if (ret == 0) { | 
 | 1499 |       DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_INIT_POST, | 
 | 1500 |                    pthread_cond_t*,cond, pthread_condattr_t*, cond_attr); | 
 | 1501 |    } else { | 
 | 1502 |       DO_PthAPIerror( "pthread_cond_init", ret ); | 
 | 1503 |    } | 
 | 1504 |  | 
 | 1505 |    if (TRACE_PTH_FNS) { | 
 | 1506 |       fprintf(stderr, " coinit -> %d >>\n", ret); | 
 | 1507 |    } | 
 | 1508 |  | 
 | 1509 |    return ret; | 
 | 1510 | } | 
 | 1511 | #if defined(VGO_linux) | 
 | 1512 |    PTH_FUNC(int, pthreadZucondZuinitZAZa, // pthread_cond_init@* | 
 | 1513 | 	    pthread_cond_t* cond, pthread_condattr_t* cond_attr) { | 
 | 1514 |      return pthread_cond_init_WRK(cond, cond_attr); | 
 | 1515 |    } | 
 | 1516 | #elif defined(VGO_darwin) | 
 | 1517 |    PTH_FUNC(int, pthreadZucondZuinit, // pthread_cond_init | 
 | 1518 | 	    pthread_cond_t* cond, pthread_condattr_t * cond_attr) { | 
 | 1519 |      return pthread_cond_init_WRK(cond, cond_attr); | 
 | 1520 |    } | 
 | 1521 | #else | 
 | 1522 | #  error "Unsupported OS" | 
 | 1523 | #endif | 
 | 1524 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1525 | #else /* VGO_solaris */ | 
 | 1526 | __attribute__((noinline)) | 
 | 1527 | PTH_FUNC(int, condZuinit, // cond_init | 
 | 1528 |               cond_t *cond, int type, void *arg) | 
 | 1529 | { | 
 | 1530 |    int ret; | 
 | 1531 |    OrigFn fn; | 
 | 1532 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1533 |  | 
 | 1534 |    if (TRACE_PTH_FNS) { | 
 | 1535 |       fprintf(stderr, "<< cond_init %p", cond); fflush(stderr); | 
 | 1536 |    } | 
 | 1537 |  | 
 | 1538 |    CALL_FN_W_WWW(ret, fn, cond, type, arg); | 
 | 1539 |  | 
 | 1540 |    if (ret == 0) { | 
 | 1541 |       /* Luckily evh__HG_PTHREAD_COND_INIT_POST() ignores cond_attr. | 
 | 1542 |          See also comment for pthread_cond_init_WRK(). */ | 
 | 1543 |       DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_INIT_POST, | 
 | 1544 |                    cond_t *, cond, void *, NULL); | 
 | 1545 |    } else { | 
 | 1546 |       DO_PthAPIerror("cond_init", ret); | 
 | 1547 |    } | 
 | 1548 |  | 
 | 1549 |    if (TRACE_PTH_FNS) { | 
 | 1550 |       fprintf(stderr, " cond_init -> %d >>\n", ret); | 
 | 1551 |    } | 
 | 1552 |  | 
 | 1553 |    return ret; | 
 | 1554 | } | 
 | 1555 | #endif /* VGO_solaris */ | 
 | 1556 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1557 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1558 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1559 | // glibc:   pthread_cond_destroy@@GLIBC_2.3.2 | 
 | 1560 | // glibc:   pthread_cond_destroy@GLIBC_2.2.5 | 
 | 1561 | // glibc:   pthread_cond_destroy@GLIBC_2.0 | 
 | 1562 | // darwin:  pthread_cond_destroy | 
 | 1563 | // Solaris: cond_destroy (pthread_cond_destroy is a weak alias) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1564 | // | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 1565 | __attribute__((noinline)) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1566 | static int pthread_cond_destroy_WRK(pthread_cond_t* cond) | 
| sewardj | f98e1c0 | 2008-10-25 16:22:41 +0000 | [diff] [blame] | 1567 | { | 
 | 1568 |    int ret; | 
| sewardj | c02f6c4 | 2013-10-14 13:51:25 +0000 | [diff] [blame] | 1569 |    unsigned long cond_is_init; | 
| sewardj | f98e1c0 | 2008-10-25 16:22:41 +0000 | [diff] [blame] | 1570 |    OrigFn fn; | 
 | 1571 |  | 
 | 1572 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1573 |  | 
 | 1574 |    if (TRACE_PTH_FNS) { | 
 | 1575 |       fprintf(stderr, "<< pthread_cond_destroy %p", cond); | 
 | 1576 |       fflush(stderr); | 
 | 1577 |    } | 
 | 1578 |  | 
| sewardj | c02f6c4 | 2013-10-14 13:51:25 +0000 | [diff] [blame] | 1579 |    if (cond != NULL) { | 
 | 1580 |       const pthread_cond_t cond_init = PTHREAD_COND_INITIALIZER; | 
 | 1581 |       cond_is_init = my_memcmp(cond, &cond_init, sizeof(*cond)) == 0; | 
 | 1582 |    } else { | 
 | 1583 |      cond_is_init = 0; | 
 | 1584 |    } | 
 | 1585 |  | 
 | 1586 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_DESTROY_PRE, | 
 | 1587 |                 pthread_cond_t*, cond, unsigned long, cond_is_init); | 
| sewardj | f98e1c0 | 2008-10-25 16:22:41 +0000 | [diff] [blame] | 1588 |  | 
 | 1589 |    CALL_FN_W_W(ret, fn, cond); | 
 | 1590 |  | 
 | 1591 |    if (ret != 0) { | 
 | 1592 |       DO_PthAPIerror( "pthread_cond_destroy", ret ); | 
 | 1593 |    } | 
 | 1594 |  | 
 | 1595 |    if (TRACE_PTH_FNS) { | 
 | 1596 |       fprintf(stderr, " codestr -> %d >>\n", ret); | 
 | 1597 |    } | 
 | 1598 |  | 
 | 1599 |    return ret; | 
 | 1600 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1601 | #if defined(VGO_linux) | 
 | 1602 |    PTH_FUNC(int, pthreadZucondZudestroyZAZa, // pthread_cond_destroy@* | 
 | 1603 |                  pthread_cond_t* cond) { | 
 | 1604 |       return pthread_cond_destroy_WRK(cond); | 
 | 1605 |    } | 
 | 1606 | #elif defined(VGO_darwin) | 
 | 1607 |    PTH_FUNC(int, pthreadZucondZudestroy, // pthread_cond_destroy | 
 | 1608 |                  pthread_cond_t* cond) { | 
 | 1609 |       return pthread_cond_destroy_WRK(cond); | 
 | 1610 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1611 | #elif defined(VGO_solaris) | 
 | 1612 |    PTH_FUNC(int, condZudestroy, // cond_destroy | 
 | 1613 |                  pthread_cond_t *cond) { | 
 | 1614 |       return pthread_cond_destroy_WRK(cond); | 
 | 1615 |    } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1616 | #else | 
 | 1617 | #  error "Unsupported OS" | 
 | 1618 | #endif | 
| sewardj | f98e1c0 | 2008-10-25 16:22:41 +0000 | [diff] [blame] | 1619 |  | 
 | 1620 |  | 
 | 1621 | /*----------------------------------------------------------------*/ | 
 | 1622 | /*--- pthread_barrier_t functions                              ---*/ | 
 | 1623 | /*----------------------------------------------------------------*/ | 
 | 1624 |  | 
| njn | f76d27a | 2009-05-28 01:53:07 +0000 | [diff] [blame] | 1625 | #if defined(HAVE_PTHREAD_BARRIER_INIT) | 
 | 1626 |  | 
| sewardj | 9f569b7 | 2008-11-13 13:33:09 +0000 | [diff] [blame] | 1627 | /* Handled:   pthread_barrier_init | 
 | 1628 |               pthread_barrier_wait | 
 | 1629 |               pthread_barrier_destroy | 
 | 1630 |  | 
 | 1631 |    Unhandled: pthread_barrierattr_destroy | 
 | 1632 |               pthread_barrierattr_getpshared | 
 | 1633 |               pthread_barrierattr_init | 
 | 1634 |               pthread_barrierattr_setpshared | 
 | 1635 |               -- are these important? | 
 | 1636 | */ | 
 | 1637 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1638 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1639 | // glibc:   pthread_barrier_init | 
 | 1640 | // darwin:  (doesn't appear to exist) | 
 | 1641 | // Solaris: pthread_barrier_init | 
| sewardj | 9f569b7 | 2008-11-13 13:33:09 +0000 | [diff] [blame] | 1642 | PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init | 
 | 1643 |          pthread_barrier_t* bar, | 
 | 1644 |          pthread_barrierattr_t* attr, unsigned long count) | 
| sewardj | f98e1c0 | 2008-10-25 16:22:41 +0000 | [diff] [blame] | 1645 | { | 
 | 1646 |    int ret; | 
 | 1647 |    OrigFn fn; | 
 | 1648 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1649 |  | 
 | 1650 |    if (TRACE_PTH_FNS) { | 
| sewardj | 9f569b7 | 2008-11-13 13:33:09 +0000 | [diff] [blame] | 1651 |       fprintf(stderr, "<< pthread_barrier_init %p %p %lu", | 
 | 1652 |                       bar, attr, count); | 
| sewardj | f98e1c0 | 2008-10-25 16:22:41 +0000 | [diff] [blame] | 1653 |       fflush(stderr); | 
 | 1654 |    } | 
 | 1655 |  | 
| sewardj | 406bac8 | 2010-03-03 23:03:40 +0000 | [diff] [blame] | 1656 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_BARRIER_INIT_PRE, | 
 | 1657 |                  pthread_barrier_t*, bar, | 
 | 1658 |                  unsigned long, count, | 
 | 1659 |                  unsigned long, 0/*!resizable*/); | 
| sewardj | f98e1c0 | 2008-10-25 16:22:41 +0000 | [diff] [blame] | 1660 |  | 
| sewardj | 9f569b7 | 2008-11-13 13:33:09 +0000 | [diff] [blame] | 1661 |    CALL_FN_W_WWW(ret, fn, bar,attr,count); | 
| sewardj | f98e1c0 | 2008-10-25 16:22:41 +0000 | [diff] [blame] | 1662 |  | 
| sewardj | 9f569b7 | 2008-11-13 13:33:09 +0000 | [diff] [blame] | 1663 |    if (ret != 0) { | 
 | 1664 |       DO_PthAPIerror( "pthread_barrier_init", ret ); | 
 | 1665 |    } | 
 | 1666 |  | 
 | 1667 |    if (TRACE_PTH_FNS) { | 
 | 1668 |       fprintf(stderr, "  pthread_barrier_init -> %d >>\n", ret); | 
 | 1669 |    } | 
 | 1670 |  | 
 | 1671 |    return ret; | 
 | 1672 | } | 
 | 1673 |  | 
 | 1674 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1675 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1676 | // glibc:   pthread_barrier_wait | 
 | 1677 | // darwin:  (doesn't appear to exist) | 
 | 1678 | // Solaris: pthread_barrier_wait | 
| sewardj | 9f569b7 | 2008-11-13 13:33:09 +0000 | [diff] [blame] | 1679 | PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait | 
 | 1680 |               pthread_barrier_t* bar) | 
 | 1681 | { | 
 | 1682 |    int ret; | 
 | 1683 |    OrigFn fn; | 
 | 1684 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1685 |  | 
 | 1686 |    if (TRACE_PTH_FNS) { | 
 | 1687 |       fprintf(stderr, "<< pthread_barrier_wait %p", bar); | 
 | 1688 |       fflush(stderr); | 
 | 1689 |    } | 
 | 1690 |  | 
 | 1691 |    /* That this works correctly, and doesn't screw up when a thread | 
 | 1692 |       leaving the barrier races round to the front and re-enters while | 
 | 1693 |       other threads are still leaving it, is quite subtle.  See | 
 | 1694 |       comments in the handler for PTHREAD_BARRIER_WAIT_PRE in | 
 | 1695 |       hg_main.c. */ | 
 | 1696 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_WAIT_PRE, | 
 | 1697 |                pthread_barrier_t*,bar); | 
 | 1698 |  | 
 | 1699 |    CALL_FN_W_W(ret, fn, bar); | 
 | 1700 |  | 
 | 1701 |    if (ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) { | 
 | 1702 |       DO_PthAPIerror( "pthread_barrier_wait", ret ); | 
 | 1703 |    } | 
| sewardj | f98e1c0 | 2008-10-25 16:22:41 +0000 | [diff] [blame] | 1704 |  | 
 | 1705 |    if (TRACE_PTH_FNS) { | 
 | 1706 |       fprintf(stderr, "  pthread_barrier_wait -> %d >>\n", ret); | 
 | 1707 |    } | 
 | 1708 |  | 
 | 1709 |    return ret; | 
 | 1710 | } | 
 | 1711 |  | 
 | 1712 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 1713 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1714 | // glibc:   pthread_barrier_destroy | 
 | 1715 | // darwin:  (doesn't appear to exist) | 
 | 1716 | // Solaris: pthread_barrier_destroy | 
| sewardj | 9f569b7 | 2008-11-13 13:33:09 +0000 | [diff] [blame] | 1717 | PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy | 
 | 1718 |          pthread_barrier_t* bar) | 
 | 1719 | { | 
 | 1720 |    int ret; | 
 | 1721 |    OrigFn fn; | 
 | 1722 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1723 |  | 
 | 1724 |    if (TRACE_PTH_FNS) { | 
 | 1725 |       fprintf(stderr, "<< pthread_barrier_destroy %p", bar); | 
 | 1726 |       fflush(stderr); | 
 | 1727 |    } | 
 | 1728 |  | 
 | 1729 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_DESTROY_PRE, | 
 | 1730 |                pthread_barrier_t*,bar); | 
 | 1731 |  | 
 | 1732 |    CALL_FN_W_W(ret, fn, bar); | 
 | 1733 |  | 
 | 1734 |    if (ret != 0) { | 
 | 1735 |       DO_PthAPIerror( "pthread_barrier_destroy", ret ); | 
 | 1736 |    } | 
 | 1737 |  | 
 | 1738 |    if (TRACE_PTH_FNS) { | 
 | 1739 |       fprintf(stderr, "  pthread_barrier_destroy -> %d >>\n", ret); | 
 | 1740 |    } | 
 | 1741 |  | 
 | 1742 |    return ret; | 
 | 1743 | } | 
| sewardj | f98e1c0 | 2008-10-25 16:22:41 +0000 | [diff] [blame] | 1744 |  | 
| njn | f76d27a | 2009-05-28 01:53:07 +0000 | [diff] [blame] | 1745 | #endif   // defined(HAVE_PTHREAD_BARRIER_INIT) | 
 | 1746 |  | 
| sewardj | 5a644da | 2009-08-11 10:35:58 +0000 | [diff] [blame] | 1747 |  | 
 | 1748 | /*----------------------------------------------------------------*/ | 
 | 1749 | /*--- pthread_spinlock_t functions                             ---*/ | 
 | 1750 | /*----------------------------------------------------------------*/ | 
 | 1751 |  | 
| petarj | 6d79b74 | 2012-12-20 18:56:57 +0000 | [diff] [blame] | 1752 | #if defined(HAVE_PTHREAD_SPIN_LOCK) \ | 
 | 1753 |     && !defined(DISABLE_PTHREAD_SPINLOCK_INTERCEPT) | 
| sewardj | 5a644da | 2009-08-11 10:35:58 +0000 | [diff] [blame] | 1754 |  | 
 | 1755 | /* Handled:   pthread_spin_init pthread_spin_destroy | 
 | 1756 |               pthread_spin_lock pthread_spin_trylock | 
 | 1757 |               pthread_spin_unlock | 
 | 1758 |  | 
 | 1759 |    Unhandled: | 
 | 1760 | */ | 
 | 1761 |  | 
 | 1762 | /* This is a nasty kludge, in that glibc "knows" that initialising a | 
 | 1763 |    spin lock unlocks it, and pthread_spin_{init,unlock} are names for | 
 | 1764 |    the same function.  Hence we have to have a wrapper which does both | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1765 |    things, without knowing which the user intended to happen. | 
 | 1766 |    Solaris has distinct functions for init/unlock but client requests | 
 | 1767 |    are immutable in helgrind.h so follow the glibc lead. */ | 
| sewardj | 5a644da | 2009-08-11 10:35:58 +0000 | [diff] [blame] | 1768 |  | 
 | 1769 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1770 | // glibc:   pthread_spin_init | 
 | 1771 | // glibc:   pthread_spin_unlock | 
 | 1772 | // darwin:  (doesn't appear to exist) | 
 | 1773 | // Solaris: pthread_spin_init | 
 | 1774 | // Solaris: pthread_spin_unlock | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 1775 | __attribute__((noinline)) | 
| sewardj | 5a644da | 2009-08-11 10:35:58 +0000 | [diff] [blame] | 1776 | static int pthread_spin_init_or_unlock_WRK(pthread_spinlock_t* lock, | 
 | 1777 |                                            int pshared) { | 
 | 1778 |    int    ret; | 
 | 1779 |    OrigFn fn; | 
 | 1780 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1781 |    if (TRACE_PTH_FNS) { | 
 | 1782 |       fprintf(stderr, "<< pthread_spin_iORu %p", lock); fflush(stderr); | 
 | 1783 |    } | 
 | 1784 |  | 
 | 1785 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE, | 
 | 1786 |                pthread_spinlock_t*, lock); | 
 | 1787 |  | 
 | 1788 |    CALL_FN_W_WW(ret, fn, lock,pshared); | 
 | 1789 |  | 
 | 1790 |    if (ret == 0 /*success*/) { | 
 | 1791 |       DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST, | 
 | 1792 |                   pthread_spinlock_t*,lock); | 
 | 1793 |    } else {  | 
 | 1794 |       DO_PthAPIerror( "pthread_spinlock_{init,unlock}", ret ); | 
 | 1795 |    } | 
 | 1796 |  | 
 | 1797 |    if (TRACE_PTH_FNS) { | 
 | 1798 |       fprintf(stderr, " :: spiniORu -> %d >>\n", ret); | 
 | 1799 |    } | 
 | 1800 |    return ret; | 
 | 1801 | } | 
 | 1802 | #if defined(VGO_linux) | 
 | 1803 |    PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init | 
 | 1804 |             pthread_spinlock_t* lock, int pshared) { | 
 | 1805 |       return pthread_spin_init_or_unlock_WRK(lock, pshared); | 
 | 1806 |    } | 
 | 1807 |    PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock | 
 | 1808 |             pthread_spinlock_t* lock) { | 
 | 1809 |       /* this is never actually called */ | 
 | 1810 |       return pthread_spin_init_or_unlock_WRK(lock, 0/*pshared*/); | 
 | 1811 |    } | 
 | 1812 | #elif defined(VGO_darwin) | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1813 | #elif defined(VGO_solaris) | 
 | 1814 |    PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init | 
 | 1815 |             pthread_spinlock_t *lock, int pshared) { | 
 | 1816 |       return pthread_spin_init_or_unlock_WRK(lock, pshared); | 
 | 1817 |    } | 
 | 1818 |    PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock | 
 | 1819 |             pthread_spinlock_t *lock) { | 
 | 1820 |       return pthread_spin_init_or_unlock_WRK(lock, 0/*pshared*/); | 
 | 1821 |    } | 
| sewardj | 5a644da | 2009-08-11 10:35:58 +0000 | [diff] [blame] | 1822 | #else | 
 | 1823 | #  error "Unsupported OS" | 
 | 1824 | #endif | 
 | 1825 |  | 
 | 1826 |  | 
 | 1827 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1828 | // glibc:   pthread_spin_destroy | 
 | 1829 | // darwin:  (doesn't appear to exist) | 
 | 1830 | // Solaris: pthread_spin_destroy | 
 | 1831 | __attribute__((noinline)) | 
 | 1832 | static int pthread_spin_destroy_WRK(pthread_spinlock_t *lock) | 
| sewardj | 5a644da | 2009-08-11 10:35:58 +0000 | [diff] [blame] | 1833 | { | 
 | 1834 |    int    ret; | 
 | 1835 |    OrigFn fn; | 
 | 1836 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1837 |    if (TRACE_PTH_FNS) { | 
 | 1838 |       fprintf(stderr, "<< pthread_spin_destroy %p", lock); | 
 | 1839 |       fflush(stderr); | 
 | 1840 |    } | 
 | 1841 |  | 
 | 1842 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_DESTROY_PRE, | 
 | 1843 |                pthread_spinlock_t*,lock); | 
 | 1844 |  | 
 | 1845 |    CALL_FN_W_W(ret, fn, lock); | 
 | 1846 |  | 
 | 1847 |    if (ret != 0) { | 
 | 1848 |       DO_PthAPIerror( "pthread_spin_destroy", ret ); | 
 | 1849 |    } | 
 | 1850 |  | 
 | 1851 |    if (TRACE_PTH_FNS) { | 
 | 1852 |       fprintf(stderr, " :: spindestroy -> %d >>\n", ret); | 
 | 1853 |    } | 
 | 1854 |    return ret; | 
 | 1855 | } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1856 | #if defined(VGO_linux) | 
| Elliott Hughes | a0664b9 | 2017-04-18 17:46:52 -0700 | [diff] [blame] | 1857 |    PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1858 |             pthread_spinlock_t *lock) { | 
 | 1859 |       return pthread_spin_destroy_WRK(lock); | 
 | 1860 |    } | 
| sewardj | 5a644da | 2009-08-11 10:35:58 +0000 | [diff] [blame] | 1861 | #elif defined(VGO_darwin) | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1862 | #elif defined(VGO_solaris) | 
| Elliott Hughes | a0664b9 | 2017-04-18 17:46:52 -0700 | [diff] [blame] | 1863 |    PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1864 |             pthread_spinlock_t *lock) { | 
 | 1865 |       return pthread_spin_destroy_WRK(lock); | 
 | 1866 |    } | 
| sewardj | 5a644da | 2009-08-11 10:35:58 +0000 | [diff] [blame] | 1867 | #else | 
 | 1868 | #  error "Unsupported OS" | 
 | 1869 | #endif | 
 | 1870 |  | 
 | 1871 |  | 
 | 1872 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1873 | // glibc:   pthread_spin_lock | 
 | 1874 | // darwin:  (doesn't appear to exist) | 
 | 1875 | // Solaris: pthread_spin_lock | 
 | 1876 | __attribute__((noinline)) | 
 | 1877 | static int pthread_spin_lock_WRK(pthread_spinlock_t *lock) | 
| sewardj | 5a644da | 2009-08-11 10:35:58 +0000 | [diff] [blame] | 1878 | { | 
 | 1879 |    int    ret; | 
 | 1880 |    OrigFn fn; | 
 | 1881 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1882 |    if (TRACE_PTH_FNS) { | 
 | 1883 |       fprintf(stderr, "<< pthread_spinlock %p", lock); | 
 | 1884 |       fflush(stderr); | 
 | 1885 |    } | 
 | 1886 |  | 
 | 1887 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE, | 
 | 1888 |                 pthread_spinlock_t*,lock, long,0/*!isTryLock*/); | 
 | 1889 |  | 
 | 1890 |    CALL_FN_W_W(ret, fn, lock); | 
 | 1891 |  | 
 | 1892 |    /* There's a hole here: libpthread now knows the lock is locked, | 
 | 1893 |       but the tool doesn't, so some other thread could run and detect | 
 | 1894 |       that the lock has been acquired by someone (this thread).  Does | 
 | 1895 |       this matter?  Not sure, but I don't think so. */ | 
 | 1896 |  | 
 | 1897 |    if (ret == 0 /*success*/) { | 
 | 1898 |       DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST, | 
 | 1899 |                   pthread_spinlock_t*,lock); | 
 | 1900 |    } else {  | 
 | 1901 |       DO_PthAPIerror( "pthread_spin_lock", ret ); | 
 | 1902 |    } | 
 | 1903 |  | 
 | 1904 |    if (TRACE_PTH_FNS) { | 
 | 1905 |       fprintf(stderr, " :: spinlock -> %d >>\n", ret); | 
 | 1906 |    } | 
 | 1907 |    return ret; | 
 | 1908 | } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1909 | #if defined(VGO_linux) | 
 | 1910 |    PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock | 
 | 1911 |                  pthread_spinlock_t *lock) { | 
 | 1912 |       return pthread_spin_lock_WRK(lock); | 
 | 1913 |    } | 
| sewardj | 5a644da | 2009-08-11 10:35:58 +0000 | [diff] [blame] | 1914 | #elif defined(VGO_darwin) | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1915 | #elif defined(VGO_solaris) | 
 | 1916 |    PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock | 
 | 1917 |                  pthread_spinlock_t *lock) { | 
 | 1918 |       return pthread_spin_lock_WRK(lock); | 
 | 1919 |    } | 
| sewardj | 5a644da | 2009-08-11 10:35:58 +0000 | [diff] [blame] | 1920 | #else | 
 | 1921 | #  error "Unsupported OS" | 
 | 1922 | #endif | 
 | 1923 |  | 
 | 1924 |  | 
 | 1925 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1926 | // glibc:   pthread_spin_trylock | 
 | 1927 | // darwin:  (doesn't appear to exist) | 
 | 1928 | // Solaris: pthread_spin_trylock | 
 | 1929 | __attribute__((noinline)) | 
 | 1930 | static int pthread_spin_trylock_WRK(pthread_spinlock_t *lock) | 
| sewardj | 5a644da | 2009-08-11 10:35:58 +0000 | [diff] [blame] | 1931 | { | 
 | 1932 |    int    ret; | 
 | 1933 |    OrigFn fn; | 
 | 1934 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 1935 |    if (TRACE_PTH_FNS) { | 
 | 1936 |       fprintf(stderr, "<< pthread_spin_trylock %p", lock); | 
 | 1937 |       fflush(stderr); | 
 | 1938 |    } | 
 | 1939 |  | 
 | 1940 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE, | 
 | 1941 |                 pthread_spinlock_t*,lock, long,1/*isTryLock*/); | 
 | 1942 |  | 
 | 1943 |    CALL_FN_W_W(ret, fn, lock); | 
 | 1944 |  | 
 | 1945 |    /* There's a hole here: libpthread now knows the lock is locked, | 
 | 1946 |       but the tool doesn't, so some other thread could run and detect | 
 | 1947 |       that the lock has been acquired by someone (this thread).  Does | 
 | 1948 |       this matter?  Not sure, but I don't think so. */ | 
 | 1949 |  | 
 | 1950 |    if (ret == 0 /*success*/) { | 
 | 1951 |       DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST, | 
 | 1952 |                   pthread_spinlock_t*,lock); | 
 | 1953 |    } else { | 
 | 1954 |       if (ret != EBUSY) | 
 | 1955 |          DO_PthAPIerror( "pthread_spin_trylock", ret ); | 
 | 1956 |    } | 
 | 1957 |  | 
 | 1958 |    if (TRACE_PTH_FNS) { | 
 | 1959 |       fprintf(stderr, " :: spin_trylock -> %d >>\n", ret); | 
 | 1960 |    } | 
 | 1961 |    return ret; | 
 | 1962 | } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1963 | #if defined(VGO_linux) | 
 | 1964 |    PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock | 
 | 1965 |                  pthread_spinlock_t *lock) { | 
 | 1966 |       return pthread_spin_trylock_WRK(lock); | 
 | 1967 |    } | 
| sewardj | 5a644da | 2009-08-11 10:35:58 +0000 | [diff] [blame] | 1968 | #elif defined(VGO_darwin) | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1969 | #elif defined(VGO_solaris) | 
 | 1970 |    PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock | 
 | 1971 |                  pthread_spinlock_t *lock) { | 
 | 1972 |       return pthread_spin_trylock_WRK(lock); | 
 | 1973 |    } | 
| sewardj | 5a644da | 2009-08-11 10:35:58 +0000 | [diff] [blame] | 1974 | #else | 
 | 1975 | #  error "Unsupported OS" | 
 | 1976 | #endif | 
 | 1977 |  | 
 | 1978 | #endif // defined(HAVE_PTHREAD_SPIN_LOCK) | 
 | 1979 |  | 
 | 1980 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1981 | /*----------------------------------------------------------------*/ | 
 | 1982 | /*--- pthread_rwlock_t functions                               ---*/ | 
 | 1983 | /*----------------------------------------------------------------*/ | 
 | 1984 |  | 
| sewardj | 0c09bf0 | 2011-07-11 22:11:58 +0000 | [diff] [blame] | 1985 | /* Android's pthread.h doesn't say anything about rwlocks, hence these | 
 | 1986 |    functions have to be conditionally compiled. */ | 
 | 1987 | #if defined(HAVE_PTHREAD_RWLOCK_T) | 
 | 1988 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1989 | /* Handled:   pthread_rwlock_init pthread_rwlock_destroy | 
 | 1990 |               pthread_rwlock_rdlock  | 
 | 1991 |               pthread_rwlock_wrlock | 
 | 1992 |               pthread_rwlock_unlock | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 1993 |               pthread_rwlock_tryrdlock | 
 | 1994 |               pthread_rwlock_trywrlock | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1995 |  | 
 | 1996 |    Unhandled: pthread_rwlock_timedrdlock | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1997 |               pthread_rwlock_timedwrlock | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 1998 | */ | 
 | 1999 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2000 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2001 | // glibc:   pthread_rwlock_init | 
 | 2002 | // darwin:  pthread_rwlock_init | 
 | 2003 | // darwin:  pthread_rwlock_init$UNIX2003 | 
 | 2004 | // Solaris: rwlock_init (pthread_rwlock_init is built atop of rwlock_init) | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 2005 | __attribute__((noinline)) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2006 | static int pthread_rwlock_init_WRK(pthread_rwlock_t *rwl, | 
 | 2007 |                                    pthread_rwlockattr_t* attr) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2008 | { | 
 | 2009 |    int    ret; | 
 | 2010 |    OrigFn fn; | 
 | 2011 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2012 |    if (TRACE_PTH_FNS) { | 
 | 2013 |       fprintf(stderr, "<< pthread_rwl_init %p", rwl); fflush(stderr); | 
 | 2014 |    } | 
 | 2015 |  | 
 | 2016 |    CALL_FN_W_WW(ret, fn, rwl,attr); | 
 | 2017 |  | 
 | 2018 |    if (ret == 0 /*success*/) { | 
 | 2019 |       DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST, | 
 | 2020 |                   pthread_rwlock_t*,rwl); | 
 | 2021 |    } else {  | 
 | 2022 |       DO_PthAPIerror( "pthread_rwlock_init", ret ); | 
 | 2023 |    } | 
 | 2024 |  | 
 | 2025 |    if (TRACE_PTH_FNS) { | 
 | 2026 |       fprintf(stderr, " :: rwl_init -> %d >>\n", ret); | 
 | 2027 |    } | 
 | 2028 |    return ret; | 
 | 2029 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2030 | #if defined(VGO_linux) | 
 | 2031 |    PTH_FUNC(int, pthreadZurwlockZuinit, // pthread_rwlock_init | 
 | 2032 |                  pthread_rwlock_t *rwl, | 
 | 2033 |                  pthread_rwlockattr_t* attr) { | 
 | 2034 |       return pthread_rwlock_init_WRK(rwl, attr); | 
 | 2035 |    } | 
 | 2036 | #elif defined(VGO_darwin) | 
 | 2037 |    PTH_FUNC(int, pthreadZurwlockZuinitZa, // pthread_rwlock_init* | 
 | 2038 |                  pthread_rwlock_t *rwl, | 
 | 2039 |                  pthread_rwlockattr_t* attr) { | 
 | 2040 |       return pthread_rwlock_init_WRK(rwl, attr); | 
 | 2041 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2042 | #elif defined(VGO_solaris) | 
 | 2043 | static int pthread_rwlock_init_WRK(pthread_rwlock_t *rwl, | 
 | 2044 |                                    pthread_rwlockattr_t* attr) | 
 | 2045 |                                    __attribute__((unused)); | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2046 | #else | 
 | 2047 | #  error "Unsupported OS" | 
 | 2048 | #endif | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2049 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2050 | #if defined(VGO_solaris) | 
 | 2051 | PTH_FUNC(int, rwlockZuinit, // rwlock_init | 
 | 2052 |               rwlock_t *rwlock, | 
 | 2053 |               int type, | 
 | 2054 |               void *arg) | 
 | 2055 | { | 
 | 2056 |    int    ret; | 
 | 2057 |    OrigFn fn; | 
 | 2058 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2059 |    if (TRACE_PTH_FNS) { | 
 | 2060 |       fprintf(stderr, "<< rwl_init %p", rwlock); fflush(stderr); | 
 | 2061 |    } | 
 | 2062 |  | 
 | 2063 |    CALL_FN_W_WWW(ret, fn, rwlock, type, arg); | 
 | 2064 |  | 
 | 2065 |    if (ret == 0 /*success*/) { | 
 | 2066 |       DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST, | 
 | 2067 |                   rwlock_t *, rwlock); | 
 | 2068 |    } else { | 
 | 2069 |       DO_PthAPIerror("rwlock_init", ret); | 
 | 2070 |    } | 
 | 2071 |  | 
 | 2072 |    if (TRACE_PTH_FNS) { | 
 | 2073 |       fprintf(stderr, " :: rwl_init -> %d >>\n", ret); | 
 | 2074 |    } | 
 | 2075 |    return ret; | 
 | 2076 | } | 
 | 2077 | #endif /* VGO_solaris */ | 
 | 2078 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2079 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2080 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2081 | // glibc:   pthread_rwlock_destroy | 
 | 2082 | // darwin:  pthread_rwlock_destroy | 
 | 2083 | // darwin:  pthread_rwlock_destroy$UNIX2003 | 
 | 2084 | // Solaris: rwlock_destroy (pthread_rwlock_destroy is a weak alias) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2085 | // | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 2086 | __attribute__((noinline)) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2087 | static int pthread_rwlock_destroy_WRK(pthread_rwlock_t* rwl) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2088 | { | 
 | 2089 |    int    ret; | 
 | 2090 |    OrigFn fn; | 
 | 2091 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2092 |    if (TRACE_PTH_FNS) { | 
 | 2093 |       fprintf(stderr, "<< pthread_rwl_destroy %p", rwl); fflush(stderr); | 
 | 2094 |    } | 
 | 2095 |  | 
 | 2096 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE, | 
 | 2097 |                pthread_rwlock_t*,rwl); | 
 | 2098 |  | 
 | 2099 |    CALL_FN_W_W(ret, fn, rwl); | 
 | 2100 |  | 
 | 2101 |    if (ret != 0) { | 
 | 2102 |       DO_PthAPIerror( "pthread_rwlock_destroy", ret ); | 
 | 2103 |    } | 
 | 2104 |  | 
 | 2105 |    if (TRACE_PTH_FNS) { | 
 | 2106 |       fprintf(stderr, " :: rwl_destroy -> %d >>\n", ret); | 
 | 2107 |    } | 
 | 2108 |    return ret; | 
 | 2109 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2110 | #if defined(VGO_linux) | 
 | 2111 |    PTH_FUNC(int, pthreadZurwlockZudestroy, // pthread_rwlock_destroy | 
 | 2112 |                  pthread_rwlock_t *rwl) { | 
 | 2113 |       return pthread_rwlock_destroy_WRK(rwl); | 
 | 2114 |    } | 
 | 2115 | #elif defined(VGO_darwin) | 
 | 2116 |    PTH_FUNC(int, pthreadZurwlockZudestroyZa, // pthread_rwlock_destroy* | 
 | 2117 |                  pthread_rwlock_t *rwl) { | 
 | 2118 |       return pthread_rwlock_destroy_WRK(rwl); | 
 | 2119 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2120 | #elif defined(VGO_solaris) | 
 | 2121 |    PTH_FUNC(int, rwlockZudestroy, // rwlock_destroy | 
 | 2122 |                  pthread_rwlock_t *rwl) { | 
 | 2123 |       return pthread_rwlock_destroy_WRK(rwl); | 
 | 2124 |    } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2125 | #else | 
 | 2126 | #  error "Unsupported OS" | 
 | 2127 | #endif | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2128 |  | 
 | 2129 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2130 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2131 | // glibc:   pthread_rwlock_wrlock | 
 | 2132 | // darwin:  pthread_rwlock_wrlock | 
 | 2133 | // darwin:  pthread_rwlock_wrlock$UNIX2003 | 
 | 2134 | // Solaris: rw_wrlock (pthread_rwlock_wrlock is a weak alias) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2135 | // | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 2136 | __attribute__((noinline)) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2137 | static int pthread_rwlock_wrlock_WRK(pthread_rwlock_t* rwlock) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2138 | { | 
 | 2139 |    int    ret; | 
 | 2140 |    OrigFn fn; | 
 | 2141 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2142 |    if (TRACE_PTH_FNS) { | 
 | 2143 |       fprintf(stderr, "<< pthread_rwl_wlk %p", rwlock); fflush(stderr); | 
 | 2144 |    } | 
 | 2145 |  | 
| sewardj | 789c3c5 | 2008-02-25 12:10:07 +0000 | [diff] [blame] | 2146 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE, | 
 | 2147 |                  pthread_rwlock_t*,rwlock,  | 
 | 2148 |                  long,1/*isW*/, long,0/*!isTryLock*/); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2149 |  | 
 | 2150 |    CALL_FN_W_W(ret, fn, rwlock); | 
 | 2151 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2152 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST, | 
 | 2153 |                  pthread_rwlock_t*,rwlock, long,1/*isW*/, | 
 | 2154 |                  long, (ret == 0) ? True : False); | 
 | 2155 |    if (ret != 0) { | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2156 |       DO_PthAPIerror( "pthread_rwlock_wrlock", ret ); | 
 | 2157 |    } | 
 | 2158 |  | 
 | 2159 |    if (TRACE_PTH_FNS) { | 
 | 2160 |       fprintf(stderr, " :: rwl_wlk -> %d >>\n", ret); | 
 | 2161 |    } | 
 | 2162 |    return ret; | 
 | 2163 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2164 | #if defined(VGO_linux) | 
 | 2165 |    PTH_FUNC(int, pthreadZurwlockZuwrlock, // pthread_rwlock_wrlock | 
 | 2166 |                  pthread_rwlock_t* rwlock) { | 
 | 2167 |       return pthread_rwlock_wrlock_WRK(rwlock); | 
 | 2168 |    } | 
 | 2169 | #elif defined(VGO_darwin) | 
 | 2170 |    PTH_FUNC(int, pthreadZurwlockZuwrlockZa, // pthread_rwlock_wrlock* | 
 | 2171 |                  pthread_rwlock_t* rwlock) { | 
 | 2172 |       return pthread_rwlock_wrlock_WRK(rwlock); | 
 | 2173 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2174 | #elif defined(VGO_solaris) | 
 | 2175 |    PTH_FUNC(int, rwZuwrlock, // rw_wrlock | 
 | 2176 |                  pthread_rwlock_t *rwlock) { | 
 | 2177 |       return pthread_rwlock_wrlock_WRK(rwlock); | 
 | 2178 |    } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2179 | #else | 
 | 2180 | #  error "Unsupported OS" | 
 | 2181 | #endif | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2182 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2183 | #if defined(VGO_solaris) | 
 | 2184 | /* Internal to libc. */ | 
 | 2185 | PTH_FUNC(void, lrwZuwrlock, // lrw_wrlock | 
 | 2186 |                rwlock_t *rwlock) | 
 | 2187 | { | 
 | 2188 |    OrigFn fn; | 
 | 2189 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2190 |    if (TRACE_PTH_FNS) { | 
 | 2191 |       fprintf(stderr, "<< lrw_wlk %p", rwlock); fflush(stderr); | 
 | 2192 |    } | 
 | 2193 |  | 
 | 2194 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE, | 
 | 2195 |                  pthread_rwlock_t *, rwlock, | 
 | 2196 |                  long, 1/*isW*/, long, 0/*!isTryLock*/); | 
 | 2197 |  | 
 | 2198 |    CALL_FN_v_W(fn, rwlock); | 
 | 2199 |  | 
 | 2200 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST, | 
 | 2201 |                  pthread_rwlock_t *, rwlock, long, 1/*isW*/, long, True); | 
 | 2202 |  | 
 | 2203 |    if (TRACE_PTH_FNS) { | 
 | 2204 |       fprintf(stderr, " :: lrw_wlk >>\n"); | 
 | 2205 |    } | 
 | 2206 | } | 
 | 2207 | #endif /* VGO_solaris */ | 
 | 2208 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2209 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2210 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2211 | // glibc:   pthread_rwlock_rdlock | 
 | 2212 | // darwin:  pthread_rwlock_rdlock | 
 | 2213 | // darwin:  pthread_rwlock_rdlock$UNIX2003 | 
 | 2214 | // Solaris: rw_rdlock (pthread_rwlock_rdlock is a weak alias) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2215 | // | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 2216 | __attribute__((noinline)) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2217 | static int pthread_rwlock_rdlock_WRK(pthread_rwlock_t* rwlock) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2218 | { | 
 | 2219 |    int    ret; | 
 | 2220 |    OrigFn fn; | 
 | 2221 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2222 |    if (TRACE_PTH_FNS) { | 
 | 2223 |       fprintf(stderr, "<< pthread_rwl_rlk %p", rwlock); fflush(stderr); | 
 | 2224 |    } | 
 | 2225 |  | 
| sewardj | 789c3c5 | 2008-02-25 12:10:07 +0000 | [diff] [blame] | 2226 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE, | 
 | 2227 |                  pthread_rwlock_t*,rwlock, | 
 | 2228 |                  long,0/*!isW*/, long,0/*!isTryLock*/); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2229 |  | 
 | 2230 |    CALL_FN_W_W(ret, fn, rwlock); | 
 | 2231 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2232 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST, | 
 | 2233 |                  pthread_rwlock_t*,rwlock, long,0/*!isW*/, | 
 | 2234 |                  long, (ret == 0) ? True : False); | 
 | 2235 |    if (ret != 0) { | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2236 |       DO_PthAPIerror( "pthread_rwlock_rdlock", ret ); | 
 | 2237 |    } | 
 | 2238 |  | 
 | 2239 |    if (TRACE_PTH_FNS) { | 
 | 2240 |       fprintf(stderr, " :: rwl_rlk -> %d >>\n", ret); | 
 | 2241 |    } | 
 | 2242 |    return ret; | 
 | 2243 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2244 | #if defined(VGO_linux) | 
 | 2245 |    PTH_FUNC(int, pthreadZurwlockZurdlock, // pthread_rwlock_rdlock | 
 | 2246 |                  pthread_rwlock_t* rwlock) { | 
 | 2247 |       return pthread_rwlock_rdlock_WRK(rwlock); | 
 | 2248 |    } | 
 | 2249 | #elif defined(VGO_darwin) | 
 | 2250 |    PTH_FUNC(int, pthreadZurwlockZurdlockZa, // pthread_rwlock_rdlock* | 
 | 2251 |                  pthread_rwlock_t* rwlock) { | 
 | 2252 |       return pthread_rwlock_rdlock_WRK(rwlock); | 
 | 2253 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2254 | #elif defined(VGO_solaris) | 
 | 2255 |    PTH_FUNC(int, rwZurdlock, // rw_rdlock | 
 | 2256 |                  pthread_rwlock_t *rwlock) { | 
 | 2257 |       return pthread_rwlock_rdlock_WRK(rwlock); | 
 | 2258 |    } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2259 | #else | 
 | 2260 | #  error "Unsupported OS" | 
 | 2261 | #endif | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2262 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2263 | #if defined(VGO_solaris) | 
 | 2264 | /* Internal to libc. */ | 
 | 2265 | PTH_FUNC(void, lrwZurdlock, // lrw_rdlock | 
 | 2266 |                rwlock_t *rwlock) | 
 | 2267 | { | 
 | 2268 |    OrigFn fn; | 
 | 2269 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2270 |    if (TRACE_PTH_FNS) { | 
 | 2271 |       fprintf(stderr, "<< lrw_rlk %p", rwlock); fflush(stderr); | 
 | 2272 |    } | 
 | 2273 |  | 
 | 2274 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE, | 
 | 2275 |                  pthread_rwlock_t *, rwlock, | 
 | 2276 |                  long, 0/*!isW*/, long, 0/*!isTryLock*/); | 
 | 2277 |  | 
 | 2278 |    CALL_FN_v_W(fn, rwlock); | 
 | 2279 |  | 
 | 2280 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST, | 
 | 2281 |                  pthread_rwlock_t *, rwlock, long, 0/*!isW*/, long, True); | 
 | 2282 |  | 
 | 2283 |    if (TRACE_PTH_FNS) { | 
 | 2284 |       fprintf(stderr, " :: lrw_rlk ->>\n"); | 
 | 2285 |    } | 
 | 2286 | } | 
 | 2287 | #endif /* VGO_solaris */ | 
 | 2288 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2289 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2290 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2291 | // glibc:   pthread_rwlock_trywrlock | 
 | 2292 | // darwin:  pthread_rwlock_trywrlock | 
 | 2293 | // darwin:  pthread_rwlock_trywrlock$UNIX2003 | 
 | 2294 | // Solaris: rw_trywrlock (pthread_rwlock_trywrlock is a weak alias) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2295 | // | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 2296 | __attribute__((noinline)) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2297 | static int pthread_rwlock_trywrlock_WRK(pthread_rwlock_t* rwlock) | 
| sewardj | 789c3c5 | 2008-02-25 12:10:07 +0000 | [diff] [blame] | 2298 | { | 
 | 2299 |    int    ret; | 
 | 2300 |    OrigFn fn; | 
 | 2301 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2302 |    if (TRACE_PTH_FNS) { | 
 | 2303 |       fprintf(stderr, "<< pthread_rwl_trywlk %p", rwlock); fflush(stderr); | 
 | 2304 |    } | 
 | 2305 |  | 
 | 2306 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE, | 
 | 2307 |                  pthread_rwlock_t*,rwlock,  | 
 | 2308 |                  long,1/*isW*/, long,1/*isTryLock*/); | 
 | 2309 |  | 
 | 2310 |    CALL_FN_W_W(ret, fn, rwlock); | 
 | 2311 |  | 
 | 2312 |    /* There's a hole here: libpthread now knows the lock is locked, | 
 | 2313 |       but the tool doesn't, so some other thread could run and detect | 
 | 2314 |       that the lock has been acquired by someone (this thread).  Does | 
 | 2315 |       this matter?  Not sure, but I don't think so. */ | 
 | 2316 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2317 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST, | 
 | 2318 |                  pthread_rwlock_t*,rwlock, long,1/*isW*/, | 
 | 2319 |                  long, (ret == 0) ? True : False); | 
 | 2320 |    if (ret != 0) { | 
| sewardj | 789c3c5 | 2008-02-25 12:10:07 +0000 | [diff] [blame] | 2321 |       if (ret != EBUSY) | 
 | 2322 |          DO_PthAPIerror( "pthread_rwlock_trywrlock", ret ); | 
 | 2323 |    } | 
 | 2324 |  | 
 | 2325 |    if (TRACE_PTH_FNS) { | 
 | 2326 |       fprintf(stderr, " :: rwl_trywlk -> %d >>\n", ret); | 
 | 2327 |    } | 
 | 2328 |    return ret; | 
 | 2329 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2330 | #if defined(VGO_linux) | 
 | 2331 |    PTH_FUNC(int, pthreadZurwlockZutrywrlock, // pthread_rwlock_trywrlock | 
 | 2332 |                  pthread_rwlock_t* rwlock) { | 
 | 2333 |       return pthread_rwlock_trywrlock_WRK(rwlock); | 
 | 2334 |    } | 
 | 2335 | #elif defined(VGO_darwin) | 
 | 2336 |    PTH_FUNC(int, pthreadZurwlockZutrywrlockZa, // pthread_rwlock_trywrlock* | 
 | 2337 |                  pthread_rwlock_t* rwlock) { | 
 | 2338 |       return pthread_rwlock_trywrlock_WRK(rwlock); | 
 | 2339 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2340 | #elif defined(VGO_solaris) | 
 | 2341 |    PTH_FUNC(int, rwZutrywrlock, // rw_trywrlock | 
 | 2342 |                  pthread_rwlock_t *rwlock) { | 
 | 2343 |       return pthread_rwlock_trywrlock_WRK(rwlock); | 
 | 2344 |    } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2345 | #else | 
 | 2346 | #  error "Unsupported OS" | 
 | 2347 | #endif | 
| sewardj | 789c3c5 | 2008-02-25 12:10:07 +0000 | [diff] [blame] | 2348 |  | 
 | 2349 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2350 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2351 | // glibc:   pthread_rwlock_tryrdlock | 
 | 2352 | // darwin:  pthread_rwlock_tryrdlock | 
 | 2353 | // darwin:  pthread_rwlock_tryrdlock$UNIX2003 | 
 | 2354 | // Solaris: rw_tryrdlock (pthread_rwlock_tryrdlock is a weak alias) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2355 | // | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 2356 | __attribute__((noinline)) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2357 | static int pthread_rwlock_tryrdlock_WRK(pthread_rwlock_t* rwlock) | 
| sewardj | 789c3c5 | 2008-02-25 12:10:07 +0000 | [diff] [blame] | 2358 | { | 
 | 2359 |    int    ret; | 
 | 2360 |    OrigFn fn; | 
 | 2361 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2362 |    if (TRACE_PTH_FNS) { | 
 | 2363 |       fprintf(stderr, "<< pthread_rwl_tryrlk %p", rwlock); fflush(stderr); | 
 | 2364 |    } | 
 | 2365 |  | 
 | 2366 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE, | 
 | 2367 |                  pthread_rwlock_t*,rwlock,  | 
 | 2368 |                  long,0/*!isW*/, long,1/*isTryLock*/); | 
 | 2369 |  | 
 | 2370 |    CALL_FN_W_W(ret, fn, rwlock); | 
 | 2371 |  | 
 | 2372 |    /* There's a hole here: libpthread now knows the lock is locked, | 
 | 2373 |       but the tool doesn't, so some other thread could run and detect | 
 | 2374 |       that the lock has been acquired by someone (this thread).  Does | 
 | 2375 |       this matter?  Not sure, but I don't think so. */ | 
 | 2376 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2377 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST, | 
 | 2378 |                 pthread_rwlock_t*,rwlock, long,0/*!isW*/, | 
 | 2379 |                 long, (ret == 0) ? True : False); | 
 | 2380 |  | 
 | 2381 |    if (ret != 0) { | 
| sewardj | 789c3c5 | 2008-02-25 12:10:07 +0000 | [diff] [blame] | 2382 |       if (ret != EBUSY) | 
 | 2383 |          DO_PthAPIerror( "pthread_rwlock_tryrdlock", ret ); | 
 | 2384 |    } | 
 | 2385 |  | 
 | 2386 |    if (TRACE_PTH_FNS) { | 
 | 2387 |       fprintf(stderr, " :: rwl_tryrlk -> %d >>\n", ret); | 
 | 2388 |    } | 
 | 2389 |    return ret; | 
 | 2390 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2391 | #if defined(VGO_linux) | 
 | 2392 |    PTH_FUNC(int, pthreadZurwlockZutryrdlock, // pthread_rwlock_tryrdlock | 
 | 2393 |                  pthread_rwlock_t* rwlock) { | 
 | 2394 |       return pthread_rwlock_tryrdlock_WRK(rwlock); | 
 | 2395 |    } | 
 | 2396 | #elif defined(VGO_darwin) | 
 | 2397 |    PTH_FUNC(int, pthreadZurwlockZutryrdlockZa, // pthread_rwlock_tryrdlock* | 
 | 2398 |                  pthread_rwlock_t* rwlock) { | 
 | 2399 |       return pthread_rwlock_tryrdlock_WRK(rwlock); | 
 | 2400 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2401 | #elif defined(VGO_solaris) | 
 | 2402 |    PTH_FUNC(int, rwZutryrdlock, // rw_tryrdlock | 
 | 2403 |                  pthread_rwlock_t *rwlock) { | 
 | 2404 |       return pthread_rwlock_tryrdlock_WRK(rwlock); | 
 | 2405 |    } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2406 | #else | 
 | 2407 | #  error "Unsupported OS" | 
 | 2408 | #endif | 
| sewardj | 789c3c5 | 2008-02-25 12:10:07 +0000 | [diff] [blame] | 2409 |  | 
 | 2410 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2411 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2412 | // glibc:   Unhandled | 
 | 2413 | // darwin:  Unhandled | 
 | 2414 | // Solaris: pthread_rwlock_timedrdlock | 
 | 2415 | // Solaris: pthread_rwlock_reltimedrdlock_np | 
 | 2416 | // | 
 | 2417 | __attribute__((noinline)) __attribute__((unused)) | 
 | 2418 | static int pthread_rwlock_timedrdlock_WRK(pthread_rwlock_t *rwlock, | 
 | 2419 |                                           const struct timespec *timeout) | 
 | 2420 | { | 
 | 2421 |    int    ret; | 
 | 2422 |    OrigFn fn; | 
 | 2423 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2424 |    if (TRACE_PTH_FNS) { | 
 | 2425 |       fprintf(stderr, "<< pthread_rwl_timedrdl %p", rwlock); fflush(stderr); | 
 | 2426 |    } | 
 | 2427 |  | 
 | 2428 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE, | 
 | 2429 |                  pthread_rwlock_t *, rwlock, | 
 | 2430 |                  long, 0/*isW*/, long, 0/*isTryLock*/); | 
 | 2431 |  | 
 | 2432 |    CALL_FN_W_WW(ret, fn, rwlock, timeout); | 
 | 2433 |  | 
 | 2434 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST, | 
 | 2435 |                  pthread_rwlock_t *, rwlock, long, 0/*isW*/, | 
 | 2436 |                  long, (ret == 0) ? True : False); | 
 | 2437 |    if (ret != 0) { | 
 | 2438 |       DO_PthAPIerror("pthread_rwlock_timedrdlock", ret); | 
 | 2439 |    } | 
 | 2440 |  | 
 | 2441 |    if (TRACE_PTH_FNS) { | 
 | 2442 |       fprintf(stderr, " :: rwl_timedrdl -> %d >>\n", ret); | 
 | 2443 |    } | 
 | 2444 |    return ret; | 
 | 2445 | } | 
 | 2446 | #if defined(VGO_linux) | 
 | 2447 | #elif defined(VGO_darwin) | 
 | 2448 | #elif defined(VGO_solaris) | 
 | 2449 |    PTH_FUNC(int, pthreadZurwlockZutimedrdlock, // pthread_rwlock_timedrdlock | 
 | 2450 |                  pthread_rwlock_t *rwlock, | 
 | 2451 |                  const struct timespec *timeout) { | 
 | 2452 |       return pthread_rwlock_timedrdlock_WRK(rwlock, timeout); | 
 | 2453 |    } | 
 | 2454 |    PTH_FUNC(int, pthreadZurwlockZureltimedrdlockZunp, // pthread_rwlock_timedrdlock_np | 
 | 2455 |                  pthread_rwlock_t *rwlock, | 
 | 2456 |                  const struct timespec *timeout) { | 
 | 2457 |       return pthread_rwlock_timedrdlock_WRK(rwlock, timeout); | 
 | 2458 |    } | 
 | 2459 | #else | 
 | 2460 | #  error "Unsupported OS" | 
 | 2461 | #endif | 
 | 2462 |  | 
 | 2463 |  | 
 | 2464 | //----------------------------------------------------------- | 
 | 2465 | // glibc:   Unhandled | 
 | 2466 | // darwin:  Unhandled | 
 | 2467 | // Solaris: pthread_rwlock_timedwrlock | 
 | 2468 | // Solaris: pthread_rwlock_reltimedwrlock_np | 
 | 2469 | // | 
 | 2470 | __attribute__((noinline)) __attribute__((unused)) | 
 | 2471 | static int pthread_rwlock_timedwrlock_WRK(pthread_rwlock_t *rwlock, | 
 | 2472 |                                           const struct timespec *timeout) | 
 | 2473 | { | 
 | 2474 |    int    ret; | 
 | 2475 |    OrigFn fn; | 
 | 2476 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2477 |    if (TRACE_PTH_FNS) { | 
 | 2478 |       fprintf(stderr, "<< pthread_rwl_timedwrl %p", rwlock); fflush(stderr); | 
 | 2479 |    } | 
 | 2480 |  | 
 | 2481 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE, | 
 | 2482 |                  pthread_rwlock_t *, rwlock, | 
 | 2483 |                  long, 1/*isW*/, long, 0/*isTryLock*/); | 
 | 2484 |  | 
 | 2485 |    CALL_FN_W_WW(ret, fn, rwlock, timeout); | 
 | 2486 |  | 
 | 2487 |    DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST, | 
 | 2488 |                  pthread_rwlock_t *, rwlock, long, 1/*isW*/, | 
 | 2489 |                  long, (ret == 0) ? True : False); | 
 | 2490 |    if (ret != 0) { | 
 | 2491 |       DO_PthAPIerror("pthread_rwlock_timedwrlock", ret); | 
 | 2492 |    } | 
 | 2493 |  | 
 | 2494 |    if (TRACE_PTH_FNS) { | 
 | 2495 |       fprintf(stderr, " :: rwl_timedwrl -> %d >>\n", ret); | 
 | 2496 |    } | 
 | 2497 |    return ret; | 
 | 2498 | } | 
 | 2499 | #if defined(VGO_linux) | 
 | 2500 | #elif defined(VGO_darwin) | 
 | 2501 | #elif defined(VGO_solaris) | 
 | 2502 |    PTH_FUNC(int, pthreadZurwlockZutimedwrlock, // pthread_rwlock_timedwrlock | 
 | 2503 |                  pthread_rwlock_t *rwlock, | 
 | 2504 |                  const struct timespec *timeout) { | 
 | 2505 |       return pthread_rwlock_timedwrlock_WRK(rwlock, timeout); | 
 | 2506 |    } | 
 | 2507 |    PTH_FUNC(int, pthreadZurwlockZureltimedwrlockZunp, // pthread_rwlock_timedwrlock_np | 
 | 2508 |                  pthread_rwlock_t *rwlock, | 
 | 2509 |                  const struct timespec *timeout) { | 
 | 2510 |       return pthread_rwlock_timedwrlock_WRK(rwlock, timeout); | 
 | 2511 |    } | 
 | 2512 | #else | 
 | 2513 | #  error "Unsupported OS" | 
 | 2514 | #endif | 
 | 2515 |  | 
 | 2516 |  | 
 | 2517 | //----------------------------------------------------------- | 
 | 2518 | // glibc:   pthread_rwlock_unlock | 
 | 2519 | // darwin:  pthread_rwlock_unlock | 
 | 2520 | // darwin:  pthread_rwlock_unlock$UNIX2003 | 
 | 2521 | // Solaris: rw_unlock (pthread_rwlock_unlock is a weak alias) | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 2522 | __attribute__((noinline)) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2523 | static int pthread_rwlock_unlock_WRK(pthread_rwlock_t* rwlock) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2524 | { | 
 | 2525 |    int    ret; | 
 | 2526 |    OrigFn fn; | 
 | 2527 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2528 |    if (TRACE_PTH_FNS) { | 
 | 2529 |       fprintf(stderr, "<< pthread_rwl_unlk %p", rwlock); fflush(stderr); | 
 | 2530 |    } | 
 | 2531 |  | 
 | 2532 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE, | 
 | 2533 |                pthread_rwlock_t*,rwlock); | 
 | 2534 |  | 
 | 2535 |    CALL_FN_W_W(ret, fn, rwlock); | 
 | 2536 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2537 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST, | 
 | 2538 |                pthread_rwlock_t*,rwlock); | 
 | 2539 |    if (ret != 0) { | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2540 |       DO_PthAPIerror( "pthread_rwlock_unlock", ret ); | 
 | 2541 |    } | 
 | 2542 |  | 
 | 2543 |    if (TRACE_PTH_FNS) { | 
 | 2544 |       fprintf(stderr, " :: rwl_unlk -> %d >>\n", ret); | 
 | 2545 |    } | 
 | 2546 |    return ret; | 
 | 2547 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2548 | #if defined(VGO_linux) | 
 | 2549 |    PTH_FUNC(int, pthreadZurwlockZuunlock, // pthread_rwlock_unlock | 
 | 2550 |                  pthread_rwlock_t* rwlock) { | 
 | 2551 |       return pthread_rwlock_unlock_WRK(rwlock); | 
 | 2552 |    } | 
 | 2553 | #elif defined(VGO_darwin) | 
 | 2554 |    PTH_FUNC(int, pthreadZurwlockZuunlockZa, // pthread_rwlock_unlock* | 
 | 2555 |                  pthread_rwlock_t* rwlock) { | 
 | 2556 |       return pthread_rwlock_unlock_WRK(rwlock); | 
 | 2557 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2558 | #elif defined(VGO_solaris) | 
 | 2559 |    PTH_FUNC(int, rwZuunlock, // rw_unlock | 
 | 2560 |                  pthread_rwlock_t *rwlock) { | 
 | 2561 |       return pthread_rwlock_unlock_WRK(rwlock); | 
 | 2562 |    } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2563 | #else | 
 | 2564 | #  error "Unsupported OS" | 
 | 2565 | #endif | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2566 |  | 
| sewardj | 0c09bf0 | 2011-07-11 22:11:58 +0000 | [diff] [blame] | 2567 | #endif /* defined(HAVE_PTHREAD_RWLOCK_T) */ | 
 | 2568 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2569 |  | 
 | 2570 | /*----------------------------------------------------------------*/ | 
 | 2571 | /*--- POSIX semaphores                                         ---*/ | 
 | 2572 | /*----------------------------------------------------------------*/ | 
 | 2573 |  | 
 | 2574 | #include <semaphore.h> | 
| sewardj | 28a7f7d | 2009-07-26 20:15:37 +0000 | [diff] [blame] | 2575 | #include <fcntl.h>       /* O_CREAT */ | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2576 |  | 
 | 2577 | #define TRACE_SEM_FNS 0 | 
 | 2578 |  | 
 | 2579 | /* Handled:  | 
 | 2580 |      int sem_init(sem_t *sem, int pshared, unsigned value); | 
 | 2581 |      int sem_destroy(sem_t *sem); | 
 | 2582 |      int sem_wait(sem_t *sem); | 
 | 2583 |      int sem_post(sem_t *sem); | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2584 |      sem_t* sem_open(const char *name, int oflag,  | 
 | 2585 |                      ... [mode_t mode, unsigned value]); | 
 | 2586 |         [complete with its idiotic semantics] | 
 | 2587 |      int sem_close(sem_t* sem); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2588 |  | 
 | 2589 |    Unhandled: | 
 | 2590 |      int sem_trywait(sem_t *sem); | 
 | 2591 |      int sem_timedwait(sem_t *restrict sem, | 
 | 2592 |                        const struct timespec *restrict abs_timeout); | 
 | 2593 | */ | 
 | 2594 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2595 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2596 | // glibc:   sem_init@@GLIBC_2.2.5 | 
 | 2597 | // glibc:   sem_init@@GLIBC_2.1 | 
 | 2598 | // glibc:   sem_init@GLIBC_2.0 | 
 | 2599 | // darwin:  sem_init | 
 | 2600 | // Solaris: sema_init (sem_init is built on top of sem_init) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2601 | // | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2602 | #if !defined(VGO_solaris) | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 2603 | __attribute__((noinline)) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2604 | static int sem_init_WRK(sem_t* sem, int pshared, unsigned long value) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2605 | { | 
 | 2606 |    OrigFn fn; | 
 | 2607 |    int    ret; | 
 | 2608 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2609 |  | 
 | 2610 |    if (TRACE_SEM_FNS) { | 
 | 2611 |       fprintf(stderr, "<< sem_init(%p,%d,%lu) ", sem,pshared,value); | 
 | 2612 |       fflush(stderr); | 
 | 2613 |    } | 
 | 2614 |  | 
 | 2615 |    CALL_FN_W_WWW(ret, fn, sem,pshared,value); | 
 | 2616 |  | 
 | 2617 |    if (ret == 0) { | 
| sewardj | 11e352f | 2007-11-30 11:11:02 +0000 | [diff] [blame] | 2618 |       DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST, | 
 | 2619 |                    sem_t*, sem, unsigned long, value); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2620 |    } else { | 
 | 2621 |       DO_PthAPIerror( "sem_init", errno ); | 
 | 2622 |    } | 
 | 2623 |  | 
 | 2624 |    if (TRACE_SEM_FNS) { | 
 | 2625 |       fprintf(stderr, " sem_init -> %d >>\n", ret); | 
 | 2626 |       fflush(stderr); | 
 | 2627 |    } | 
 | 2628 |  | 
 | 2629 |    return ret; | 
 | 2630 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2631 | #if defined(VGO_linux) | 
 | 2632 |    PTH_FUNC(int, semZuinitZAZa, // sem_init@* | 
 | 2633 |                  sem_t* sem, int pshared, unsigned long value) { | 
 | 2634 |       return sem_init_WRK(sem, pshared, value); | 
 | 2635 |    } | 
 | 2636 | #elif defined(VGO_darwin) | 
 | 2637 |    PTH_FUNC(int, semZuinit, // sem_init | 
 | 2638 |                  sem_t* sem, int pshared, unsigned long value) { | 
 | 2639 |       return sem_init_WRK(sem, pshared, value); | 
 | 2640 |    } | 
 | 2641 | #else | 
 | 2642 | #  error "Unsupported OS" | 
 | 2643 | #endif | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2644 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2645 | #else /* VGO_solaris */ | 
 | 2646 | PTH_FUNC(int, semaZuinit, // sema_init | 
 | 2647 |               sema_t *sem, | 
 | 2648 |               unsigned int value, | 
 | 2649 |               int type, | 
 | 2650 |               void *arg) | 
 | 2651 | { | 
 | 2652 |    OrigFn fn; | 
 | 2653 |    int    ret; | 
 | 2654 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2655 |  | 
 | 2656 |    if (TRACE_SEM_FNS) { | 
 | 2657 |       fprintf(stderr, "<< sema_init(%p, %d, %u) ", sem, type, value); | 
 | 2658 |       fflush(stderr); | 
 | 2659 |    } | 
 | 2660 |  | 
 | 2661 |    CALL_FN_W_WWWW(ret, fn, sem, value, type, arg); | 
 | 2662 |  | 
 | 2663 |    if (ret == 0) { | 
 | 2664 |       DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST, | 
 | 2665 |                    sema_t *, sem, Word, value); | 
 | 2666 |    } else { | 
 | 2667 |       DO_PthAPIerror("sema_init", ret); | 
 | 2668 |    } | 
 | 2669 |  | 
 | 2670 |    if (TRACE_SEM_FNS) { | 
 | 2671 |       fprintf(stderr, " sema_init -> %d >>\n", ret); | 
 | 2672 |       fflush(stderr); | 
 | 2673 |    } | 
 | 2674 |  | 
 | 2675 |    return ret; | 
 | 2676 | } | 
 | 2677 | #endif /* VGO_solaris */ | 
 | 2678 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2679 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2680 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2681 | // glibc:   sem_destroy@GLIBC_2.0 | 
 | 2682 | // glibc:   sem_destroy@@GLIBC_2.1 | 
 | 2683 | // glibc:   sem_destroy@@GLIBC_2.2.5 | 
 | 2684 | // darwin:  sem_destroy | 
 | 2685 | // Solaris: sema_destroy (sem_destroy is built on top of sema_destroy) | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 2686 | __attribute__((noinline)) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2687 | static int sem_destroy_WRK(sem_t* sem) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2688 | { | 
 | 2689 |    OrigFn fn; | 
 | 2690 |    int    ret; | 
 | 2691 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2692 |  | 
 | 2693 |    if (TRACE_SEM_FNS) { | 
 | 2694 |       fprintf(stderr, "<< sem_destroy(%p) ", sem); | 
 | 2695 |       fflush(stderr); | 
 | 2696 |    } | 
 | 2697 |  | 
| sewardj | 11e352f | 2007-11-30 11:11:02 +0000 | [diff] [blame] | 2698 |    DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, sem_t*, sem); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2699 |  | 
 | 2700 |    CALL_FN_W_W(ret, fn, sem); | 
 | 2701 |  | 
 | 2702 |    if (ret != 0) { | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2703 |       DO_PthAPIerror( "sem_destroy", SEM_ERROR ); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2704 |    } | 
 | 2705 |  | 
 | 2706 |    if (TRACE_SEM_FNS) { | 
 | 2707 |       fprintf(stderr, " sem_destroy -> %d >>\n", ret); | 
 | 2708 |       fflush(stderr); | 
 | 2709 |    } | 
 | 2710 |  | 
 | 2711 |    return ret; | 
 | 2712 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2713 | #if defined(VGO_linux) | 
 | 2714 |    PTH_FUNC(int, semZudestroyZAZa,  // sem_destroy* | 
 | 2715 |                  sem_t* sem) { | 
 | 2716 |       return sem_destroy_WRK(sem); | 
 | 2717 |    } | 
 | 2718 | #elif defined(VGO_darwin) | 
 | 2719 |    PTH_FUNC(int, semZudestroy,  // sem_destroy | 
 | 2720 |                  sem_t* sem) { | 
 | 2721 |       return sem_destroy_WRK(sem); | 
 | 2722 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2723 | #elif defined(VGO_solaris) | 
 | 2724 |    PTH_FUNC(int, semaZudestroy,  // sema_destroy | 
 | 2725 |                  sem_t *sem) { | 
 | 2726 |       return sem_destroy_WRK(sem); | 
 | 2727 |    } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2728 | #else | 
 | 2729 | #  error "Unsupported OS" | 
 | 2730 | #endif | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2731 |  | 
 | 2732 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2733 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2734 | // glibc:   sem_wait | 
 | 2735 | // glibc:   sem_wait@GLIBC_2.0 | 
 | 2736 | // glibc:   sem_wait@@GLIBC_2.1 | 
 | 2737 | // darwin:  sem_wait | 
 | 2738 | // darwin:  sem_wait$NOCANCEL$UNIX2003 | 
 | 2739 | // darwin:  sem_wait$UNIX2003 | 
 | 2740 | // Solaris: sema_wait (sem_wait is built on top of sema_wait) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2741 | // | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2742 | /* wait: decrement semaphore - acquire lockage */ | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 2743 | __attribute__((noinline)) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2744 | static int sem_wait_WRK(sem_t* sem) | 
 | 2745 | { | 
 | 2746 |    OrigFn fn; | 
 | 2747 |    int    ret; | 
 | 2748 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2749 |  | 
 | 2750 |    if (TRACE_SEM_FNS) { | 
 | 2751 |       fprintf(stderr, "<< sem_wait(%p) ", sem); | 
 | 2752 |       fflush(stderr); | 
 | 2753 |    } | 
 | 2754 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2755 |    DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_WAIT_PRE, sem_t*,sem); | 
 | 2756 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2757 |    CALL_FN_W_W(ret, fn, sem); | 
 | 2758 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2759 |    DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_WAIT_POST, sem_t*,sem, | 
 | 2760 |                 long, (ret == 0) ? True : False); | 
 | 2761 |  | 
 | 2762 |    if (ret != 0) { | 
 | 2763 |       DO_PthAPIerror( "sem_wait", SEM_ERROR ); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2764 |    } | 
 | 2765 |  | 
 | 2766 |    if (TRACE_SEM_FNS) { | 
 | 2767 |       fprintf(stderr, " sem_wait -> %d >>\n", ret); | 
 | 2768 |       fflush(stderr); | 
 | 2769 |    } | 
 | 2770 |  | 
 | 2771 |    return ret; | 
 | 2772 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2773 | #if defined(VGO_linux) | 
 | 2774 |    PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */ | 
 | 2775 |       return sem_wait_WRK(sem); | 
 | 2776 |    } | 
 | 2777 |    PTH_FUNC(int, semZuwaitZAZa, sem_t* sem) { /* sem_wait@* */ | 
 | 2778 |       return sem_wait_WRK(sem); | 
 | 2779 |    } | 
 | 2780 | #elif defined(VGO_darwin) | 
 | 2781 |    PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */ | 
 | 2782 |       return sem_wait_WRK(sem); | 
 | 2783 |    } | 
 | 2784 |    PTH_FUNC(int, semZuwaitZDZa, sem_t* sem) { /* sem_wait$* */ | 
 | 2785 |       return sem_wait_WRK(sem); | 
 | 2786 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2787 | #elif defined(VGO_solaris) | 
 | 2788 |    PTH_FUNC(int, semaZuwait, sem_t *sem) { /* sema_wait */ | 
 | 2789 |       return sem_wait_WRK(sem); | 
 | 2790 |    } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2791 | #else | 
 | 2792 | #  error "Unsupported OS" | 
 | 2793 | #endif | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2794 |  | 
 | 2795 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2796 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2797 | // glibc:   sem_post | 
 | 2798 | // glibc:   sem_post@GLIBC_2.0 | 
 | 2799 | // glibc:   sem_post@@GLIBC_2.1 | 
 | 2800 | // darwin:  sem_post | 
 | 2801 | // Solaris: sema_post (sem_post is built on top of sema_post) | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2802 | // | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2803 | /* post: increment semaphore - release lockage */ | 
| florian | 31014da | 2011-09-26 00:29:44 +0000 | [diff] [blame] | 2804 | __attribute__((noinline)) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2805 | static int sem_post_WRK(sem_t* sem) | 
 | 2806 | { | 
 | 2807 |    OrigFn fn; | 
 | 2808 |    int    ret; | 
 | 2809 |  | 
 | 2810 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2811 |  | 
 | 2812 |    if (TRACE_SEM_FNS) { | 
 | 2813 |       fprintf(stderr, "<< sem_post(%p) ", sem); | 
 | 2814 |       fflush(stderr); | 
 | 2815 |    } | 
 | 2816 |  | 
| sewardj | 11e352f | 2007-11-30 11:11:02 +0000 | [diff] [blame] | 2817 |    DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_POST_PRE, sem_t*,sem); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2818 |  | 
 | 2819 |    CALL_FN_W_W(ret, fn, sem); | 
 | 2820 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2821 |    DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_POST_POST, sem_t*,sem); | 
 | 2822 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2823 |    if (ret != 0) { | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2824 |       DO_PthAPIerror( "sem_post", SEM_ERROR ); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2825 |    } | 
 | 2826 |  | 
 | 2827 |    if (TRACE_SEM_FNS) { | 
 | 2828 |       fprintf(stderr, " sem_post -> %d >>\n", ret); | 
 | 2829 |       fflush(stderr); | 
 | 2830 |    } | 
 | 2831 |  | 
 | 2832 |    return ret; | 
 | 2833 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2834 | #if defined(VGO_linux) | 
 | 2835 |    PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */ | 
 | 2836 |       return sem_post_WRK(sem); | 
 | 2837 |    } | 
 | 2838 |    PTH_FUNC(int, semZupostZAZa, sem_t* sem) { /* sem_post@* */ | 
 | 2839 |       return sem_post_WRK(sem); | 
 | 2840 |    } | 
 | 2841 | #elif defined(VGO_darwin) | 
 | 2842 |    PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */ | 
 | 2843 |       return sem_post_WRK(sem); | 
 | 2844 |    } | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2845 | #elif defined(VGO_solaris) | 
 | 2846 |    PTH_FUNC(int, semaZupost, sem_t *sem) { /* sema_post */ | 
 | 2847 |       return sem_post_WRK(sem); | 
 | 2848 |    } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2849 | #else | 
 | 2850 | #  error "Unsupported OS" | 
 | 2851 | #endif | 
 | 2852 |  | 
 | 2853 |  | 
 | 2854 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2855 | // glibc:   sem_open | 
 | 2856 | // darwin:  sem_open | 
 | 2857 | // Solaris: sem_open | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2858 | // | 
 | 2859 | PTH_FUNC(sem_t*, semZuopen, | 
 | 2860 |                  const char* name, long oflag, | 
 | 2861 |                  long mode, unsigned long value) | 
 | 2862 | { | 
 | 2863 |    /* A copy of sem_init_WRK (more or less).  Is this correct? */ | 
 | 2864 |    OrigFn fn; | 
 | 2865 |    sem_t* ret; | 
 | 2866 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2867 |  | 
 | 2868 |    if (TRACE_SEM_FNS) { | 
 | 2869 |       fprintf(stderr, "<< sem_open(\"%s\",%ld,%lx,%lu) ", | 
 | 2870 |                       name,oflag,mode,value); | 
 | 2871 |       fflush(stderr); | 
 | 2872 |    } | 
 | 2873 |  | 
 | 2874 |    CALL_FN_W_WWWW(ret, fn, name,oflag,mode,value); | 
 | 2875 |  | 
 | 2876 |    if (ret != SEM_FAILED && (oflag & O_CREAT)) { | 
 | 2877 |       DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST, | 
 | 2878 |                    sem_t*, ret, unsigned long, value); | 
 | 2879 |    }  | 
 | 2880 |    if (ret == SEM_FAILED) { | 
 | 2881 |       DO_PthAPIerror( "sem_open", errno ); | 
 | 2882 |    } | 
 | 2883 |  | 
 | 2884 |    if (TRACE_SEM_FNS) { | 
 | 2885 |       fprintf(stderr, " sem_open -> %p >>\n", ret); | 
 | 2886 |       fflush(stderr); | 
 | 2887 |    } | 
 | 2888 |  | 
 | 2889 |    return ret; | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2890 | } | 
 | 2891 |  | 
 | 2892 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2893 | //----------------------------------------------------------- | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 2894 | // glibc:   sem_close | 
 | 2895 | // darwin:  sem_close | 
 | 2896 | // Solaris: sem_close | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 2897 | PTH_FUNC(int, sem_close, sem_t* sem) | 
 | 2898 | { | 
 | 2899 |    OrigFn fn; | 
 | 2900 |    int    ret; | 
 | 2901 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 2902 |  | 
 | 2903 |    if (TRACE_SEM_FNS) { | 
 | 2904 |       fprintf(stderr, "<< sem_close(%p) ", sem); | 
 | 2905 |       fflush(stderr); | 
 | 2906 |    } | 
 | 2907 |  | 
 | 2908 |    DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, sem_t*, sem); | 
 | 2909 |  | 
 | 2910 |    CALL_FN_W_W(ret, fn, sem); | 
 | 2911 |  | 
 | 2912 |    if (ret != 0) { | 
 | 2913 |       DO_PthAPIerror( "sem_close", errno ); | 
 | 2914 |    } | 
 | 2915 |  | 
 | 2916 |    if (TRACE_SEM_FNS) { | 
 | 2917 |       fprintf(stderr, " close -> %d >>\n", ret); | 
 | 2918 |       fflush(stderr); | 
 | 2919 |    } | 
 | 2920 |  | 
 | 2921 |    return ret; | 
 | 2922 | } | 
 | 2923 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2924 |  | 
 | 2925 | /*----------------------------------------------------------------*/ | 
 | 2926 | /*--- Qt 4 threading functions (w/ GNU name mangling)          ---*/ | 
 | 2927 | /*----------------------------------------------------------------*/ | 
 | 2928 |  | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 2929 | /* Handled: | 
 | 2930 |       QMutex::lock() | 
 | 2931 |       QMutex::unlock() | 
 | 2932 |       QMutex::tryLock() | 
 | 2933 |       QMutex::tryLock(int) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2934 |  | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 2935 |       QMutex::QMutex(QMutex::RecursionMode)  _ZN6QMutexC1ENS_13RecursionModeE | 
 | 2936 |       QMutex::QMutex(QMutex::RecursionMode)  _ZN6QMutexC2ENS_13RecursionModeE | 
 | 2937 |       QMutex::~QMutex()                      _ZN6QMutexD1Ev | 
 | 2938 |       QMutex::~QMutex()                      _ZN6QMutexD2Ev | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 2939 |  | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 2940 |    Unhandled: | 
 | 2941 |       QReadWriteLock::lockForRead() | 
 | 2942 |       QReadWriteLock::lockForWrite() | 
 | 2943 |       QReadWriteLock::unlock() | 
 | 2944 |       QReadWriteLock::tryLockForRead(int) | 
 | 2945 |       QReadWriteLock::tryLockForRead() | 
 | 2946 |       QReadWriteLock::tryLockForWrite(int) | 
 | 2947 |       QReadWriteLock::tryLockForWrite() | 
 | 2948 |  | 
 | 2949 |       QWaitCondition::wait(QMutex*, unsigned long) | 
 | 2950 |       QWaitCondition::wakeAll() | 
 | 2951 |       QWaitCondition::wakeOne() | 
 | 2952 |  | 
 | 2953 |       QSemaphore::* | 
 | 2954 | */ | 
 | 2955 | /* More comments, 19 Nov 08, based on assessment of qt-4.5.0TP1, | 
 | 2956 |    at least on Unix: | 
 | 2957 |  | 
 | 2958 |    It's apparently only necessary to intercept QMutex, since that is | 
 | 2959 |    not implemented using pthread_mutex_t; instead Qt4 has its own | 
 | 2960 |    implementation based on atomics (to check the non-contended case) | 
 | 2961 |    and pthread_cond_wait (to wait in the contended case). | 
 | 2962 |  | 
 | 2963 |    QReadWriteLock is built on top of QMutex, counters, and a wait | 
 | 2964 |    queue.  So we don't need to handle it specially once QMutex | 
 | 2965 |    handling is correct -- presumably the dependencies through QMutex | 
 | 2966 |    are sufficient to avoid any false race reports.  On the other hand, | 
 | 2967 |    it is an open question whether too many dependencies are observed | 
 | 2968 |    -- in which case we may miss races (false negatives).  I suspect | 
 | 2969 |    this is likely to be the case, unfortunately. | 
 | 2970 |  | 
 | 2971 |    QWaitCondition is built on pthread_cond_t, pthread_mutex_t, QMutex | 
 | 2972 |    and QReadWriteLock.  Same compositional-correctness justificiation | 
 | 2973 |    and limitations as fro QReadWriteLock. | 
 | 2974 |  | 
 | 2975 |    Ditto QSemaphore (from cursory examination). | 
 | 2976 |  | 
 | 2977 |    Does it matter that only QMutex is handled directly?  Open | 
 | 2978 |    question.  From testing with drd/tests/qt4_* and with KDE4 apps, it | 
 | 2979 |    appears that no false errors are reported; however it is not clear | 
 | 2980 |    if this is causing false negatives. | 
 | 2981 |  | 
 | 2982 |    Another problem with Qt4 is thread exiting.  Threads are created | 
 | 2983 |    with pthread_create (fine); but they detach and simply exit when | 
 | 2984 |    done.  There is no use of pthread_join, and the provided | 
 | 2985 |    wait-for-a-thread-to-exit mechanism (QThread::wait, I believe) | 
 | 2986 |    relies on a system of mutexes and flags.  I suspect this also | 
 | 2987 |    causes too many dependencies to appear.  Consequently H sometimes | 
 | 2988 |    fails to detect races at exit in some very short-lived racy | 
 | 2989 |    programs, because it appears that a thread can exit _and_ have an | 
 | 2990 |    observed dependency edge back to the main thread (presumably) | 
 | 2991 |    before the main thread reaps the child (that is, calls | 
 | 2992 |    QThread::wait). | 
 | 2993 |  | 
 | 2994 |    This theory is supported by the observation that if all threads are | 
 | 2995 |    made to wait at a pthread_barrier_t immediately before they exit, | 
 | 2996 |    then H's detection of races in such programs becomes reliable; | 
 | 2997 |    without the barrier, it is varies from run to run, depending | 
 | 2998 |    (according to investigation) on whether aforementioned | 
 | 2999 |    exit-before-reaping behaviour happens or not. | 
 | 3000 |  | 
 | 3001 |    Finally, why is it necessary to intercept the QMutex constructors | 
 | 3002 |    and destructors?  The constructors are intercepted only as a matter | 
 | 3003 |    of convenience, so H can print accurate "first observed at" | 
 | 3004 |    clauses.  However, it is actually necessary to intercept the | 
 | 3005 |    destructors (as it is with pthread_mutex_destroy) in order that | 
 | 3006 |    locks get removed from LAOG when they are destroyed. | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3007 | */ | 
 | 3008 |  | 
 | 3009 | // soname is libQtCore.so.4 ; match against libQtCore.so* | 
 | 3010 | #define QT4_FUNC(ret_ty, f, args...) \ | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3011 |    ret_ty I_WRAP_SONAME_FNNAME_ZU(libQtCoreZdsoZa,f)(args); \ | 
 | 3012 |    ret_ty I_WRAP_SONAME_FNNAME_ZU(libQtCoreZdsoZa,f)(args) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3013 |  | 
| sewardj | d52defb | 2013-02-07 11:53:36 +0000 | [diff] [blame] | 3014 | // soname is libQt5Core.so.4 ; match against libQt5Core.so* | 
 | 3015 | #define QT5_FUNC(ret_ty, f, args...) \ | 
 | 3016 |    ret_ty I_WRAP_SONAME_FNNAME_ZU(libQt5CoreZdsoZa,f)(args); \ | 
 | 3017 |    ret_ty I_WRAP_SONAME_FNNAME_ZU(libQt5CoreZdsoZa,f)(args) | 
 | 3018 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 3019 | //----------------------------------------------------------- | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3020 | // QMutex::lock() | 
| sewardj | d52defb | 2013-02-07 11:53:36 +0000 | [diff] [blame] | 3021 | __attribute__((noinline)) | 
 | 3022 | static void QMutex_lock_WRK(void* self) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3023 | { | 
 | 3024 |    OrigFn fn; | 
 | 3025 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 3026 |    if (TRACE_QT4_FNS) { | 
 | 3027 |       fprintf(stderr, "<< QMutex::lock %p", self); fflush(stderr); | 
 | 3028 |    } | 
 | 3029 |  | 
 | 3030 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE, | 
 | 3031 |                 void*,self, long,0/*!isTryLock*/); | 
 | 3032 |  | 
 | 3033 |    CALL_FN_v_W(fn, self); | 
 | 3034 |  | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 3035 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, | 
 | 3036 |                 void *, self, long, True); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3037 |  | 
 | 3038 |    if (TRACE_QT4_FNS) { | 
 | 3039 |       fprintf(stderr, " :: Q::lock done >>\n"); | 
 | 3040 |    } | 
 | 3041 | } | 
 | 3042 |  | 
| sewardj | d52defb | 2013-02-07 11:53:36 +0000 | [diff] [blame] | 3043 | QT4_FUNC(void, _ZN6QMutex4lockEv, void* self) { | 
 | 3044 |     QMutex_lock_WRK(self); | 
 | 3045 | } | 
 | 3046 | QT5_FUNC(void, _ZN6QMutex4lockEv, void* self) { | 
 | 3047 |     QMutex_lock_WRK(self); | 
 | 3048 | } | 
 | 3049 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 3050 | //----------------------------------------------------------- | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3051 | // QMutex::unlock() | 
| sewardj | d52defb | 2013-02-07 11:53:36 +0000 | [diff] [blame] | 3052 | __attribute__((noinline)) | 
 | 3053 | static void QMutex_unlock_WRK(void* self) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3054 | { | 
 | 3055 |    OrigFn fn; | 
 | 3056 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 3057 |  | 
 | 3058 |    if (TRACE_QT4_FNS) { | 
 | 3059 |       fprintf(stderr, "<< QMutex::unlock %p", self); fflush(stderr); | 
 | 3060 |    } | 
 | 3061 |  | 
 | 3062 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE, | 
 | 3063 |                void*, self); | 
 | 3064 |  | 
 | 3065 |    CALL_FN_v_W(fn, self); | 
 | 3066 |  | 
 | 3067 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST, | 
 | 3068 |                void*, self); | 
 | 3069 |  | 
 | 3070 |    if (TRACE_QT4_FNS) { | 
 | 3071 |       fprintf(stderr, " Q::unlock done >>\n"); | 
 | 3072 |    } | 
 | 3073 | } | 
 | 3074 |  | 
| sewardj | d52defb | 2013-02-07 11:53:36 +0000 | [diff] [blame] | 3075 | QT4_FUNC(void, _ZN6QMutex6unlockEv, void* self) { | 
 | 3076 |     QMutex_unlock_WRK(self); | 
 | 3077 | } | 
 | 3078 | QT5_FUNC(void, _ZN6QMutex6unlockEv, void* self) { | 
 | 3079 |     QMutex_unlock_WRK(self); | 
 | 3080 | } | 
 | 3081 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 3082 | //----------------------------------------------------------- | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3083 | // bool QMutex::tryLock() | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3084 | // using 'long' to mimic C++ 'bool' | 
| sewardj | d52defb | 2013-02-07 11:53:36 +0000 | [diff] [blame] | 3085 | __attribute__((noinline)) | 
 | 3086 | static long QMutex_tryLock_WRK(void* self) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3087 | { | 
 | 3088 |    OrigFn fn; | 
 | 3089 |    long   ret; | 
 | 3090 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 3091 |    if (TRACE_QT4_FNS) { | 
 | 3092 |       fprintf(stderr, "<< QMutex::tryLock %p", self); fflush(stderr); | 
 | 3093 |    } | 
 | 3094 |  | 
 | 3095 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE, | 
 | 3096 |                 void*,self, long,1/*isTryLock*/); | 
 | 3097 |  | 
 | 3098 |    CALL_FN_W_W(ret, fn, self); | 
 | 3099 |  | 
 | 3100 |    // assumes that only the low 8 bits of the 'bool' are significant | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 3101 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, | 
 | 3102 |                 void *, self, long, (ret & 0xFF) ? True : False); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3103 |  | 
 | 3104 |    if (TRACE_QT4_FNS) { | 
 | 3105 |       fprintf(stderr, " :: Q::tryLock -> %lu >>\n", ret); | 
 | 3106 |    } | 
 | 3107 |     | 
 | 3108 |    return ret; | 
 | 3109 | } | 
 | 3110 |  | 
| sewardj | d52defb | 2013-02-07 11:53:36 +0000 | [diff] [blame] | 3111 | QT4_FUNC(long, _ZN6QMutex7tryLockEv, void* self) { | 
 | 3112 |     return QMutex_tryLock_WRK(self); | 
 | 3113 | } | 
 | 3114 | QT5_FUNC(long, _ZN6QMutex7tryLockEv, void* self) { | 
 | 3115 |     return QMutex_tryLock_WRK(self); | 
 | 3116 | } | 
 | 3117 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 3118 | //----------------------------------------------------------- | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3119 | // bool QMutex::tryLock(int) | 
 | 3120 | // using 'long' to mimic C++ 'bool' | 
| sewardj | d52defb | 2013-02-07 11:53:36 +0000 | [diff] [blame] | 3121 | __attribute__((noinline)) | 
 | 3122 | static long QMutex_tryLock_int_WRK(void* self, long arg2) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3123 | { | 
 | 3124 |    OrigFn fn; | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3125 |    long   ret; | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3126 |    VALGRIND_GET_ORIG_FN(fn); | 
 | 3127 |    if (TRACE_QT4_FNS) { | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3128 |       fprintf(stderr, "<< QMutex::tryLock(int) %p %d", self, (int)arg2); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3129 |       fflush(stderr); | 
 | 3130 |    } | 
 | 3131 |  | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3132 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE, | 
 | 3133 |                 void*,self, long,1/*isTryLock*/); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3134 |  | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3135 |    CALL_FN_W_WW(ret, fn, self,arg2); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3136 |  | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3137 |    // assumes that only the low 8 bits of the 'bool' are significant | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 3138 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST, | 
 | 3139 |                void *, self, long, (ret & 0xFF) ? True : False); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3140 |  | 
 | 3141 |    if (TRACE_QT4_FNS) { | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3142 |       fprintf(stderr, " :: Q::tryLock(int) -> %lu >>\n", ret); | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3143 |    } | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3144 |     | 
 | 3145 |    return ret; | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3146 | } | 
 | 3147 |  | 
| sewardj | d52defb | 2013-02-07 11:53:36 +0000 | [diff] [blame] | 3148 | QT4_FUNC(long, _ZN6QMutex7tryLockEi, void* self, long arg2) { | 
 | 3149 |     return QMutex_tryLock_int_WRK(self, arg2); | 
 | 3150 | } | 
 | 3151 | QT5_FUNC(long, _ZN6QMutex7tryLockEi, void* self, long arg2) { | 
 | 3152 |     return QMutex_tryLock_int_WRK(self, arg2); | 
 | 3153 | } | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3154 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 3155 | //----------------------------------------------------------- | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3156 | // It's not really very clear what the args are here.  But from | 
 | 3157 | // a bit of dataflow analysis of the generated machine code of | 
 | 3158 | // the original function, it appears this takes two args, and | 
 | 3159 | // returns nothing.  Nevertheless preserve return value just in | 
 | 3160 | // case.  A bit of debug printing indicates that the first arg | 
 | 3161 | // is that of the mutex and the second is either zero or one, | 
 | 3162 | // probably being the recursion mode, therefore. | 
 | 3163 | // QMutex::QMutex(QMutex::RecursionMode)  ("C1ENS" variant) | 
| sewardj | d52defb | 2013-02-07 11:53:36 +0000 | [diff] [blame] | 3164 | __attribute__((noinline)) | 
 | 3165 | static void* QMutex_constructor_WRK(void* mutex, long recmode) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3166 | { | 
 | 3167 |    OrigFn fn; | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3168 |    long   ret; | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3169 |    VALGRIND_GET_ORIG_FN(fn); | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3170 |    CALL_FN_W_WW(ret, fn, mutex, recmode); | 
 | 3171 |    //   fprintf(stderr, "QMutex constructor 1: %p <- %p %p\n", ret, arg1, arg2); | 
 | 3172 |    DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST, | 
 | 3173 |                 void*,mutex, long,1/*mbRec*/); | 
 | 3174 |    return (void*)ret; | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3175 | } | 
 | 3176 |  | 
| sewardj | d52defb | 2013-02-07 11:53:36 +0000 | [diff] [blame] | 3177 | QT4_FUNC(void*, _ZN6QMutexC1ENS_13RecursionModeE, void* self, long recmode) { | 
 | 3178 |     return QMutex_constructor_WRK(self, recmode); | 
 | 3179 | } | 
 | 3180 | QT5_FUNC(void*, _ZN6QMutexC1ENS_13RecursionModeE, void* self, long recmode) { | 
 | 3181 |     return QMutex_constructor_WRK(self, recmode); | 
 | 3182 | } | 
 | 3183 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 3184 | //----------------------------------------------------------- | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3185 | // QMutex::~QMutex()  ("D1Ev" variant) | 
| sewardj | d52defb | 2013-02-07 11:53:36 +0000 | [diff] [blame] | 3186 | __attribute__((noinline)) | 
 | 3187 | static void* QMutex_destructor_WRK(void* mutex) | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3188 | { | 
 | 3189 |    OrigFn fn; | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3190 |    long   ret; | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3191 |    VALGRIND_GET_ORIG_FN(fn); | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3192 |    DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE, | 
 | 3193 |                void*,mutex); | 
 | 3194 |    CALL_FN_W_W(ret, fn, mutex); | 
 | 3195 |    return (void*)ret; | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3196 | } | 
 | 3197 |  | 
| sewardj | d52defb | 2013-02-07 11:53:36 +0000 | [diff] [blame] | 3198 | QT4_FUNC(void*, _ZN6QMutexD1Ev, void* self) { | 
 | 3199 |     return QMutex_destructor_WRK(self); | 
 | 3200 | } | 
 | 3201 | QT5_FUNC(void*, _ZN6QMutexD1Ev, void* self) { | 
 | 3202 |     return QMutex_destructor_WRK(self); | 
 | 3203 | } | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3204 |  | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 3205 | //----------------------------------------------------------- | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3206 | // QMutex::QMutex(QMutex::RecursionMode)  ("C2ENS" variant) | 
 | 3207 | QT4_FUNC(void*, _ZN6QMutexC2ENS_13RecursionModeE, | 
 | 3208 |          void* mutex, | 
 | 3209 |          long  recmode) | 
 | 3210 | { | 
 | 3211 |    assert(0); | 
| sewardj | 211c253 | 2011-07-12 06:13:08 +0000 | [diff] [blame] | 3212 |    /*NOTREACHED*/ | 
 | 3213 |    /* Android's gcc behaves like it doesn't know that assert(0) | 
 | 3214 |       never returns.  Hence: */ | 
 | 3215 |    return NULL; | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3216 | } | 
 | 3217 |  | 
| sewardj | d52defb | 2013-02-07 11:53:36 +0000 | [diff] [blame] | 3218 | QT5_FUNC(void*, _ZN6QMutexC2ENS_13RecursionModeE, void* self, long recmode) | 
 | 3219 | { | 
 | 3220 |    assert(0); | 
 | 3221 |    /*NOTREACHED*/ | 
 | 3222 |    return NULL; | 
 | 3223 | } | 
| sewardj | 1c147ff | 2009-07-26 19:52:06 +0000 | [diff] [blame] | 3224 |  | 
 | 3225 | //----------------------------------------------------------- | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3226 | // QMutex::~QMutex()  ("D2Ev" variant) | 
 | 3227 | QT4_FUNC(void*, _ZN6QMutexD2Ev, void* mutex) | 
 | 3228 | { | 
 | 3229 |    assert(0); | 
| sewardj | 211c253 | 2011-07-12 06:13:08 +0000 | [diff] [blame] | 3230 |    /* Android's gcc behaves like it doesn't know that assert(0) | 
 | 3231 |       never returns.  Hence: */ | 
 | 3232 |    return NULL; | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3233 | } | 
 | 3234 |  | 
| sewardj | d52defb | 2013-02-07 11:53:36 +0000 | [diff] [blame] | 3235 | QT5_FUNC(void*, _ZN6QMutexD2Ev, void* self) | 
 | 3236 | { | 
 | 3237 |    assert(0); | 
 | 3238 |    /*NOTREACHED*/ | 
 | 3239 |    return NULL; | 
 | 3240 | } | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3241 |  | 
 | 3242 | // QReadWriteLock is not intercepted directly.  See comments | 
 | 3243 | // above. | 
 | 3244 |  | 
 | 3245 | //// QReadWriteLock::lockForRead() | 
 | 3246 | //// _ZN14QReadWriteLock11lockForReadEv == QReadWriteLock::lockForRead() | 
 | 3247 | //QT4_FUNC(void, ZuZZN14QReadWriteLock11lockForReadEv,  | 
 | 3248 | //               // _ZN14QReadWriteLock11lockForReadEv | 
 | 3249 | //               void* self) | 
 | 3250 | //{ | 
 | 3251 | //   OrigFn fn; | 
 | 3252 | //   VALGRIND_GET_ORIG_FN(fn); | 
 | 3253 | //   if (TRACE_QT4_FNS) { | 
 | 3254 | //      fprintf(stderr, "<< QReadWriteLock::lockForRead %p", self); | 
 | 3255 | //      fflush(stderr); | 
 | 3256 | //   } | 
 | 3257 | // | 
 | 3258 | //   DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE, | 
 | 3259 | //                 void*,self, | 
 | 3260 | //                 long,0/*!isW*/, long,0/*!isTryLock*/); | 
 | 3261 | // | 
 | 3262 | //   CALL_FN_v_W(fn, self); | 
 | 3263 | // | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 3264 | //   DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST, | 
 | 3265 | //                 void*,self, long,0/*!isW*/, long, True); | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3266 | // | 
 | 3267 | //   if (TRACE_QT4_FNS) { | 
 | 3268 | //      fprintf(stderr, " :: Q::lockForRead :: done >>\n"); | 
 | 3269 | //   } | 
 | 3270 | //} | 
 | 3271 | // | 
 | 3272 | //// QReadWriteLock::lockForWrite() | 
 | 3273 | //// _ZN14QReadWriteLock12lockForWriteEv == QReadWriteLock::lockForWrite() | 
 | 3274 | //QT4_FUNC(void, ZuZZN14QReadWriteLock12lockForWriteEv,  | 
 | 3275 | //               // _ZN14QReadWriteLock12lockForWriteEv | 
 | 3276 | //               void* self) | 
 | 3277 | //{ | 
 | 3278 | //   OrigFn fn; | 
 | 3279 | //   VALGRIND_GET_ORIG_FN(fn); | 
 | 3280 | //   if (TRACE_QT4_FNS) { | 
 | 3281 | //      fprintf(stderr, "<< QReadWriteLock::lockForWrite %p", self); | 
 | 3282 | //      fflush(stderr); | 
 | 3283 | //   } | 
 | 3284 | // | 
 | 3285 | //   DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE, | 
 | 3286 | //                 void*,self, | 
 | 3287 | //                 long,1/*isW*/, long,0/*!isTryLock*/); | 
 | 3288 | // | 
 | 3289 | //   CALL_FN_v_W(fn, self); | 
 | 3290 | // | 
| sewardj | 8eb8bab | 2015-07-21 14:44:28 +0000 | [diff] [blame] | 3291 | //   DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST, | 
 | 3292 | //                 void*,self, long,1/*isW*/, long, True); | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3293 | // | 
 | 3294 | //   if (TRACE_QT4_FNS) { | 
 | 3295 | //      fprintf(stderr, " :: Q::lockForWrite :: done >>\n"); | 
 | 3296 | //   } | 
 | 3297 | //} | 
 | 3298 | // | 
 | 3299 | //// QReadWriteLock::unlock() | 
 | 3300 | //// _ZN14QReadWriteLock6unlockEv == QReadWriteLock::unlock() | 
 | 3301 | //QT4_FUNC(void, ZuZZN14QReadWriteLock6unlockEv, | 
 | 3302 | //               // _ZN14QReadWriteLock6unlockEv | 
 | 3303 | //               void* self) | 
 | 3304 | //{ | 
 | 3305 | //   OrigFn fn; | 
 | 3306 | //   VALGRIND_GET_ORIG_FN(fn); | 
 | 3307 | //   if (TRACE_QT4_FNS) { | 
 | 3308 | //      fprintf(stderr, "<< QReadWriteLock::unlock %p", self); | 
 | 3309 | //      fflush(stderr); | 
 | 3310 | //   } | 
 | 3311 | // | 
 | 3312 | //   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE, | 
 | 3313 | //               void*,self); | 
 | 3314 | // | 
 | 3315 | //   CALL_FN_v_W(fn, self); | 
 | 3316 | // | 
 | 3317 | //   DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST, | 
 | 3318 | //               void*,self); | 
 | 3319 | // | 
 | 3320 | //   if (TRACE_QT4_FNS) { | 
 | 3321 | //      fprintf(stderr, " :: Q::unlock :: done >>\n"); | 
 | 3322 | //   } | 
 | 3323 | //} | 
 | 3324 |  | 
 | 3325 |  | 
 | 3326 | /*----------------------------------------------------------------*/ | 
 | 3327 | /*--- Replacements for basic string functions, that don't      ---*/ | 
| sewardj | b80f0c9 | 2008-11-19 16:33:59 +0000 | [diff] [blame] | 3328 | /*--- overrun the input arrays.                                ---*/ | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3329 | /*----------------------------------------------------------------*/ | 
 | 3330 |  | 
| bart | 9c7779b | 2013-11-24 17:48:13 +0000 | [diff] [blame] | 3331 | #include "../shared/vg_replace_strmem.c" | 
| sewardj | 38e0cf9 | 2008-11-19 10:40:56 +0000 | [diff] [blame] | 3332 |  | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3333 | /*--------------------------------------------------------------------*/ | 
| sewardj | 3c94445 | 2011-09-05 20:39:57 +0000 | [diff] [blame] | 3334 | /*--- end                                          hg_intercepts.c ---*/ | 
| sewardj | b411202 | 2007-11-09 22:49:28 +0000 | [diff] [blame] | 3335 | /*--------------------------------------------------------------------*/ |