blob: f5dc2838be54381110c2cc308cc27f1efdff5880 [file] [log] [blame]
sewardjb4112022007-11-09 22:49:28 +00001
2/*--------------------------------------------------------------------*/
3/*--- pthread intercepts for thread checking. ---*/
4/*--- tc_intercepts.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Helgrind, a Valgrind tool for detecting errors
9 in threaded programs.
10
njn9f207462009-03-10 22:02:09 +000011 Copyright (C) 2007-2009 OpenWorks LLP
sewardjb4112022007-11-09 22:49:28 +000012 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
sewardj1c147ff2009-07-26 19:52:06 +000048// 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
sewardjb4112022007-11-09 22:49:28 +000055#include "pub_tool_basics.h"
sewardj38e0cf92008-11-19 10:40:56 +000056#include "pub_tool_redir.h"
sewardjb4112022007-11-09 22:49:28 +000057#include "valgrind.h"
58#include "helgrind.h"
bart870f7452009-12-29 16:56:18 +000059#include "config.h"
sewardjb4112022007-11-09 22:49:28 +000060
61#define TRACE_PTH_FNS 0
62#define TRACE_QT4_FNS 0
63
64
65/*----------------------------------------------------------------*/
66/*--- ---*/
67/*----------------------------------------------------------------*/
68
69#define PTH_FUNC(ret_ty, f, args...) \
njn5f5ef2a2009-05-11 08:01:09 +000070 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args); \
71 ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args)
sewardjb4112022007-11-09 22:49:28 +000072
sewardj406bac82010-03-03 23:03:40 +000073// Do a client request. These are macros rather than a functions so
74// as to avoid having an extra frame in stack traces.
75
76// NB: these duplicate definitions in helgrind.h. But here, we
77// can have better typing (Word etc) and assertions, whereas
78// in helgrind.h we can't. Obviously it's important the two
79// sets of definitions are kept in sync.
80
81// nuke the previous definitions
82#undef DO_CREQ_v_W
83#undef DO_CREQ_v_WW
84#undef DO_CREQ_W_WW
85#undef DO_CREQ_v_WWW
sewardjb4112022007-11-09 22:49:28 +000086
87#define DO_CREQ_v_W(_creqF, _ty1F,_arg1F) \
88 do { \
89 Word _unused_res, _arg1; \
90 assert(sizeof(_ty1F) == sizeof(Word)); \
91 _arg1 = (Word)(_arg1F); \
92 VALGRIND_DO_CLIENT_REQUEST(_unused_res, 0, \
93 (_creqF), \
94 _arg1, 0,0,0,0); \
95 } while (0)
96
97#define DO_CREQ_v_WW(_creqF, _ty1F,_arg1F, _ty2F,_arg2F) \
98 do { \
99 Word _unused_res, _arg1, _arg2; \
100 assert(sizeof(_ty1F) == sizeof(Word)); \
101 assert(sizeof(_ty2F) == sizeof(Word)); \
102 _arg1 = (Word)(_arg1F); \
103 _arg2 = (Word)(_arg2F); \
104 VALGRIND_DO_CLIENT_REQUEST(_unused_res, 0, \
105 (_creqF), \
106 _arg1,_arg2,0,0,0); \
107 } while (0)
108
sewardj1c147ff2009-07-26 19:52:06 +0000109#define DO_CREQ_W_WW(_resF, _creqF, _ty1F,_arg1F, _ty2F,_arg2F) \
sewardjb4112022007-11-09 22:49:28 +0000110 do { \
111 Word _res, _arg1, _arg2; \
112 assert(sizeof(_ty1F) == sizeof(Word)); \
113 assert(sizeof(_ty2F) == sizeof(Word)); \
114 _arg1 = (Word)(_arg1F); \
115 _arg2 = (Word)(_arg2F); \
116 VALGRIND_DO_CLIENT_REQUEST(_res, 2, \
117 (_creqF), \
118 _arg1,_arg2,0,0,0); \
119 _resF = _res; \
120 } while (0)
121
122#define DO_CREQ_v_WWW(_creqF, _ty1F,_arg1F, \
sewardj1c147ff2009-07-26 19:52:06 +0000123 _ty2F,_arg2F, _ty3F, _arg3F) \
sewardjb4112022007-11-09 22:49:28 +0000124 do { \
125 Word _unused_res, _arg1, _arg2, _arg3; \
126 assert(sizeof(_ty1F) == sizeof(Word)); \
127 assert(sizeof(_ty2F) == sizeof(Word)); \
128 assert(sizeof(_ty3F) == sizeof(Word)); \
129 _arg1 = (Word)(_arg1F); \
130 _arg2 = (Word)(_arg2F); \
131 _arg3 = (Word)(_arg3F); \
132 VALGRIND_DO_CLIENT_REQUEST(_unused_res, 0, \
133 (_creqF), \
134 _arg1,_arg2,_arg3,0,0); \
135 } while (0)
136
137
138#define DO_PthAPIerror(_fnnameF, _errF) \
139 do { \
140 char* _fnname = (char*)(_fnnameF); \
sewardj1c147ff2009-07-26 19:52:06 +0000141 long _err = (long)(int)(_errF); \
sewardjb4112022007-11-09 22:49:28 +0000142 char* _errstr = lame_strerror(_err); \
143 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTH_API_ERROR, \
144 char*,_fnname, \
145 long,_err, char*,_errstr); \
146 } while (0)
147
148
149/* Needed for older glibcs (2.3 and older, at least) who don't
150 otherwise "know" about pthread_rwlock_anything or about
151 PTHREAD_MUTEX_RECURSIVE (amongst things). */
152#define _GNU_SOURCE 1
153
154#include <stdio.h>
155#include <assert.h>
156#include <errno.h>
157#include <pthread.h>
158
159
160/* A lame version of strerror which doesn't use the real libc
161 strerror_r, since using the latter just generates endless more
162 threading errors (glibc goes off and does tons of crap w.r.t.
163 locales etc) */
164static char* lame_strerror ( long err )
165{ switch (err) {
166 case EPERM: return "EPERM: Operation not permitted";
167 case ENOENT: return "ENOENT: No such file or directory";
168 case ESRCH: return "ESRCH: No such process";
169 case EINTR: return "EINTR: Interrupted system call";
170 case EBADF: return "EBADF: Bad file number";
171 case EAGAIN: return "EAGAIN: Try again";
172 case ENOMEM: return "ENOMEM: Out of memory";
173 case EACCES: return "EACCES: Permission denied";
174 case EFAULT: return "EFAULT: Bad address";
175 case EEXIST: return "EEXIST: File exists";
176 case EINVAL: return "EINVAL: Invalid argument";
177 case EMFILE: return "EMFILE: Too many open files";
178 case ENOSYS: return "ENOSYS: Function not implemented";
179 case EOVERFLOW: return "EOVERFLOW: Value too large "
180 "for defined data type";
181 case EBUSY: return "EBUSY: Device or resource busy";
182 case ETIMEDOUT: return "ETIMEDOUT: Connection timed out";
183 case EDEADLK: return "EDEADLK: Resource deadlock would occur";
184 case EOPNOTSUPP: return "EOPNOTSUPP: Operation not supported on "
185 "transport endpoint"; /* honest, guv */
186 default: return "tc_intercepts.c: lame_strerror(): "
187 "unhandled case -- please fix me!";
188 }
189}
190
191
192/*----------------------------------------------------------------*/
193/*--- pthread_create, pthread_join, pthread_exit ---*/
194/*----------------------------------------------------------------*/
195
sewardj0d2a2c12007-11-11 05:58:41 +0000196/* Do not rename this function. It contains an unavoidable race and
197 so is mentioned by name in glibc-*helgrind*.supp. */
sewardjb4112022007-11-09 22:49:28 +0000198static void* mythread_wrapper ( void* xargsV )
199{
bart31277bf2008-07-29 17:04:31 +0000200 volatile Word* xargs = (volatile Word*) xargsV;
sewardjb4112022007-11-09 22:49:28 +0000201 void*(*fn)(void*) = (void*(*)(void*))xargs[0];
202 void* arg = (void*)xargs[1];
203 pthread_t me = pthread_self();
204 /* Tell the tool what my pthread_t is. */
205 DO_CREQ_v_W(_VG_USERREQ__HG_SET_MY_PTHREAD_T, pthread_t,me);
206 /* allow the parent to proceed. We can't let it proceed until
207 we're ready because (1) we need to make sure it doesn't exit and
208 hence deallocate xargs[] while we still need it, and (2) we
209 don't want either parent nor child to proceed until the tool has
210 been notified of the child's pthread_t. */
211 xargs[2] = 0;
212 /* Now we can no longer safely use xargs[]. */
213 return (void*) fn( (void*)arg );
214}
215
sewardj1c147ff2009-07-26 19:52:06 +0000216//-----------------------------------------------------------
217// glibc: pthread_create@GLIBC_2.0
218// glibc: pthread_create@@GLIBC_2.1
219// glibc: pthread_create@@GLIBC_2.2.5
220// darwin: pthread_create
221// darwin: pthread_create_suspended_np (trapped)
njnf76d27a2009-05-28 01:53:07 +0000222//
sewardj28a7f7d2009-07-26 20:15:37 +0000223/* ensure this has its own frame, so as to make it more distinguishable
224 in suppressions */
225__attribute__((noinline))
njnf76d27a2009-05-28 01:53:07 +0000226static int pthread_create_WRK(pthread_t *thread, const pthread_attr_t *attr,
227 void *(*start) (void *), void *arg)
sewardjb4112022007-11-09 22:49:28 +0000228{
229 int ret;
230 OrigFn fn;
231 volatile Word xargs[3];
232
233 VALGRIND_GET_ORIG_FN(fn);
234 if (TRACE_PTH_FNS) {
235 fprintf(stderr, "<< pthread_create wrapper"); fflush(stderr);
236 }
237 xargs[0] = (Word)start;
238 xargs[1] = (Word)arg;
239 xargs[2] = 1; /* serves as a spinlock -- sigh */
240
241 CALL_FN_W_WWWW(ret, fn, thread,attr,mythread_wrapper,&xargs[0]);
242
243 if (ret == 0) {
244 /* we have to wait for the child to notify the tool of its
245 pthread_t before continuing */
246 while (xargs[2] != 0) {
sewardjeafad3b2007-11-18 01:16:52 +0000247 /* Do nothing. We need to spin until the child writes to
248 xargs[2]. However, that can lead to starvation in the
249 child and very long delays (eg, tc19_shadowmem on
250 ppc64-linux Fedora Core 6). So yield the cpu if we can,
251 to let the child run at the earliest available
252 opportunity. */
253 sched_yield();
sewardjb4112022007-11-09 22:49:28 +0000254 }
255 } else {
256 DO_PthAPIerror( "pthread_create", ret );
257 }
258
259 if (TRACE_PTH_FNS) {
260 fprintf(stderr, " :: pth_create -> %d >>\n", ret);
261 }
262 return ret;
263}
sewardj1c147ff2009-07-26 19:52:06 +0000264#if defined(VGO_linux)
265 PTH_FUNC(int, pthreadZucreateZAZa, // pthread_create@*
266 pthread_t *thread, const pthread_attr_t *attr,
267 void *(*start) (void *), void *arg) {
268 return pthread_create_WRK(thread, attr, start, arg);
269 }
270#elif defined(VGO_darwin)
271 PTH_FUNC(int, pthreadZucreate, // pthread_create
272 pthread_t *thread, const pthread_attr_t *attr,
273 void *(*start) (void *), void *arg) {
274 return pthread_create_WRK(thread, attr, start, arg);
275 }
276 PTH_FUNC(int, pthreadZucreateZuZa, // pthread_create_*
277 pthread_t *thread, const pthread_attr_t *attr,
278 void *(*start) (void *), void *arg) {
279 // trap anything else
280 assert(0);
281 }
282#else
283# error "Unsupported OS"
284#endif
sewardjb4112022007-11-09 22:49:28 +0000285
sewardj1c147ff2009-07-26 19:52:06 +0000286
287//-----------------------------------------------------------
288// glibc: pthread_join
289// darwin: pthread_join
290// darwin: pthread_join$NOCANCEL$UNIX2003
291// darwin pthread_join$UNIX2003
292static int pthread_join_WRK(pthread_t thread, void** value_pointer)
sewardjb4112022007-11-09 22:49:28 +0000293{
294 int ret;
295 OrigFn fn;
296 VALGRIND_GET_ORIG_FN(fn);
297 if (TRACE_PTH_FNS) {
298 fprintf(stderr, "<< pthread_join wrapper"); fflush(stderr);
299 }
300
301 CALL_FN_W_WW(ret, fn, thread,value_pointer);
302
303 /* At least with NPTL as the thread library, this is safe because
304 it is guaranteed (by NPTL) that the joiner will completely gone
305 before pthread_join (the original) returns. See email below.*/
306 if (ret == 0 /*success*/) {
307 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_JOIN_POST, pthread_t,thread);
308 } else {
309 DO_PthAPIerror( "pthread_join", ret );
310 }
311
312 if (TRACE_PTH_FNS) {
313 fprintf(stderr, " :: pth_join -> %d >>\n", ret);
314 }
315 return ret;
316}
sewardj1c147ff2009-07-26 19:52:06 +0000317#if defined(VGO_linux)
318 PTH_FUNC(int, pthreadZujoin, // pthread_join
319 pthread_t thread, void** value_pointer) {
320 return pthread_join_WRK(thread, value_pointer);
321 }
322#elif defined(VGO_darwin)
323 PTH_FUNC(int, pthreadZujoinZa, // pthread_join*
324 pthread_t thread, void** value_pointer) {
325 return pthread_join_WRK(thread, value_pointer);
326 }
327#else
328# error "Unsupported OS"
329#endif
330
sewardjb4112022007-11-09 22:49:28 +0000331
332/* Behaviour of pthread_join on NPTL:
333
334Me:
335I have a question re the NPTL pthread_join implementation.
336
337 Suppose I am the thread 'stayer'.
338
339 If I call pthread_join(quitter), is it guaranteed that the
340 thread 'quitter' has really exited before pthread_join returns?
341
342 IOW, is it guaranteed that 'quitter' will not execute any further
343 instructions after pthread_join returns?
344
345I believe this is true based on the following analysis of
346glibc-2.5 sources. However am not 100% sure and would appreciate
347confirmation.
348
349 'quitter' will be running start_thread() in nptl/pthread_create.c
350
351 The last action of start_thread() is to exit via
352 __exit_thread_inline(0), which simply does sys_exit
353 (nptl/pthread_create.c:403)
354
355 'stayer' meanwhile is waiting for lll_wait_tid (pd->tid)
356 (call at nptl/pthread_join.c:89)
357
358 As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536,
359 lll_wait_tid will not return until kernel notifies via futex
360 wakeup that 'quitter' has terminated.
361
362 Hence pthread_join cannot return until 'quitter' really has
363 completely disappeared.
364
365Drepper:
366> As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536,
367> lll_wait_tid will not return until kernel notifies via futex
368> wakeup that 'quitter' has terminated.
369That's the key. The kernel resets the TID field after the thread is
370done. No way the joiner can return before the thread is gone.
371*/
372
373
374/*----------------------------------------------------------------*/
375/*--- pthread_mutex_t functions ---*/
376/*----------------------------------------------------------------*/
377
378/* Handled: pthread_mutex_init pthread_mutex_destroy
379 pthread_mutex_lock
380 pthread_mutex_trylock pthread_mutex_timedlock
381 pthread_mutex_unlock
sewardjb4112022007-11-09 22:49:28 +0000382*/
383
sewardj1c147ff2009-07-26 19:52:06 +0000384//-----------------------------------------------------------
385// glibc: pthread_mutex_init
386// darwin: pthread_mutex_init
sewardjb4112022007-11-09 22:49:28 +0000387PTH_FUNC(int, pthreadZumutexZuinit, // pthread_mutex_init
388 pthread_mutex_t *mutex,
389 pthread_mutexattr_t* attr)
390{
391 int ret;
392 long mbRec;
393 OrigFn fn;
394 VALGRIND_GET_ORIG_FN(fn);
395 if (TRACE_PTH_FNS) {
396 fprintf(stderr, "<< pthread_mxinit %p", mutex); fflush(stderr);
397 }
398
399 mbRec = 0;
400 if (attr) {
401 int ty, zzz;
402 zzz = pthread_mutexattr_gettype(attr, &ty);
403 if (zzz == 0 && ty == PTHREAD_MUTEX_RECURSIVE)
404 mbRec = 1;
405 }
406
407 CALL_FN_W_WW(ret, fn, mutex,attr);
408
409 if (ret == 0 /*success*/) {
410 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST,
411 pthread_mutex_t*,mutex, long,mbRec);
412 } else {
413 DO_PthAPIerror( "pthread_mutex_init", ret );
414 }
415
416 if (TRACE_PTH_FNS) {
417 fprintf(stderr, " :: mxinit -> %d >>\n", ret);
418 }
419 return ret;
420}
421
422
sewardj1c147ff2009-07-26 19:52:06 +0000423//-----------------------------------------------------------
424// glibc: pthread_mutex_destroy
425// darwin: pthread_mutex_destroy
sewardjb4112022007-11-09 22:49:28 +0000426PTH_FUNC(int, pthreadZumutexZudestroy, // pthread_mutex_destroy
427 pthread_mutex_t *mutex)
428{
429 int ret;
430 OrigFn fn;
431 VALGRIND_GET_ORIG_FN(fn);
432 if (TRACE_PTH_FNS) {
433 fprintf(stderr, "<< pthread_mxdestroy %p", mutex); fflush(stderr);
434 }
435
436 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE,
437 pthread_mutex_t*,mutex);
438
439 CALL_FN_W_W(ret, fn, mutex);
440
441 if (ret != 0) {
442 DO_PthAPIerror( "pthread_mutex_destroy", ret );
443 }
444
445 if (TRACE_PTH_FNS) {
446 fprintf(stderr, " :: mxdestroy -> %d >>\n", ret);
447 }
448 return ret;
449}
450
451
sewardj1c147ff2009-07-26 19:52:06 +0000452//-----------------------------------------------------------
453// glibc: pthread_mutex_lock
454// darwin: pthread_mutex_lock
sewardjb4112022007-11-09 22:49:28 +0000455PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock
456 pthread_mutex_t *mutex)
457{
458 int ret;
459 OrigFn fn;
460 VALGRIND_GET_ORIG_FN(fn);
461 if (TRACE_PTH_FNS) {
462 fprintf(stderr, "<< pthread_mxlock %p", mutex); fflush(stderr);
463 }
464
465 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
466 pthread_mutex_t*,mutex, long,0/*!isTryLock*/);
467
468 CALL_FN_W_W(ret, fn, mutex);
469
470 /* There's a hole here: libpthread now knows the lock is locked,
471 but the tool doesn't, so some other thread could run and detect
472 that the lock has been acquired by someone (this thread). Does
473 this matter? Not sure, but I don't think so. */
474
475 if (ret == 0 /*success*/) {
476 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
477 pthread_mutex_t*,mutex);
478 } else {
479 DO_PthAPIerror( "pthread_mutex_lock", ret );
480 }
481
482 if (TRACE_PTH_FNS) {
483 fprintf(stderr, " :: mxlock -> %d >>\n", ret);
484 }
485 return ret;
486}
487
488
sewardj1c147ff2009-07-26 19:52:06 +0000489//-----------------------------------------------------------
490// glibc: pthread_mutex_trylock
491// darwin: pthread_mutex_trylock
492//
sewardjb4112022007-11-09 22:49:28 +0000493// pthread_mutex_trylock. The handling needed here is very similar
494// to that for pthread_mutex_lock, except that we need to tell
495// the pre-lock creq that this is a trylock-style operation, and
496// therefore not to complain if the lock is nonrecursive and
497// already locked by this thread -- because then it'll just fail
498// immediately with EBUSY.
499PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock
500 pthread_mutex_t *mutex)
501{
502 int ret;
503 OrigFn fn;
504 VALGRIND_GET_ORIG_FN(fn);
505 if (TRACE_PTH_FNS) {
506 fprintf(stderr, "<< pthread_mxtrylock %p", mutex); fflush(stderr);
507 }
508
509 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
510 pthread_mutex_t*,mutex, long,1/*isTryLock*/);
511
512 CALL_FN_W_W(ret, fn, mutex);
513
514 /* There's a hole here: libpthread now knows the lock is locked,
515 but the tool doesn't, so some other thread could run and detect
516 that the lock has been acquired by someone (this thread). Does
517 this matter? Not sure, but I don't think so. */
518
519 if (ret == 0 /*success*/) {
520 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
521 pthread_mutex_t*,mutex);
522 } else {
523 if (ret != EBUSY)
524 DO_PthAPIerror( "pthread_mutex_trylock", ret );
525 }
526
527 if (TRACE_PTH_FNS) {
528 fprintf(stderr, " :: mxtrylock -> %d >>\n", ret);
529 }
530 return ret;
531}
532
533
sewardj1c147ff2009-07-26 19:52:06 +0000534//-----------------------------------------------------------
535// glibc: pthread_mutex_timedlock
536// darwin: (doesn't appear to exist)
537//
sewardjb4112022007-11-09 22:49:28 +0000538// pthread_mutex_timedlock. Identical logic to pthread_mutex_trylock.
539PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock
sewardj1c147ff2009-07-26 19:52:06 +0000540 pthread_mutex_t *mutex,
sewardjb4112022007-11-09 22:49:28 +0000541 void* timeout)
542{
543 int ret;
544 OrigFn fn;
545 VALGRIND_GET_ORIG_FN(fn);
546 if (TRACE_PTH_FNS) {
547 fprintf(stderr, "<< pthread_mxtimedlock %p %p", mutex, timeout);
548 fflush(stderr);
549 }
550
551 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
552 pthread_mutex_t*,mutex, long,1/*isTryLock-ish*/);
553
554 CALL_FN_W_WW(ret, fn, mutex,timeout);
555
556 /* There's a hole here: libpthread now knows the lock is locked,
557 but the tool doesn't, so some other thread could run and detect
558 that the lock has been acquired by someone (this thread). Does
559 this matter? Not sure, but I don't think so. */
560
561 if (ret == 0 /*success*/) {
562 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
563 pthread_mutex_t*,mutex);
564 } else {
565 if (ret != ETIMEDOUT)
566 DO_PthAPIerror( "pthread_mutex_timedlock", ret );
567 }
568
569 if (TRACE_PTH_FNS) {
570 fprintf(stderr, " :: mxtimedlock -> %d >>\n", ret);
571 }
572 return ret;
573}
574
575
sewardj1c147ff2009-07-26 19:52:06 +0000576//-----------------------------------------------------------
577// glibc: pthread_mutex_unlock
578// darwin: pthread_mutex_unlock
sewardjb4112022007-11-09 22:49:28 +0000579PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock
580 pthread_mutex_t *mutex)
581{
582 int ret;
583 OrigFn fn;
584 VALGRIND_GET_ORIG_FN(fn);
585
586 if (TRACE_PTH_FNS) {
587 fprintf(stderr, "<< pthread_mxunlk %p", mutex); fflush(stderr);
588 }
589
590 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
591 pthread_mutex_t*,mutex);
592
593 CALL_FN_W_W(ret, fn, mutex);
594
595 if (ret == 0 /*success*/) {
596 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST,
597 pthread_mutex_t*,mutex);
598 } else {
599 DO_PthAPIerror( "pthread_mutex_unlock", ret );
600 }
601
602 if (TRACE_PTH_FNS) {
603 fprintf(stderr, " mxunlk -> %d >>\n", ret);
604 }
605 return ret;
606}
607
608
609/*----------------------------------------------------------------*/
610/*--- pthread_cond_t functions ---*/
611/*----------------------------------------------------------------*/
612
613/* Handled: pthread_cond_wait pthread_cond_timedwait
614 pthread_cond_signal pthread_cond_broadcast
sewardjf98e1c02008-10-25 16:22:41 +0000615 pthread_cond_destroy
sewardjb4112022007-11-09 22:49:28 +0000616
sewardjf98e1c02008-10-25 16:22:41 +0000617 Unhandled: pthread_cond_init
618 -- is this important?
sewardjb4112022007-11-09 22:49:28 +0000619*/
620
sewardj1c147ff2009-07-26 19:52:06 +0000621//-----------------------------------------------------------
622// glibc: pthread_cond_wait@GLIBC_2.2.5
623// glibc: pthread_cond_wait@@GLIBC_2.3.2
624// darwin: pthread_cond_wait
625// darwin: pthread_cond_wait$NOCANCEL$UNIX2003
626// darwin: pthread_cond_wait$UNIX2003
627//
628static int pthread_cond_wait_WRK(pthread_cond_t* cond,
629 pthread_mutex_t* mutex)
sewardjb4112022007-11-09 22:49:28 +0000630{
631 int ret;
632 OrigFn fn;
633 unsigned long mutex_is_valid;
634
635 VALGRIND_GET_ORIG_FN(fn);
636
637 if (TRACE_PTH_FNS) {
638 fprintf(stderr, "<< pthread_cond_wait %p %p", cond, mutex);
639 fflush(stderr);
640 }
641
642 /* Tell the tool a cond-wait is about to happen, so it can check
643 for bogus argument values. In return it tells us whether it
644 thinks the mutex is valid or not. */
645 DO_CREQ_W_WW(mutex_is_valid,
646 _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE,
647 pthread_cond_t*,cond, pthread_mutex_t*,mutex);
648 assert(mutex_is_valid == 1 || mutex_is_valid == 0);
649
650 /* Tell the tool we're about to drop the mutex. This reflects the
651 fact that in a cond_wait, we show up holding the mutex, and the
652 call atomically drops the mutex and waits for the cv to be
653 signalled. */
654 if (mutex_is_valid) {
655 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
656 pthread_mutex_t*,mutex);
657 }
658
659 CALL_FN_W_WW(ret, fn, cond,mutex);
660
661 /* these conditionals look stupid, but compare w/ same logic for
662 pthread_cond_timedwait below */
663 if (ret == 0 && mutex_is_valid) {
664 /* and now we have the mutex again */
665 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
666 pthread_mutex_t*,mutex);
667 }
668
669 if (ret == 0 && mutex_is_valid) {
670 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST,
671 pthread_cond_t*,cond, pthread_mutex_t*,mutex);
672 }
673
674 if (ret != 0) {
675 DO_PthAPIerror( "pthread_cond_wait", ret );
676 }
677
678 if (TRACE_PTH_FNS) {
679 fprintf(stderr, " cowait -> %d >>\n", ret);
680 }
681
682 return ret;
683}
sewardj1c147ff2009-07-26 19:52:06 +0000684#if defined(VGO_linux)
685 PTH_FUNC(int, pthreadZucondZuwaitZAZa, // pthread_cond_wait@*
686 pthread_cond_t* cond, pthread_mutex_t* mutex) {
687 return pthread_cond_wait_WRK(cond, mutex);
688 }
689#elif defined(VGO_darwin)
690 PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait*
691 pthread_cond_t* cond, pthread_mutex_t* mutex) {
692 return pthread_cond_wait_WRK(cond, mutex);
693 }
694#else
695# error "Unsupported OS"
696#endif
sewardjb4112022007-11-09 22:49:28 +0000697
698
sewardj1c147ff2009-07-26 19:52:06 +0000699//-----------------------------------------------------------
700// glibc: pthread_cond_timedwait@@GLIBC_2.3.2
701// glibc: pthread_cond_timedwait@GLIBC_2.2.5
702// glibc: pthread_cond_timedwait@GLIBC_2.0
703// darwin: pthread_cond_timedwait
704// darwin: pthread_cond_timedwait$NOCANCEL$UNIX2003
705// darwin: pthread_cond_timedwait$UNIX2003
706// darwin: pthread_cond_timedwait_relative_np (trapped)
707//
708static int pthread_cond_timedwait_WRK(pthread_cond_t* cond,
709 pthread_mutex_t* mutex,
710 struct timespec* abstime)
sewardjb4112022007-11-09 22:49:28 +0000711{
712 int ret;
713 OrigFn fn;
714 unsigned long mutex_is_valid;
715 VALGRIND_GET_ORIG_FN(fn);
716
717 if (TRACE_PTH_FNS) {
718 fprintf(stderr, "<< pthread_cond_timedwait %p %p %p",
719 cond, mutex, abstime);
720 fflush(stderr);
721 }
722
723 /* Tell the tool a cond-wait is about to happen, so it can check
724 for bogus argument values. In return it tells us whether it
725 thinks the mutex is valid or not. */
726 DO_CREQ_W_WW(mutex_is_valid,
727 _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE,
728 pthread_cond_t*,cond, pthread_mutex_t*,mutex);
729 assert(mutex_is_valid == 1 || mutex_is_valid == 0);
730
731 /* Tell the tool we're about to drop the mutex. This reflects the
732 fact that in a cond_wait, we show up holding the mutex, and the
733 call atomically drops the mutex and waits for the cv to be
734 signalled. */
735 if (mutex_is_valid) {
736 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
737 pthread_mutex_t*,mutex);
738 }
739
740 CALL_FN_W_WWW(ret, fn, cond,mutex,abstime);
741
742 if ((ret == 0 || ret == ETIMEDOUT) && mutex_is_valid) {
743 /* and now we have the mutex again */
744 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
745 pthread_mutex_t*,mutex);
746 }
747
748 if (ret == 0 && mutex_is_valid) {
749 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST,
750 pthread_cond_t*,cond, pthread_mutex_t*,mutex);
751 }
752
753 if (ret != 0 && ret != ETIMEDOUT) {
754 DO_PthAPIerror( "pthread_cond_timedwait", ret );
755 }
756
757 if (TRACE_PTH_FNS) {
758 fprintf(stderr, " cotimedwait -> %d >>\n", ret);
759 }
760
761 return ret;
762}
sewardj1c147ff2009-07-26 19:52:06 +0000763#if defined(VGO_linux)
764 PTH_FUNC(int, pthreadZucondZutimedwaitZAZa, // pthread_cond_timedwait@*
765 pthread_cond_t* cond, pthread_mutex_t* mutex,
766 struct timespec* abstime) {
767 return pthread_cond_timedwait_WRK(cond, mutex, abstime);
768 }
769#elif defined(VGO_darwin)
770 PTH_FUNC(int, pthreadZucondZutimedwait, // pthread_cond_timedwait
771 pthread_cond_t* cond, pthread_mutex_t* mutex,
772 struct timespec* abstime) {
773 return pthread_cond_timedwait_WRK(cond, mutex, abstime);
774 }
775 PTH_FUNC(int, pthreadZucondZutimedwaitZDZa, // pthread_cond_timedwait$*
776 pthread_cond_t* cond, pthread_mutex_t* mutex,
777 struct timespec* abstime) {
778 return pthread_cond_timedwait_WRK(cond, mutex, abstime);
779 }
780 PTH_FUNC(int, pthreadZucondZutimedwaitZuZa, // pthread_cond_timedwait_*
781 pthread_cond_t* cond, pthread_mutex_t* mutex,
782 struct timespec* abstime) {
783 assert(0);
784 }
785#else
786# error "Unsupported OS"
787#endif
sewardjb4112022007-11-09 22:49:28 +0000788
789
sewardj1c147ff2009-07-26 19:52:06 +0000790//-----------------------------------------------------------
791// glibc: pthread_cond_signal@GLIBC_2.0
792// glibc: pthread_cond_signal@GLIBC_2.2.5
793// glibc: pthread_cond_signal@@GLIBC_2.3.2
794// darwin: pthread_cond_signal
795// darwin: pthread_cond_signal_thread_np (don't intercept this)
796//
797static int pthread_cond_signal_WRK(pthread_cond_t* cond)
sewardjb4112022007-11-09 22:49:28 +0000798{
799 int ret;
800 OrigFn fn;
801 VALGRIND_GET_ORIG_FN(fn);
802
803 if (TRACE_PTH_FNS) {
804 fprintf(stderr, "<< pthread_cond_signal %p", cond);
805 fflush(stderr);
806 }
807
808 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_SIGNAL_PRE,
809 pthread_cond_t*,cond);
810
811 CALL_FN_W_W(ret, fn, cond);
812
813 if (ret != 0) {
814 DO_PthAPIerror( "pthread_cond_signal", ret );
815 }
816
817 if (TRACE_PTH_FNS) {
818 fprintf(stderr, " cosig -> %d >>\n", ret);
819 }
820
821 return ret;
822}
sewardj1c147ff2009-07-26 19:52:06 +0000823#if defined(VGO_linux)
824 PTH_FUNC(int, pthreadZucondZusignalZAZa, // pthread_cond_signal@*
825 pthread_cond_t* cond) {
826 return pthread_cond_signal_WRK(cond);
827 }
828#elif defined(VGO_darwin)
829 PTH_FUNC(int, pthreadZucondZusignal, // pthread_cond_signal
830 pthread_cond_t* cond) {
831 return pthread_cond_signal_WRK(cond);
832 }
833#else
834# error "Unsupported OS"
835#endif
sewardjb4112022007-11-09 22:49:28 +0000836
837
sewardj1c147ff2009-07-26 19:52:06 +0000838//-----------------------------------------------------------
839// glibc: pthread_cond_broadcast@GLIBC_2.0
840// glibc: pthread_cond_broadcast@GLIBC_2.2.5
841// glibc: pthread_cond_broadcast@@GLIBC_2.3.2
842// darwin: pthread_cond_broadcast
843//
sewardjb4112022007-11-09 22:49:28 +0000844// Note, this is pretty much identical, from a dependency-graph
845// point of view, with cond_signal, so the code is duplicated.
846// Maybe it should be commoned up.
sewardj1c147ff2009-07-26 19:52:06 +0000847//
848static int pthread_cond_broadcast_WRK(pthread_cond_t* cond)
sewardjb4112022007-11-09 22:49:28 +0000849{
850 int ret;
851 OrigFn fn;
852 VALGRIND_GET_ORIG_FN(fn);
853
854 if (TRACE_PTH_FNS) {
sewardj1c147ff2009-07-26 19:52:06 +0000855 fprintf(stderr, "<< pthread_cond_broadcast %p", cond);
sewardjb4112022007-11-09 22:49:28 +0000856 fflush(stderr);
857 }
858
859 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_BROADCAST_PRE,
860 pthread_cond_t*,cond);
861
862 CALL_FN_W_W(ret, fn, cond);
863
864 if (ret != 0) {
865 DO_PthAPIerror( "pthread_cond_broadcast", ret );
866 }
867
868 if (TRACE_PTH_FNS) {
869 fprintf(stderr, " cobro -> %d >>\n", ret);
870 }
871
872 return ret;
873}
sewardj1c147ff2009-07-26 19:52:06 +0000874#if defined(VGO_linux)
875 PTH_FUNC(int, pthreadZucondZubroadcastZAZa, // pthread_cond_broadcast@*
876 pthread_cond_t* cond) {
877 return pthread_cond_broadcast_WRK(cond);
878 }
879#elif defined(VGO_darwin)
880 PTH_FUNC(int, pthreadZucondZubroadcast, // pthread_cond_broadcast
881 pthread_cond_t* cond) {
882 return pthread_cond_broadcast_WRK(cond);
883 }
884#else
885# error "Unsupported OS"
886#endif
sewardjb4112022007-11-09 22:49:28 +0000887
888
sewardj1c147ff2009-07-26 19:52:06 +0000889//-----------------------------------------------------------
890// glibc: pthread_cond_destroy@@GLIBC_2.3.2
891// glibc: pthread_cond_destroy@GLIBC_2.2.5
892// glibc: pthread_cond_destroy@GLIBC_2.0
893// darwin: pthread_cond_destroy
894//
895static int pthread_cond_destroy_WRK(pthread_cond_t* cond)
sewardjf98e1c02008-10-25 16:22:41 +0000896{
897 int ret;
898 OrigFn fn;
899
900 VALGRIND_GET_ORIG_FN(fn);
901
902 if (TRACE_PTH_FNS) {
903 fprintf(stderr, "<< pthread_cond_destroy %p", cond);
904 fflush(stderr);
905 }
906
907 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_DESTROY_PRE,
908 pthread_cond_t*,cond);
909
910 CALL_FN_W_W(ret, fn, cond);
911
912 if (ret != 0) {
913 DO_PthAPIerror( "pthread_cond_destroy", ret );
914 }
915
916 if (TRACE_PTH_FNS) {
917 fprintf(stderr, " codestr -> %d >>\n", ret);
918 }
919
920 return ret;
921}
sewardj1c147ff2009-07-26 19:52:06 +0000922#if defined(VGO_linux)
923 PTH_FUNC(int, pthreadZucondZudestroyZAZa, // pthread_cond_destroy@*
924 pthread_cond_t* cond) {
925 return pthread_cond_destroy_WRK(cond);
926 }
927#elif defined(VGO_darwin)
928 PTH_FUNC(int, pthreadZucondZudestroy, // pthread_cond_destroy
929 pthread_cond_t* cond) {
930 return pthread_cond_destroy_WRK(cond);
931 }
932#else
933# error "Unsupported OS"
934#endif
sewardjf98e1c02008-10-25 16:22:41 +0000935
936
937/*----------------------------------------------------------------*/
938/*--- pthread_barrier_t functions ---*/
939/*----------------------------------------------------------------*/
940
njnf76d27a2009-05-28 01:53:07 +0000941#if defined(HAVE_PTHREAD_BARRIER_INIT)
942
sewardj9f569b72008-11-13 13:33:09 +0000943/* Handled: pthread_barrier_init
944 pthread_barrier_wait
945 pthread_barrier_destroy
946
947 Unhandled: pthread_barrierattr_destroy
948 pthread_barrierattr_getpshared
949 pthread_barrierattr_init
950 pthread_barrierattr_setpshared
951 -- are these important?
952*/
953
sewardj1c147ff2009-07-26 19:52:06 +0000954//-----------------------------------------------------------
955// glibc: pthread_barrier_init
956// darwin: (doesn't appear to exist)
sewardj9f569b72008-11-13 13:33:09 +0000957PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init
958 pthread_barrier_t* bar,
959 pthread_barrierattr_t* attr, unsigned long count)
sewardjf98e1c02008-10-25 16:22:41 +0000960{
961 int ret;
962 OrigFn fn;
963 VALGRIND_GET_ORIG_FN(fn);
964
965 if (TRACE_PTH_FNS) {
sewardj9f569b72008-11-13 13:33:09 +0000966 fprintf(stderr, "<< pthread_barrier_init %p %p %lu",
967 bar, attr, count);
sewardjf98e1c02008-10-25 16:22:41 +0000968 fflush(stderr);
969 }
970
sewardj406bac82010-03-03 23:03:40 +0000971 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_BARRIER_INIT_PRE,
972 pthread_barrier_t*, bar,
973 unsigned long, count,
974 unsigned long, 0/*!resizable*/);
sewardjf98e1c02008-10-25 16:22:41 +0000975
sewardj9f569b72008-11-13 13:33:09 +0000976 CALL_FN_W_WWW(ret, fn, bar,attr,count);
sewardjf98e1c02008-10-25 16:22:41 +0000977
sewardj9f569b72008-11-13 13:33:09 +0000978 if (ret != 0) {
979 DO_PthAPIerror( "pthread_barrier_init", ret );
980 }
981
982 if (TRACE_PTH_FNS) {
983 fprintf(stderr, " pthread_barrier_init -> %d >>\n", ret);
984 }
985
986 return ret;
987}
988
989
sewardj1c147ff2009-07-26 19:52:06 +0000990//-----------------------------------------------------------
991// glibc: pthread_barrier_wait
992// darwin: (doesn't appear to exist)
sewardj9f569b72008-11-13 13:33:09 +0000993PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait
994 pthread_barrier_t* bar)
995{
996 int ret;
997 OrigFn fn;
998 VALGRIND_GET_ORIG_FN(fn);
999
1000 if (TRACE_PTH_FNS) {
1001 fprintf(stderr, "<< pthread_barrier_wait %p", bar);
1002 fflush(stderr);
1003 }
1004
1005 /* That this works correctly, and doesn't screw up when a thread
1006 leaving the barrier races round to the front and re-enters while
1007 other threads are still leaving it, is quite subtle. See
1008 comments in the handler for PTHREAD_BARRIER_WAIT_PRE in
1009 hg_main.c. */
1010 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_WAIT_PRE,
1011 pthread_barrier_t*,bar);
1012
1013 CALL_FN_W_W(ret, fn, bar);
1014
1015 if (ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
1016 DO_PthAPIerror( "pthread_barrier_wait", ret );
1017 }
sewardjf98e1c02008-10-25 16:22:41 +00001018
1019 if (TRACE_PTH_FNS) {
1020 fprintf(stderr, " pthread_barrier_wait -> %d >>\n", ret);
1021 }
1022
1023 return ret;
1024}
1025
1026
sewardj1c147ff2009-07-26 19:52:06 +00001027//-----------------------------------------------------------
1028// glibc: pthread_barrier_destroy
1029// darwin: (doesn't appear to exist)
sewardj9f569b72008-11-13 13:33:09 +00001030PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy
1031 pthread_barrier_t* bar)
1032{
1033 int ret;
1034 OrigFn fn;
1035 VALGRIND_GET_ORIG_FN(fn);
1036
1037 if (TRACE_PTH_FNS) {
1038 fprintf(stderr, "<< pthread_barrier_destroy %p", bar);
1039 fflush(stderr);
1040 }
1041
1042 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_DESTROY_PRE,
1043 pthread_barrier_t*,bar);
1044
1045 CALL_FN_W_W(ret, fn, bar);
1046
1047 if (ret != 0) {
1048 DO_PthAPIerror( "pthread_barrier_destroy", ret );
1049 }
1050
1051 if (TRACE_PTH_FNS) {
1052 fprintf(stderr, " pthread_barrier_destroy -> %d >>\n", ret);
1053 }
1054
1055 return ret;
1056}
sewardjf98e1c02008-10-25 16:22:41 +00001057
njnf76d27a2009-05-28 01:53:07 +00001058#endif // defined(HAVE_PTHREAD_BARRIER_INIT)
1059
sewardj5a644da2009-08-11 10:35:58 +00001060
1061/*----------------------------------------------------------------*/
1062/*--- pthread_spinlock_t functions ---*/
1063/*----------------------------------------------------------------*/
1064
1065#if defined(HAVE_PTHREAD_SPIN_LOCK)
1066
1067/* Handled: pthread_spin_init pthread_spin_destroy
1068 pthread_spin_lock pthread_spin_trylock
1069 pthread_spin_unlock
1070
1071 Unhandled:
1072*/
1073
1074/* This is a nasty kludge, in that glibc "knows" that initialising a
1075 spin lock unlocks it, and pthread_spin_{init,unlock} are names for
1076 the same function. Hence we have to have a wrapper which does both
1077 things, without knowing which the user intended to happen. */
1078
1079//-----------------------------------------------------------
1080// glibc: pthread_spin_init
1081// glibc: pthread_spin_unlock
1082// darwin: (doesn't appear to exist)
1083static int pthread_spin_init_or_unlock_WRK(pthread_spinlock_t* lock,
1084 int pshared) {
1085 int ret;
1086 OrigFn fn;
1087 VALGRIND_GET_ORIG_FN(fn);
1088 if (TRACE_PTH_FNS) {
1089 fprintf(stderr, "<< pthread_spin_iORu %p", lock); fflush(stderr);
1090 }
1091
1092 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE,
1093 pthread_spinlock_t*, lock);
1094
1095 CALL_FN_W_WW(ret, fn, lock,pshared);
1096
1097 if (ret == 0 /*success*/) {
1098 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST,
1099 pthread_spinlock_t*,lock);
1100 } else {
1101 DO_PthAPIerror( "pthread_spinlock_{init,unlock}", ret );
1102 }
1103
1104 if (TRACE_PTH_FNS) {
1105 fprintf(stderr, " :: spiniORu -> %d >>\n", ret);
1106 }
1107 return ret;
1108}
1109#if defined(VGO_linux)
1110 PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init
1111 pthread_spinlock_t* lock, int pshared) {
1112 return pthread_spin_init_or_unlock_WRK(lock, pshared);
1113 }
1114 PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock
1115 pthread_spinlock_t* lock) {
1116 /* this is never actually called */
1117 return pthread_spin_init_or_unlock_WRK(lock, 0/*pshared*/);
1118 }
1119#elif defined(VGO_darwin)
1120#else
1121# error "Unsupported OS"
1122#endif
1123
1124
1125//-----------------------------------------------------------
1126// glibc: pthread_spin_destroy
1127// darwin: (doesn't appear to exist)
1128#if defined(VGO_linux)
1129
1130PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy
1131 pthread_spinlock_t* lock)
1132{
1133 int ret;
1134 OrigFn fn;
1135 VALGRIND_GET_ORIG_FN(fn);
1136 if (TRACE_PTH_FNS) {
1137 fprintf(stderr, "<< pthread_spin_destroy %p", lock);
1138 fflush(stderr);
1139 }
1140
1141 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_DESTROY_PRE,
1142 pthread_spinlock_t*,lock);
1143
1144 CALL_FN_W_W(ret, fn, lock);
1145
1146 if (ret != 0) {
1147 DO_PthAPIerror( "pthread_spin_destroy", ret );
1148 }
1149
1150 if (TRACE_PTH_FNS) {
1151 fprintf(stderr, " :: spindestroy -> %d >>\n", ret);
1152 }
1153 return ret;
1154}
1155
1156#elif defined(VGO_darwin)
1157#else
1158# error "Unsupported OS"
1159#endif
1160
1161
1162//-----------------------------------------------------------
1163// glibc: pthread_spin_lock
1164// darwin: (doesn't appear to exist)
1165#if defined(VGO_linux)
1166
1167PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock
1168 pthread_spinlock_t* lock)
1169{
1170 int ret;
1171 OrigFn fn;
1172 VALGRIND_GET_ORIG_FN(fn);
1173 if (TRACE_PTH_FNS) {
1174 fprintf(stderr, "<< pthread_spinlock %p", lock);
1175 fflush(stderr);
1176 }
1177
1178 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE,
1179 pthread_spinlock_t*,lock, long,0/*!isTryLock*/);
1180
1181 CALL_FN_W_W(ret, fn, lock);
1182
1183 /* There's a hole here: libpthread now knows the lock is locked,
1184 but the tool doesn't, so some other thread could run and detect
1185 that the lock has been acquired by someone (this thread). Does
1186 this matter? Not sure, but I don't think so. */
1187
1188 if (ret == 0 /*success*/) {
1189 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST,
1190 pthread_spinlock_t*,lock);
1191 } else {
1192 DO_PthAPIerror( "pthread_spin_lock", ret );
1193 }
1194
1195 if (TRACE_PTH_FNS) {
1196 fprintf(stderr, " :: spinlock -> %d >>\n", ret);
1197 }
1198 return ret;
1199}
1200
1201#elif defined(VGO_darwin)
1202#else
1203# error "Unsupported OS"
1204#endif
1205
1206
1207//-----------------------------------------------------------
1208// glibc: pthread_spin_trylock
1209// darwin: (doesn't appear to exist)
1210#if defined(VGO_linux)
1211
1212PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock
1213 pthread_spinlock_t* lock)
1214{
1215 int ret;
1216 OrigFn fn;
1217 VALGRIND_GET_ORIG_FN(fn);
1218 if (TRACE_PTH_FNS) {
1219 fprintf(stderr, "<< pthread_spin_trylock %p", lock);
1220 fflush(stderr);
1221 }
1222
1223 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE,
1224 pthread_spinlock_t*,lock, long,1/*isTryLock*/);
1225
1226 CALL_FN_W_W(ret, fn, lock);
1227
1228 /* There's a hole here: libpthread now knows the lock is locked,
1229 but the tool doesn't, so some other thread could run and detect
1230 that the lock has been acquired by someone (this thread). Does
1231 this matter? Not sure, but I don't think so. */
1232
1233 if (ret == 0 /*success*/) {
1234 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST,
1235 pthread_spinlock_t*,lock);
1236 } else {
1237 if (ret != EBUSY)
1238 DO_PthAPIerror( "pthread_spin_trylock", ret );
1239 }
1240
1241 if (TRACE_PTH_FNS) {
1242 fprintf(stderr, " :: spin_trylock -> %d >>\n", ret);
1243 }
1244 return ret;
1245}
1246
1247#elif defined(VGO_darwin)
1248#else
1249# error "Unsupported OS"
1250#endif
1251
1252#endif // defined(HAVE_PTHREAD_SPIN_LOCK)
1253
1254
sewardjb4112022007-11-09 22:49:28 +00001255/*----------------------------------------------------------------*/
1256/*--- pthread_rwlock_t functions ---*/
1257/*----------------------------------------------------------------*/
1258
1259/* Handled: pthread_rwlock_init pthread_rwlock_destroy
1260 pthread_rwlock_rdlock
1261 pthread_rwlock_wrlock
1262 pthread_rwlock_unlock
1263
1264 Unhandled: pthread_rwlock_timedrdlock
1265 pthread_rwlock_tryrdlock
1266
1267 pthread_rwlock_timedwrlock
1268 pthread_rwlock_trywrlock
1269*/
1270
sewardj1c147ff2009-07-26 19:52:06 +00001271//-----------------------------------------------------------
1272// glibc: pthread_rwlock_init
1273// darwin: pthread_rwlock_init
1274// darwin: pthread_rwlock_init$UNIX2003
1275static int pthread_rwlock_init_WRK(pthread_rwlock_t *rwl,
1276 pthread_rwlockattr_t* attr)
sewardjb4112022007-11-09 22:49:28 +00001277{
1278 int ret;
1279 OrigFn fn;
1280 VALGRIND_GET_ORIG_FN(fn);
1281 if (TRACE_PTH_FNS) {
1282 fprintf(stderr, "<< pthread_rwl_init %p", rwl); fflush(stderr);
1283 }
1284
1285 CALL_FN_W_WW(ret, fn, rwl,attr);
1286
1287 if (ret == 0 /*success*/) {
1288 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST,
1289 pthread_rwlock_t*,rwl);
1290 } else {
1291 DO_PthAPIerror( "pthread_rwlock_init", ret );
1292 }
1293
1294 if (TRACE_PTH_FNS) {
1295 fprintf(stderr, " :: rwl_init -> %d >>\n", ret);
1296 }
1297 return ret;
1298}
sewardj1c147ff2009-07-26 19:52:06 +00001299#if defined(VGO_linux)
1300 PTH_FUNC(int, pthreadZurwlockZuinit, // pthread_rwlock_init
1301 pthread_rwlock_t *rwl,
1302 pthread_rwlockattr_t* attr) {
1303 return pthread_rwlock_init_WRK(rwl, attr);
1304 }
1305#elif defined(VGO_darwin)
1306 PTH_FUNC(int, pthreadZurwlockZuinitZa, // pthread_rwlock_init*
1307 pthread_rwlock_t *rwl,
1308 pthread_rwlockattr_t* attr) {
1309 return pthread_rwlock_init_WRK(rwl, attr);
1310 }
1311#else
1312# error "Unsupported OS"
1313#endif
sewardjb4112022007-11-09 22:49:28 +00001314
1315
sewardj1c147ff2009-07-26 19:52:06 +00001316//-----------------------------------------------------------
1317// glibc: pthread_rwlock_destroy
1318// darwin: pthread_rwlock_destroy
1319// darwin: pthread_rwlock_destroy$UNIX2003
1320//
1321static int pthread_rwlock_destroy_WRK(pthread_rwlock_t* rwl)
sewardjb4112022007-11-09 22:49:28 +00001322{
1323 int ret;
1324 OrigFn fn;
1325 VALGRIND_GET_ORIG_FN(fn);
1326 if (TRACE_PTH_FNS) {
1327 fprintf(stderr, "<< pthread_rwl_destroy %p", rwl); fflush(stderr);
1328 }
1329
1330 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE,
1331 pthread_rwlock_t*,rwl);
1332
1333 CALL_FN_W_W(ret, fn, rwl);
1334
1335 if (ret != 0) {
1336 DO_PthAPIerror( "pthread_rwlock_destroy", ret );
1337 }
1338
1339 if (TRACE_PTH_FNS) {
1340 fprintf(stderr, " :: rwl_destroy -> %d >>\n", ret);
1341 }
1342 return ret;
1343}
sewardj1c147ff2009-07-26 19:52:06 +00001344#if defined(VGO_linux)
1345 PTH_FUNC(int, pthreadZurwlockZudestroy, // pthread_rwlock_destroy
1346 pthread_rwlock_t *rwl) {
1347 return pthread_rwlock_destroy_WRK(rwl);
1348 }
1349#elif defined(VGO_darwin)
1350 PTH_FUNC(int, pthreadZurwlockZudestroyZa, // pthread_rwlock_destroy*
1351 pthread_rwlock_t *rwl) {
1352 return pthread_rwlock_destroy_WRK(rwl);
1353 }
1354#else
1355# error "Unsupported OS"
1356#endif
sewardjb4112022007-11-09 22:49:28 +00001357
1358
sewardj1c147ff2009-07-26 19:52:06 +00001359//-----------------------------------------------------------
1360// glibc: pthread_rwlock_wrlock
1361// darwin: pthread_rwlock_wrlock
1362// darwin: pthread_rwlock_wrlock$UNIX2003
1363//
1364static int pthread_rwlock_wrlock_WRK(pthread_rwlock_t* rwlock)
sewardjb4112022007-11-09 22:49:28 +00001365{
1366 int ret;
1367 OrigFn fn;
1368 VALGRIND_GET_ORIG_FN(fn);
1369 if (TRACE_PTH_FNS) {
1370 fprintf(stderr, "<< pthread_rwl_wlk %p", rwlock); fflush(stderr);
1371 }
1372
sewardj789c3c52008-02-25 12:10:07 +00001373 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1374 pthread_rwlock_t*,rwlock,
1375 long,1/*isW*/, long,0/*!isTryLock*/);
sewardjb4112022007-11-09 22:49:28 +00001376
1377 CALL_FN_W_W(ret, fn, rwlock);
1378
1379 if (ret == 0 /*success*/) {
1380 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1381 pthread_rwlock_t*,rwlock, long,1/*isW*/);
1382 } else {
1383 DO_PthAPIerror( "pthread_rwlock_wrlock", ret );
1384 }
1385
1386 if (TRACE_PTH_FNS) {
1387 fprintf(stderr, " :: rwl_wlk -> %d >>\n", ret);
1388 }
1389 return ret;
1390}
sewardj1c147ff2009-07-26 19:52:06 +00001391#if defined(VGO_linux)
1392 PTH_FUNC(int, pthreadZurwlockZuwrlock, // pthread_rwlock_wrlock
1393 pthread_rwlock_t* rwlock) {
1394 return pthread_rwlock_wrlock_WRK(rwlock);
1395 }
1396#elif defined(VGO_darwin)
1397 PTH_FUNC(int, pthreadZurwlockZuwrlockZa, // pthread_rwlock_wrlock*
1398 pthread_rwlock_t* rwlock) {
1399 return pthread_rwlock_wrlock_WRK(rwlock);
1400 }
1401#else
1402# error "Unsupported OS"
1403#endif
sewardjb4112022007-11-09 22:49:28 +00001404
1405
sewardj1c147ff2009-07-26 19:52:06 +00001406//-----------------------------------------------------------
1407// glibc: pthread_rwlock_rdlock
1408// darwin: pthread_rwlock_rdlock
1409// darwin: pthread_rwlock_rdlock$UNIX2003
1410//
1411static int pthread_rwlock_rdlock_WRK(pthread_rwlock_t* rwlock)
sewardjb4112022007-11-09 22:49:28 +00001412{
1413 int ret;
1414 OrigFn fn;
1415 VALGRIND_GET_ORIG_FN(fn);
1416 if (TRACE_PTH_FNS) {
1417 fprintf(stderr, "<< pthread_rwl_rlk %p", rwlock); fflush(stderr);
1418 }
1419
sewardj789c3c52008-02-25 12:10:07 +00001420 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1421 pthread_rwlock_t*,rwlock,
1422 long,0/*!isW*/, long,0/*!isTryLock*/);
sewardjb4112022007-11-09 22:49:28 +00001423
1424 CALL_FN_W_W(ret, fn, rwlock);
1425
1426 if (ret == 0 /*success*/) {
1427 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1428 pthread_rwlock_t*,rwlock, long,0/*!isW*/);
1429 } else {
1430 DO_PthAPIerror( "pthread_rwlock_rdlock", ret );
1431 }
1432
1433 if (TRACE_PTH_FNS) {
1434 fprintf(stderr, " :: rwl_rlk -> %d >>\n", ret);
1435 }
1436 return ret;
1437}
sewardj1c147ff2009-07-26 19:52:06 +00001438#if defined(VGO_linux)
1439 PTH_FUNC(int, pthreadZurwlockZurdlock, // pthread_rwlock_rdlock
1440 pthread_rwlock_t* rwlock) {
1441 return pthread_rwlock_rdlock_WRK(rwlock);
1442 }
1443#elif defined(VGO_darwin)
1444 PTH_FUNC(int, pthreadZurwlockZurdlockZa, // pthread_rwlock_rdlock*
1445 pthread_rwlock_t* rwlock) {
1446 return pthread_rwlock_rdlock_WRK(rwlock);
1447 }
1448#else
1449# error "Unsupported OS"
1450#endif
sewardjb4112022007-11-09 22:49:28 +00001451
1452
sewardj1c147ff2009-07-26 19:52:06 +00001453//-----------------------------------------------------------
1454// glibc: pthread_rwlock_trywrlock
1455// darwin: pthread_rwlock_trywrlock
1456// darwin: pthread_rwlock_trywrlock$UNIX2003
1457//
1458static int pthread_rwlock_trywrlock_WRK(pthread_rwlock_t* rwlock)
sewardj789c3c52008-02-25 12:10:07 +00001459{
1460 int ret;
1461 OrigFn fn;
1462 VALGRIND_GET_ORIG_FN(fn);
1463 if (TRACE_PTH_FNS) {
1464 fprintf(stderr, "<< pthread_rwl_trywlk %p", rwlock); fflush(stderr);
1465 }
1466
1467 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1468 pthread_rwlock_t*,rwlock,
1469 long,1/*isW*/, long,1/*isTryLock*/);
1470
1471 CALL_FN_W_W(ret, fn, rwlock);
1472
1473 /* There's a hole here: libpthread now knows the lock is locked,
1474 but the tool doesn't, so some other thread could run and detect
1475 that the lock has been acquired by someone (this thread). Does
1476 this matter? Not sure, but I don't think so. */
1477
1478 if (ret == 0 /*success*/) {
1479 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1480 pthread_rwlock_t*,rwlock, long,1/*isW*/);
1481 } else {
1482 if (ret != EBUSY)
1483 DO_PthAPIerror( "pthread_rwlock_trywrlock", ret );
1484 }
1485
1486 if (TRACE_PTH_FNS) {
1487 fprintf(stderr, " :: rwl_trywlk -> %d >>\n", ret);
1488 }
1489 return ret;
1490}
sewardj1c147ff2009-07-26 19:52:06 +00001491#if defined(VGO_linux)
1492 PTH_FUNC(int, pthreadZurwlockZutrywrlock, // pthread_rwlock_trywrlock
1493 pthread_rwlock_t* rwlock) {
1494 return pthread_rwlock_trywrlock_WRK(rwlock);
1495 }
1496#elif defined(VGO_darwin)
1497 PTH_FUNC(int, pthreadZurwlockZutrywrlockZa, // pthread_rwlock_trywrlock*
1498 pthread_rwlock_t* rwlock) {
1499 return pthread_rwlock_trywrlock_WRK(rwlock);
1500 }
1501#else
1502# error "Unsupported OS"
1503#endif
sewardj789c3c52008-02-25 12:10:07 +00001504
1505
sewardj1c147ff2009-07-26 19:52:06 +00001506//-----------------------------------------------------------
1507// glibc: pthread_rwlock_tryrdlock
1508// darwin: pthread_rwlock_trywrlock
1509// darwin: pthread_rwlock_trywrlock$UNIX2003
1510//
1511static int pthread_rwlock_tryrdlock_WRK(pthread_rwlock_t* rwlock)
sewardj789c3c52008-02-25 12:10:07 +00001512{
1513 int ret;
1514 OrigFn fn;
1515 VALGRIND_GET_ORIG_FN(fn);
1516 if (TRACE_PTH_FNS) {
1517 fprintf(stderr, "<< pthread_rwl_tryrlk %p", rwlock); fflush(stderr);
1518 }
1519
1520 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1521 pthread_rwlock_t*,rwlock,
1522 long,0/*!isW*/, long,1/*isTryLock*/);
1523
1524 CALL_FN_W_W(ret, fn, rwlock);
1525
1526 /* There's a hole here: libpthread now knows the lock is locked,
1527 but the tool doesn't, so some other thread could run and detect
1528 that the lock has been acquired by someone (this thread). Does
1529 this matter? Not sure, but I don't think so. */
1530
1531 if (ret == 0 /*success*/) {
1532 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1533 pthread_rwlock_t*,rwlock, long,0/*!isW*/);
1534 } else {
1535 if (ret != EBUSY)
1536 DO_PthAPIerror( "pthread_rwlock_tryrdlock", ret );
1537 }
1538
1539 if (TRACE_PTH_FNS) {
1540 fprintf(stderr, " :: rwl_tryrlk -> %d >>\n", ret);
1541 }
1542 return ret;
1543}
sewardj1c147ff2009-07-26 19:52:06 +00001544#if defined(VGO_linux)
1545 PTH_FUNC(int, pthreadZurwlockZutryrdlock, // pthread_rwlock_tryrdlock
1546 pthread_rwlock_t* rwlock) {
1547 return pthread_rwlock_tryrdlock_WRK(rwlock);
1548 }
1549#elif defined(VGO_darwin)
1550 PTH_FUNC(int, pthreadZurwlockZutryrdlockZa, // pthread_rwlock_tryrdlock*
1551 pthread_rwlock_t* rwlock) {
1552 return pthread_rwlock_tryrdlock_WRK(rwlock);
1553 }
1554#else
1555# error "Unsupported OS"
1556#endif
sewardj789c3c52008-02-25 12:10:07 +00001557
1558
sewardj1c147ff2009-07-26 19:52:06 +00001559//-----------------------------------------------------------
1560// glibc: pthread_rwlock_unlock
1561// darwin: pthread_rwlock_unlock
1562// darwin: pthread_rwlock_unlock$UNIX2003
1563static int pthread_rwlock_unlock_WRK(pthread_rwlock_t* rwlock)
sewardjb4112022007-11-09 22:49:28 +00001564{
1565 int ret;
1566 OrigFn fn;
1567 VALGRIND_GET_ORIG_FN(fn);
1568 if (TRACE_PTH_FNS) {
1569 fprintf(stderr, "<< pthread_rwl_unlk %p", rwlock); fflush(stderr);
1570 }
1571
1572 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE,
1573 pthread_rwlock_t*,rwlock);
1574
1575 CALL_FN_W_W(ret, fn, rwlock);
1576
1577 if (ret == 0 /*success*/) {
1578 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST,
1579 pthread_rwlock_t*,rwlock);
1580 } else {
1581 DO_PthAPIerror( "pthread_rwlock_unlock", ret );
1582 }
1583
1584 if (TRACE_PTH_FNS) {
1585 fprintf(stderr, " :: rwl_unlk -> %d >>\n", ret);
1586 }
1587 return ret;
1588}
sewardj1c147ff2009-07-26 19:52:06 +00001589#if defined(VGO_linux)
1590 PTH_FUNC(int, pthreadZurwlockZuunlock, // pthread_rwlock_unlock
1591 pthread_rwlock_t* rwlock) {
1592 return pthread_rwlock_unlock_WRK(rwlock);
1593 }
1594#elif defined(VGO_darwin)
1595 PTH_FUNC(int, pthreadZurwlockZuunlockZa, // pthread_rwlock_unlock*
1596 pthread_rwlock_t* rwlock) {
1597 return pthread_rwlock_unlock_WRK(rwlock);
1598 }
1599#else
1600# error "Unsupported OS"
1601#endif
sewardjb4112022007-11-09 22:49:28 +00001602
1603
1604/*----------------------------------------------------------------*/
1605/*--- POSIX semaphores ---*/
1606/*----------------------------------------------------------------*/
1607
1608#include <semaphore.h>
sewardj28a7f7d2009-07-26 20:15:37 +00001609#include <fcntl.h> /* O_CREAT */
sewardjb4112022007-11-09 22:49:28 +00001610
1611#define TRACE_SEM_FNS 0
1612
1613/* Handled:
1614 int sem_init(sem_t *sem, int pshared, unsigned value);
1615 int sem_destroy(sem_t *sem);
1616 int sem_wait(sem_t *sem);
1617 int sem_post(sem_t *sem);
sewardj1c147ff2009-07-26 19:52:06 +00001618 sem_t* sem_open(const char *name, int oflag,
1619 ... [mode_t mode, unsigned value]);
1620 [complete with its idiotic semantics]
1621 int sem_close(sem_t* sem);
sewardjb4112022007-11-09 22:49:28 +00001622
1623 Unhandled:
1624 int sem_trywait(sem_t *sem);
1625 int sem_timedwait(sem_t *restrict sem,
1626 const struct timespec *restrict abs_timeout);
1627*/
1628
sewardj1c147ff2009-07-26 19:52:06 +00001629//-----------------------------------------------------------
1630// glibc: sem_init@@GLIBC_2.2.5
1631// glibc: sem_init@@GLIBC_2.1
1632// glibc: sem_init@GLIBC_2.0
1633// darwin: sem_init
1634//
1635static int sem_init_WRK(sem_t* sem, int pshared, unsigned long value)
sewardjb4112022007-11-09 22:49:28 +00001636{
1637 OrigFn fn;
1638 int ret;
1639 VALGRIND_GET_ORIG_FN(fn);
1640
1641 if (TRACE_SEM_FNS) {
1642 fprintf(stderr, "<< sem_init(%p,%d,%lu) ", sem,pshared,value);
1643 fflush(stderr);
1644 }
1645
1646 CALL_FN_W_WWW(ret, fn, sem,pshared,value);
1647
1648 if (ret == 0) {
sewardj11e352f2007-11-30 11:11:02 +00001649 DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST,
1650 sem_t*, sem, unsigned long, value);
sewardjb4112022007-11-09 22:49:28 +00001651 } else {
1652 DO_PthAPIerror( "sem_init", errno );
1653 }
1654
1655 if (TRACE_SEM_FNS) {
1656 fprintf(stderr, " sem_init -> %d >>\n", ret);
1657 fflush(stderr);
1658 }
1659
1660 return ret;
1661}
sewardj1c147ff2009-07-26 19:52:06 +00001662#if defined(VGO_linux)
1663 PTH_FUNC(int, semZuinitZAZa, // sem_init@*
1664 sem_t* sem, int pshared, unsigned long value) {
1665 return sem_init_WRK(sem, pshared, value);
1666 }
1667#elif defined(VGO_darwin)
1668 PTH_FUNC(int, semZuinit, // sem_init
1669 sem_t* sem, int pshared, unsigned long value) {
1670 return sem_init_WRK(sem, pshared, value);
1671 }
1672#else
1673# error "Unsupported OS"
1674#endif
sewardjb4112022007-11-09 22:49:28 +00001675
1676
sewardj1c147ff2009-07-26 19:52:06 +00001677//-----------------------------------------------------------
1678// glibc: sem_destroy@GLIBC_2.0
1679// glibc: sem_destroy@@GLIBC_2.1
1680// glibc: sem_destroy@@GLIBC_2.2.5
1681// darwin: sem_destroy
1682static int sem_destroy_WRK(sem_t* sem)
sewardjb4112022007-11-09 22:49:28 +00001683{
1684 OrigFn fn;
1685 int ret;
1686 VALGRIND_GET_ORIG_FN(fn);
1687
1688 if (TRACE_SEM_FNS) {
1689 fprintf(stderr, "<< sem_destroy(%p) ", sem);
1690 fflush(stderr);
1691 }
1692
sewardj11e352f2007-11-30 11:11:02 +00001693 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, sem_t*, sem);
sewardjb4112022007-11-09 22:49:28 +00001694
1695 CALL_FN_W_W(ret, fn, sem);
1696
1697 if (ret != 0) {
1698 DO_PthAPIerror( "sem_destroy", errno );
1699 }
1700
1701 if (TRACE_SEM_FNS) {
1702 fprintf(stderr, " sem_destroy -> %d >>\n", ret);
1703 fflush(stderr);
1704 }
1705
1706 return ret;
1707}
sewardj1c147ff2009-07-26 19:52:06 +00001708#if defined(VGO_linux)
1709 PTH_FUNC(int, semZudestroyZAZa, // sem_destroy*
1710 sem_t* sem) {
1711 return sem_destroy_WRK(sem);
1712 }
1713#elif defined(VGO_darwin)
1714 PTH_FUNC(int, semZudestroy, // sem_destroy
1715 sem_t* sem) {
1716 return sem_destroy_WRK(sem);
1717 }
1718#else
1719# error "Unsupported OS"
1720#endif
sewardjb4112022007-11-09 22:49:28 +00001721
1722
sewardj1c147ff2009-07-26 19:52:06 +00001723//-----------------------------------------------------------
1724// glibc: sem_wait
1725// glibc: sem_wait@GLIBC_2.0
1726// glibc: sem_wait@@GLIBC_2.1
1727// darwin: sem_wait
1728// darwin: sem_wait$NOCANCEL$UNIX2003
1729// darwin: sem_wait$UNIX2003
1730//
sewardjb4112022007-11-09 22:49:28 +00001731/* wait: decrement semaphore - acquire lockage */
1732static int sem_wait_WRK(sem_t* sem)
1733{
1734 OrigFn fn;
1735 int ret;
1736 VALGRIND_GET_ORIG_FN(fn);
1737
1738 if (TRACE_SEM_FNS) {
1739 fprintf(stderr, "<< sem_wait(%p) ", sem);
1740 fflush(stderr);
1741 }
1742
1743 CALL_FN_W_W(ret, fn, sem);
1744
1745 if (ret == 0) {
sewardj11e352f2007-11-30 11:11:02 +00001746 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_WAIT_POST, sem_t*,sem);
sewardjb4112022007-11-09 22:49:28 +00001747 } else {
1748 DO_PthAPIerror( "sem_wait", errno );
1749 }
1750
1751 if (TRACE_SEM_FNS) {
1752 fprintf(stderr, " sem_wait -> %d >>\n", ret);
1753 fflush(stderr);
1754 }
1755
1756 return ret;
1757}
sewardj1c147ff2009-07-26 19:52:06 +00001758#if defined(VGO_linux)
1759 PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */
1760 return sem_wait_WRK(sem);
1761 }
1762 PTH_FUNC(int, semZuwaitZAZa, sem_t* sem) { /* sem_wait@* */
1763 return sem_wait_WRK(sem);
1764 }
1765#elif defined(VGO_darwin)
1766 PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */
1767 return sem_wait_WRK(sem);
1768 }
1769 PTH_FUNC(int, semZuwaitZDZa, sem_t* sem) { /* sem_wait$* */
1770 return sem_wait_WRK(sem);
1771 }
1772#else
1773# error "Unsupported OS"
1774#endif
sewardjb4112022007-11-09 22:49:28 +00001775
1776
sewardj1c147ff2009-07-26 19:52:06 +00001777//-----------------------------------------------------------
1778// glibc: sem_post
1779// glibc: sem_post@GLIBC_2.0
1780// glibc: sem_post@@GLIBC_2.1
1781// darwin: sem_post
1782//
sewardjb4112022007-11-09 22:49:28 +00001783/* post: increment semaphore - release lockage */
1784static int sem_post_WRK(sem_t* sem)
1785{
1786 OrigFn fn;
1787 int ret;
1788
1789 VALGRIND_GET_ORIG_FN(fn);
1790
1791 if (TRACE_SEM_FNS) {
1792 fprintf(stderr, "<< sem_post(%p) ", sem);
1793 fflush(stderr);
1794 }
1795
sewardj11e352f2007-11-30 11:11:02 +00001796 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_POST_PRE, sem_t*,sem);
sewardjb4112022007-11-09 22:49:28 +00001797
1798 CALL_FN_W_W(ret, fn, sem);
1799
1800 if (ret != 0) {
1801 DO_PthAPIerror( "sem_post", errno );
1802 }
1803
1804 if (TRACE_SEM_FNS) {
1805 fprintf(stderr, " sem_post -> %d >>\n", ret);
1806 fflush(stderr);
1807 }
1808
1809 return ret;
1810}
sewardj1c147ff2009-07-26 19:52:06 +00001811#if defined(VGO_linux)
1812 PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */
1813 return sem_post_WRK(sem);
1814 }
1815 PTH_FUNC(int, semZupostZAZa, sem_t* sem) { /* sem_post@* */
1816 return sem_post_WRK(sem);
1817 }
1818#elif defined(VGO_darwin)
1819 PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */
1820 return sem_post_WRK(sem);
1821 }
1822#else
1823# error "Unsupported OS"
1824#endif
1825
1826
1827//-----------------------------------------------------------
1828// glibc: sem_open
1829// darwin: sem_open
1830//
1831PTH_FUNC(sem_t*, semZuopen,
1832 const char* name, long oflag,
1833 long mode, unsigned long value)
1834{
1835 /* A copy of sem_init_WRK (more or less). Is this correct? */
1836 OrigFn fn;
1837 sem_t* ret;
1838 VALGRIND_GET_ORIG_FN(fn);
1839
1840 if (TRACE_SEM_FNS) {
1841 fprintf(stderr, "<< sem_open(\"%s\",%ld,%lx,%lu) ",
1842 name,oflag,mode,value);
1843 fflush(stderr);
1844 }
1845
1846 CALL_FN_W_WWWW(ret, fn, name,oflag,mode,value);
1847
1848 if (ret != SEM_FAILED && (oflag & O_CREAT)) {
1849 DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST,
1850 sem_t*, ret, unsigned long, value);
1851 }
1852 if (ret == SEM_FAILED) {
1853 DO_PthAPIerror( "sem_open", errno );
1854 }
1855
1856 if (TRACE_SEM_FNS) {
1857 fprintf(stderr, " sem_open -> %p >>\n", ret);
1858 fflush(stderr);
1859 }
1860
1861 return ret;
sewardjb4112022007-11-09 22:49:28 +00001862}
1863
1864
sewardj1c147ff2009-07-26 19:52:06 +00001865//-----------------------------------------------------------
1866// glibc: sem_close
1867// darwin: sem_close
1868PTH_FUNC(int, sem_close, sem_t* sem)
1869{
1870 OrigFn fn;
1871 int ret;
1872 VALGRIND_GET_ORIG_FN(fn);
1873
1874 if (TRACE_SEM_FNS) {
1875 fprintf(stderr, "<< sem_close(%p) ", sem);
1876 fflush(stderr);
1877 }
1878
1879 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, sem_t*, sem);
1880
1881 CALL_FN_W_W(ret, fn, sem);
1882
1883 if (ret != 0) {
1884 DO_PthAPIerror( "sem_close", errno );
1885 }
1886
1887 if (TRACE_SEM_FNS) {
1888 fprintf(stderr, " close -> %d >>\n", ret);
1889 fflush(stderr);
1890 }
1891
1892 return ret;
1893}
1894
sewardjb4112022007-11-09 22:49:28 +00001895
1896/*----------------------------------------------------------------*/
1897/*--- Qt 4 threading functions (w/ GNU name mangling) ---*/
1898/*----------------------------------------------------------------*/
1899
sewardj38e0cf92008-11-19 10:40:56 +00001900/* Handled:
1901 QMutex::lock()
1902 QMutex::unlock()
1903 QMutex::tryLock()
1904 QMutex::tryLock(int)
sewardjb4112022007-11-09 22:49:28 +00001905
sewardj38e0cf92008-11-19 10:40:56 +00001906 QMutex::QMutex(QMutex::RecursionMode) _ZN6QMutexC1ENS_13RecursionModeE
1907 QMutex::QMutex(QMutex::RecursionMode) _ZN6QMutexC2ENS_13RecursionModeE
1908 QMutex::~QMutex() _ZN6QMutexD1Ev
1909 QMutex::~QMutex() _ZN6QMutexD2Ev
sewardjb4112022007-11-09 22:49:28 +00001910
sewardj38e0cf92008-11-19 10:40:56 +00001911 Unhandled:
1912 QReadWriteLock::lockForRead()
1913 QReadWriteLock::lockForWrite()
1914 QReadWriteLock::unlock()
1915 QReadWriteLock::tryLockForRead(int)
1916 QReadWriteLock::tryLockForRead()
1917 QReadWriteLock::tryLockForWrite(int)
1918 QReadWriteLock::tryLockForWrite()
1919
1920 QWaitCondition::wait(QMutex*, unsigned long)
1921 QWaitCondition::wakeAll()
1922 QWaitCondition::wakeOne()
1923
1924 QSemaphore::*
1925*/
1926/* More comments, 19 Nov 08, based on assessment of qt-4.5.0TP1,
1927 at least on Unix:
1928
1929 It's apparently only necessary to intercept QMutex, since that is
1930 not implemented using pthread_mutex_t; instead Qt4 has its own
1931 implementation based on atomics (to check the non-contended case)
1932 and pthread_cond_wait (to wait in the contended case).
1933
1934 QReadWriteLock is built on top of QMutex, counters, and a wait
1935 queue. So we don't need to handle it specially once QMutex
1936 handling is correct -- presumably the dependencies through QMutex
1937 are sufficient to avoid any false race reports. On the other hand,
1938 it is an open question whether too many dependencies are observed
1939 -- in which case we may miss races (false negatives). I suspect
1940 this is likely to be the case, unfortunately.
1941
1942 QWaitCondition is built on pthread_cond_t, pthread_mutex_t, QMutex
1943 and QReadWriteLock. Same compositional-correctness justificiation
1944 and limitations as fro QReadWriteLock.
1945
1946 Ditto QSemaphore (from cursory examination).
1947
1948 Does it matter that only QMutex is handled directly? Open
1949 question. From testing with drd/tests/qt4_* and with KDE4 apps, it
1950 appears that no false errors are reported; however it is not clear
1951 if this is causing false negatives.
1952
1953 Another problem with Qt4 is thread exiting. Threads are created
1954 with pthread_create (fine); but they detach and simply exit when
1955 done. There is no use of pthread_join, and the provided
1956 wait-for-a-thread-to-exit mechanism (QThread::wait, I believe)
1957 relies on a system of mutexes and flags. I suspect this also
1958 causes too many dependencies to appear. Consequently H sometimes
1959 fails to detect races at exit in some very short-lived racy
1960 programs, because it appears that a thread can exit _and_ have an
1961 observed dependency edge back to the main thread (presumably)
1962 before the main thread reaps the child (that is, calls
1963 QThread::wait).
1964
1965 This theory is supported by the observation that if all threads are
1966 made to wait at a pthread_barrier_t immediately before they exit,
1967 then H's detection of races in such programs becomes reliable;
1968 without the barrier, it is varies from run to run, depending
1969 (according to investigation) on whether aforementioned
1970 exit-before-reaping behaviour happens or not.
1971
1972 Finally, why is it necessary to intercept the QMutex constructors
1973 and destructors? The constructors are intercepted only as a matter
1974 of convenience, so H can print accurate "first observed at"
1975 clauses. However, it is actually necessary to intercept the
1976 destructors (as it is with pthread_mutex_destroy) in order that
1977 locks get removed from LAOG when they are destroyed.
sewardjb4112022007-11-09 22:49:28 +00001978*/
1979
1980// soname is libQtCore.so.4 ; match against libQtCore.so*
1981#define QT4_FUNC(ret_ty, f, args...) \
sewardj38e0cf92008-11-19 10:40:56 +00001982 ret_ty I_WRAP_SONAME_FNNAME_ZU(libQtCoreZdsoZa,f)(args); \
1983 ret_ty I_WRAP_SONAME_FNNAME_ZU(libQtCoreZdsoZa,f)(args)
sewardjb4112022007-11-09 22:49:28 +00001984
sewardj1c147ff2009-07-26 19:52:06 +00001985//-----------------------------------------------------------
sewardjb4112022007-11-09 22:49:28 +00001986// QMutex::lock()
sewardj38e0cf92008-11-19 10:40:56 +00001987QT4_FUNC(void, _ZN6QMutex4lockEv, void* self)
sewardjb4112022007-11-09 22:49:28 +00001988{
1989 OrigFn fn;
1990 VALGRIND_GET_ORIG_FN(fn);
1991 if (TRACE_QT4_FNS) {
1992 fprintf(stderr, "<< QMutex::lock %p", self); fflush(stderr);
1993 }
1994
1995 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
1996 void*,self, long,0/*!isTryLock*/);
1997
1998 CALL_FN_v_W(fn, self);
1999
2000 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
2001 void*, self);
2002
2003 if (TRACE_QT4_FNS) {
2004 fprintf(stderr, " :: Q::lock done >>\n");
2005 }
2006}
2007
sewardj1c147ff2009-07-26 19:52:06 +00002008//-----------------------------------------------------------
sewardjb4112022007-11-09 22:49:28 +00002009// QMutex::unlock()
sewardj38e0cf92008-11-19 10:40:56 +00002010QT4_FUNC(void, _ZN6QMutex6unlockEv, void* self)
sewardjb4112022007-11-09 22:49:28 +00002011{
2012 OrigFn fn;
2013 VALGRIND_GET_ORIG_FN(fn);
2014
2015 if (TRACE_QT4_FNS) {
2016 fprintf(stderr, "<< QMutex::unlock %p", self); fflush(stderr);
2017 }
2018
2019 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
2020 void*, self);
2021
2022 CALL_FN_v_W(fn, self);
2023
2024 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST,
2025 void*, self);
2026
2027 if (TRACE_QT4_FNS) {
2028 fprintf(stderr, " Q::unlock done >>\n");
2029 }
2030}
2031
sewardj1c147ff2009-07-26 19:52:06 +00002032//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002033// bool QMutex::tryLock()
sewardjb4112022007-11-09 22:49:28 +00002034// using 'long' to mimic C++ 'bool'
sewardj38e0cf92008-11-19 10:40:56 +00002035QT4_FUNC(long, _ZN6QMutex7tryLockEv, void* self)
sewardjb4112022007-11-09 22:49:28 +00002036{
2037 OrigFn fn;
2038 long ret;
2039 VALGRIND_GET_ORIG_FN(fn);
2040 if (TRACE_QT4_FNS) {
2041 fprintf(stderr, "<< QMutex::tryLock %p", self); fflush(stderr);
2042 }
2043
2044 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
2045 void*,self, long,1/*isTryLock*/);
2046
2047 CALL_FN_W_W(ret, fn, self);
2048
2049 // assumes that only the low 8 bits of the 'bool' are significant
2050 if (ret & 0xFF) {
2051 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
2052 void*, self);
2053 }
2054
2055 if (TRACE_QT4_FNS) {
2056 fprintf(stderr, " :: Q::tryLock -> %lu >>\n", ret);
2057 }
2058
2059 return ret;
2060}
2061
sewardj1c147ff2009-07-26 19:52:06 +00002062//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002063// bool QMutex::tryLock(int)
2064// using 'long' to mimic C++ 'bool'
2065QT4_FUNC(long, _ZN6QMutex7tryLockEi, void* self, long arg2)
sewardjb4112022007-11-09 22:49:28 +00002066{
2067 OrigFn fn;
sewardj38e0cf92008-11-19 10:40:56 +00002068 long ret;
sewardjb4112022007-11-09 22:49:28 +00002069 VALGRIND_GET_ORIG_FN(fn);
2070 if (TRACE_QT4_FNS) {
sewardj38e0cf92008-11-19 10:40:56 +00002071 fprintf(stderr, "<< QMutex::tryLock(int) %p %d", self, (int)arg2);
sewardjb4112022007-11-09 22:49:28 +00002072 fflush(stderr);
2073 }
2074
sewardj38e0cf92008-11-19 10:40:56 +00002075 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
2076 void*,self, long,1/*isTryLock*/);
sewardjb4112022007-11-09 22:49:28 +00002077
sewardj38e0cf92008-11-19 10:40:56 +00002078 CALL_FN_W_WW(ret, fn, self,arg2);
sewardjb4112022007-11-09 22:49:28 +00002079
sewardj38e0cf92008-11-19 10:40:56 +00002080 // assumes that only the low 8 bits of the 'bool' are significant
2081 if (ret & 0xFF) {
2082 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
2083 void*, self);
2084 }
sewardjb4112022007-11-09 22:49:28 +00002085
2086 if (TRACE_QT4_FNS) {
sewardj38e0cf92008-11-19 10:40:56 +00002087 fprintf(stderr, " :: Q::tryLock(int) -> %lu >>\n", ret);
sewardjb4112022007-11-09 22:49:28 +00002088 }
sewardj38e0cf92008-11-19 10:40:56 +00002089
2090 return ret;
sewardjb4112022007-11-09 22:49:28 +00002091}
2092
sewardj38e0cf92008-11-19 10:40:56 +00002093
sewardj1c147ff2009-07-26 19:52:06 +00002094//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002095// It's not really very clear what the args are here. But from
2096// a bit of dataflow analysis of the generated machine code of
2097// the original function, it appears this takes two args, and
2098// returns nothing. Nevertheless preserve return value just in
2099// case. A bit of debug printing indicates that the first arg
2100// is that of the mutex and the second is either zero or one,
2101// probably being the recursion mode, therefore.
2102// QMutex::QMutex(QMutex::RecursionMode) ("C1ENS" variant)
2103QT4_FUNC(void*, _ZN6QMutexC1ENS_13RecursionModeE,
2104 void* mutex,
2105 long recmode)
sewardjb4112022007-11-09 22:49:28 +00002106{
2107 OrigFn fn;
sewardj38e0cf92008-11-19 10:40:56 +00002108 long ret;
sewardjb4112022007-11-09 22:49:28 +00002109 VALGRIND_GET_ORIG_FN(fn);
sewardj38e0cf92008-11-19 10:40:56 +00002110 CALL_FN_W_WW(ret, fn, mutex, recmode);
2111 // fprintf(stderr, "QMutex constructor 1: %p <- %p %p\n", ret, arg1, arg2);
2112 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST,
2113 void*,mutex, long,1/*mbRec*/);
2114 return (void*)ret;
sewardjb4112022007-11-09 22:49:28 +00002115}
2116
sewardj1c147ff2009-07-26 19:52:06 +00002117//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002118// QMutex::~QMutex() ("D1Ev" variant)
2119QT4_FUNC(void*, _ZN6QMutexD1Ev, void* mutex)
sewardjb4112022007-11-09 22:49:28 +00002120{
2121 OrigFn fn;
sewardj38e0cf92008-11-19 10:40:56 +00002122 long ret;
sewardjb4112022007-11-09 22:49:28 +00002123 VALGRIND_GET_ORIG_FN(fn);
sewardj38e0cf92008-11-19 10:40:56 +00002124 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE,
2125 void*,mutex);
2126 CALL_FN_W_W(ret, fn, mutex);
2127 return (void*)ret;
sewardjb4112022007-11-09 22:49:28 +00002128}
2129
2130
sewardj1c147ff2009-07-26 19:52:06 +00002131//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002132// QMutex::QMutex(QMutex::RecursionMode) ("C2ENS" variant)
2133QT4_FUNC(void*, _ZN6QMutexC2ENS_13RecursionModeE,
2134 void* mutex,
2135 long recmode)
2136{
2137 assert(0);
2138}
2139
sewardj1c147ff2009-07-26 19:52:06 +00002140
2141//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002142// QMutex::~QMutex() ("D2Ev" variant)
2143QT4_FUNC(void*, _ZN6QMutexD2Ev, void* mutex)
2144{
2145 assert(0);
2146}
2147
2148
2149// QReadWriteLock is not intercepted directly. See comments
2150// above.
2151
2152//// QReadWriteLock::lockForRead()
2153//// _ZN14QReadWriteLock11lockForReadEv == QReadWriteLock::lockForRead()
2154//QT4_FUNC(void, ZuZZN14QReadWriteLock11lockForReadEv,
2155// // _ZN14QReadWriteLock11lockForReadEv
2156// void* self)
2157//{
2158// OrigFn fn;
2159// VALGRIND_GET_ORIG_FN(fn);
2160// if (TRACE_QT4_FNS) {
2161// fprintf(stderr, "<< QReadWriteLock::lockForRead %p", self);
2162// fflush(stderr);
2163// }
2164//
2165// DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
2166// void*,self,
2167// long,0/*!isW*/, long,0/*!isTryLock*/);
2168//
2169// CALL_FN_v_W(fn, self);
2170//
2171// DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
2172// void*,self, long,0/*!isW*/);
2173//
2174// if (TRACE_QT4_FNS) {
2175// fprintf(stderr, " :: Q::lockForRead :: done >>\n");
2176// }
2177//}
2178//
2179//// QReadWriteLock::lockForWrite()
2180//// _ZN14QReadWriteLock12lockForWriteEv == QReadWriteLock::lockForWrite()
2181//QT4_FUNC(void, ZuZZN14QReadWriteLock12lockForWriteEv,
2182// // _ZN14QReadWriteLock12lockForWriteEv
2183// void* self)
2184//{
2185// OrigFn fn;
2186// VALGRIND_GET_ORIG_FN(fn);
2187// if (TRACE_QT4_FNS) {
2188// fprintf(stderr, "<< QReadWriteLock::lockForWrite %p", self);
2189// fflush(stderr);
2190// }
2191//
2192// DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
2193// void*,self,
2194// long,1/*isW*/, long,0/*!isTryLock*/);
2195//
2196// CALL_FN_v_W(fn, self);
2197//
2198// DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
2199// void*,self, long,1/*isW*/);
2200//
2201// if (TRACE_QT4_FNS) {
2202// fprintf(stderr, " :: Q::lockForWrite :: done >>\n");
2203// }
2204//}
2205//
2206//// QReadWriteLock::unlock()
2207//// _ZN14QReadWriteLock6unlockEv == QReadWriteLock::unlock()
2208//QT4_FUNC(void, ZuZZN14QReadWriteLock6unlockEv,
2209// // _ZN14QReadWriteLock6unlockEv
2210// void* self)
2211//{
2212// OrigFn fn;
2213// VALGRIND_GET_ORIG_FN(fn);
2214// if (TRACE_QT4_FNS) {
2215// fprintf(stderr, "<< QReadWriteLock::unlock %p", self);
2216// fflush(stderr);
2217// }
2218//
2219// DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE,
2220// void*,self);
2221//
2222// CALL_FN_v_W(fn, self);
2223//
2224// DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST,
2225// void*,self);
2226//
2227// if (TRACE_QT4_FNS) {
2228// fprintf(stderr, " :: Q::unlock :: done >>\n");
2229// }
2230//}
2231
2232
2233/*----------------------------------------------------------------*/
2234/*--- Replacements for basic string functions, that don't ---*/
sewardjb80f0c92008-11-19 16:33:59 +00002235/*--- overrun the input arrays. ---*/
sewardj38e0cf92008-11-19 10:40:56 +00002236/*----------------------------------------------------------------*/
2237
2238/* Copied verbatim from memcheck/mc_replace_strmem.c. When copying
2239 new functions, please keep them in the same order as they appear in
2240 mc_replace_strmem.c. */
2241
sewardj38e0cf92008-11-19 10:40:56 +00002242
2243#define STRCHR(soname, fnname) \
2244 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
2245 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
2246 { \
2247 UChar ch = (UChar)((UInt)c); \
2248 UChar* p = (UChar*)s; \
2249 while (True) { \
2250 if (*p == ch) return p; \
2251 if (*p == 0) return NULL; \
2252 p++; \
2253 } \
2254 }
2255
2256// Apparently index() is the same thing as strchr()
njne6154662009-02-10 04:23:41 +00002257STRCHR(VG_Z_LIBC_SONAME, strchr)
njne6154662009-02-10 04:23:41 +00002258STRCHR(VG_Z_LIBC_SONAME, index)
njnb4cfbc42009-05-04 04:20:02 +00002259#if defined(VGO_linux)
2260STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
njne6154662009-02-10 04:23:41 +00002261STRCHR(VG_Z_LD_LINUX_SO_2, index)
njnb4cfbc42009-05-04 04:20:02 +00002262STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
njne6154662009-02-10 04:23:41 +00002263STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
njnb4cfbc42009-05-04 04:20:02 +00002264#endif
sewardj38e0cf92008-11-19 10:40:56 +00002265
2266
2267// Note that this replacement often doesn't get used because gcc inlines
2268// calls to strlen() with its own built-in version. This can be very
2269// confusing if you aren't expecting it. Other small functions in this file
2270// may also be inline by gcc.
2271#define STRLEN(soname, fnname) \
2272 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
2273 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
2274 { \
2275 SizeT i = 0; \
2276 while (str[i] != 0) i++; \
2277 return i; \
2278 }
2279
njne6154662009-02-10 04:23:41 +00002280STRLEN(VG_Z_LIBC_SONAME, strlen)
njnb4cfbc42009-05-04 04:20:02 +00002281#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +00002282STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
2283STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
njnb4cfbc42009-05-04 04:20:02 +00002284#endif
sewardj38e0cf92008-11-19 10:40:56 +00002285
2286
2287#define STRCPY(soname, fnname) \
2288 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
2289 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
2290 { \
2291 const Char* dst_orig = dst; \
2292 \
2293 while (*src) *dst++ = *src++; \
2294 *dst = 0; \
2295 \
2296 return (char*)dst_orig; \
2297 }
2298
njne6154662009-02-10 04:23:41 +00002299STRCPY(VG_Z_LIBC_SONAME, strcpy)
sewardj38e0cf92008-11-19 10:40:56 +00002300
2301
2302#define STRCMP(soname, fnname) \
2303 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2304 ( const char* s1, const char* s2 ); \
2305 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2306 ( const char* s1, const char* s2 ) \
2307 { \
2308 register unsigned char c1; \
2309 register unsigned char c2; \
2310 while (True) { \
2311 c1 = *(unsigned char *)s1; \
2312 c2 = *(unsigned char *)s2; \
2313 if (c1 != c2) break; \
2314 if (c1 == 0) break; \
2315 s1++; s2++; \
2316 } \
2317 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
2318 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
2319 return 0; \
2320 }
2321
njne6154662009-02-10 04:23:41 +00002322STRCMP(VG_Z_LIBC_SONAME, strcmp)
njnb4cfbc42009-05-04 04:20:02 +00002323#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +00002324STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
2325STRCMP(VG_Z_LD64_SO_1, strcmp)
njnb4cfbc42009-05-04 04:20:02 +00002326#endif
sewardj38e0cf92008-11-19 10:40:56 +00002327
2328
2329#define MEMCPY(soname, fnname) \
2330 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2331 ( void *dst, const void *src, SizeT len ); \
2332 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2333 ( void *dst, const void *src, SizeT len ) \
2334 { \
2335 register char *d; \
2336 register char *s; \
2337 \
2338 if (len == 0) \
2339 return dst; \
2340 \
2341 if ( dst > src ) { \
2342 d = (char *)dst + len - 1; \
2343 s = (char *)src + len - 1; \
2344 while ( len >= 4 ) { \
2345 *d-- = *s--; \
2346 *d-- = *s--; \
2347 *d-- = *s--; \
2348 *d-- = *s--; \
2349 len -= 4; \
2350 } \
2351 while ( len-- ) { \
2352 *d-- = *s--; \
2353 } \
2354 } else if ( dst < src ) { \
2355 d = (char *)dst; \
2356 s = (char *)src; \
2357 while ( len >= 4 ) { \
2358 *d++ = *s++; \
2359 *d++ = *s++; \
2360 *d++ = *s++; \
2361 *d++ = *s++; \
2362 len -= 4; \
2363 } \
2364 while ( len-- ) { \
2365 *d++ = *s++; \
2366 } \
2367 } \
2368 return dst; \
2369 }
2370
njne6154662009-02-10 04:23:41 +00002371MEMCPY(VG_Z_LIBC_SONAME, memcpy)
njnb4cfbc42009-05-04 04:20:02 +00002372#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +00002373MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
2374MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
njnb4cfbc42009-05-04 04:20:02 +00002375#endif
sewardj38e0cf92008-11-19 10:40:56 +00002376/* icc9 blats these around all over the place. Not only in the main
2377 executable but various .so's. They are highly tuned and read
2378 memory beyond the source boundary (although work correctly and
2379 never go across page boundaries), so give errors when run natively,
2380 at least for misaligned source arg. Just intercepting in the exe
2381 only until we understand more about the problem. See
2382 http://bugs.kde.org/show_bug.cgi?id=139776
2383 */
2384MEMCPY(NONE, _intel_fast_memcpy)
2385
2386
sewardjb4112022007-11-09 22:49:28 +00002387/*--------------------------------------------------------------------*/
2388/*--- end tc_intercepts.c ---*/
2389/*--------------------------------------------------------------------*/