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