blob: 8c17cc784b003be42b19733127c2f0908a9abdc1 [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
73// Do a client request. This is a macro rather than a function
74// so as to avoid having an extra function in the stack trace.
75
76#define DO_CREQ_v_W(_creqF, _ty1F,_arg1F) \
77 do { \
78 Word _unused_res, _arg1; \
79 assert(sizeof(_ty1F) == sizeof(Word)); \
80 _arg1 = (Word)(_arg1F); \
81 VALGRIND_DO_CLIENT_REQUEST(_unused_res, 0, \
82 (_creqF), \
83 _arg1, 0,0,0,0); \
84 } while (0)
85
86#define DO_CREQ_v_WW(_creqF, _ty1F,_arg1F, _ty2F,_arg2F) \
87 do { \
88 Word _unused_res, _arg1, _arg2; \
89 assert(sizeof(_ty1F) == sizeof(Word)); \
90 assert(sizeof(_ty2F) == sizeof(Word)); \
91 _arg1 = (Word)(_arg1F); \
92 _arg2 = (Word)(_arg2F); \
93 VALGRIND_DO_CLIENT_REQUEST(_unused_res, 0, \
94 (_creqF), \
95 _arg1,_arg2,0,0,0); \
96 } while (0)
97
sewardj1c147ff2009-07-26 19:52:06 +000098#define DO_CREQ_W_WW(_resF, _creqF, _ty1F,_arg1F, _ty2F,_arg2F) \
sewardjb4112022007-11-09 22:49:28 +000099 do { \
100 Word _res, _arg1, _arg2; \
101 assert(sizeof(_ty1F) == sizeof(Word)); \
102 assert(sizeof(_ty2F) == sizeof(Word)); \
103 _arg1 = (Word)(_arg1F); \
104 _arg2 = (Word)(_arg2F); \
105 VALGRIND_DO_CLIENT_REQUEST(_res, 2, \
106 (_creqF), \
107 _arg1,_arg2,0,0,0); \
108 _resF = _res; \
109 } while (0)
110
111#define DO_CREQ_v_WWW(_creqF, _ty1F,_arg1F, \
sewardj1c147ff2009-07-26 19:52:06 +0000112 _ty2F,_arg2F, _ty3F, _arg3F) \
sewardjb4112022007-11-09 22:49:28 +0000113 do { \
114 Word _unused_res, _arg1, _arg2, _arg3; \
115 assert(sizeof(_ty1F) == sizeof(Word)); \
116 assert(sizeof(_ty2F) == sizeof(Word)); \
117 assert(sizeof(_ty3F) == sizeof(Word)); \
118 _arg1 = (Word)(_arg1F); \
119 _arg2 = (Word)(_arg2F); \
120 _arg3 = (Word)(_arg3F); \
121 VALGRIND_DO_CLIENT_REQUEST(_unused_res, 0, \
122 (_creqF), \
123 _arg1,_arg2,_arg3,0,0); \
124 } while (0)
125
126
127#define DO_PthAPIerror(_fnnameF, _errF) \
128 do { \
129 char* _fnname = (char*)(_fnnameF); \
sewardj1c147ff2009-07-26 19:52:06 +0000130 long _err = (long)(int)(_errF); \
sewardjb4112022007-11-09 22:49:28 +0000131 char* _errstr = lame_strerror(_err); \
132 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTH_API_ERROR, \
133 char*,_fnname, \
134 long,_err, char*,_errstr); \
135 } while (0)
136
137
138/* Needed for older glibcs (2.3 and older, at least) who don't
139 otherwise "know" about pthread_rwlock_anything or about
140 PTHREAD_MUTEX_RECURSIVE (amongst things). */
141#define _GNU_SOURCE 1
142
143#include <stdio.h>
144#include <assert.h>
145#include <errno.h>
146#include <pthread.h>
147
148
149/* A lame version of strerror which doesn't use the real libc
150 strerror_r, since using the latter just generates endless more
151 threading errors (glibc goes off and does tons of crap w.r.t.
152 locales etc) */
153static char* lame_strerror ( long err )
154{ switch (err) {
155 case EPERM: return "EPERM: Operation not permitted";
156 case ENOENT: return "ENOENT: No such file or directory";
157 case ESRCH: return "ESRCH: No such process";
158 case EINTR: return "EINTR: Interrupted system call";
159 case EBADF: return "EBADF: Bad file number";
160 case EAGAIN: return "EAGAIN: Try again";
161 case ENOMEM: return "ENOMEM: Out of memory";
162 case EACCES: return "EACCES: Permission denied";
163 case EFAULT: return "EFAULT: Bad address";
164 case EEXIST: return "EEXIST: File exists";
165 case EINVAL: return "EINVAL: Invalid argument";
166 case EMFILE: return "EMFILE: Too many open files";
167 case ENOSYS: return "ENOSYS: Function not implemented";
168 case EOVERFLOW: return "EOVERFLOW: Value too large "
169 "for defined data type";
170 case EBUSY: return "EBUSY: Device or resource busy";
171 case ETIMEDOUT: return "ETIMEDOUT: Connection timed out";
172 case EDEADLK: return "EDEADLK: Resource deadlock would occur";
173 case EOPNOTSUPP: return "EOPNOTSUPP: Operation not supported on "
174 "transport endpoint"; /* honest, guv */
175 default: return "tc_intercepts.c: lame_strerror(): "
176 "unhandled case -- please fix me!";
177 }
178}
179
180
181/*----------------------------------------------------------------*/
182/*--- pthread_create, pthread_join, pthread_exit ---*/
183/*----------------------------------------------------------------*/
184
sewardj0d2a2c12007-11-11 05:58:41 +0000185/* Do not rename this function. It contains an unavoidable race and
186 so is mentioned by name in glibc-*helgrind*.supp. */
sewardjb4112022007-11-09 22:49:28 +0000187static void* mythread_wrapper ( void* xargsV )
188{
bart31277bf2008-07-29 17:04:31 +0000189 volatile Word* xargs = (volatile Word*) xargsV;
sewardjb4112022007-11-09 22:49:28 +0000190 void*(*fn)(void*) = (void*(*)(void*))xargs[0];
191 void* arg = (void*)xargs[1];
192 pthread_t me = pthread_self();
193 /* Tell the tool what my pthread_t is. */
194 DO_CREQ_v_W(_VG_USERREQ__HG_SET_MY_PTHREAD_T, pthread_t,me);
195 /* allow the parent to proceed. We can't let it proceed until
196 we're ready because (1) we need to make sure it doesn't exit and
197 hence deallocate xargs[] while we still need it, and (2) we
198 don't want either parent nor child to proceed until the tool has
199 been notified of the child's pthread_t. */
200 xargs[2] = 0;
201 /* Now we can no longer safely use xargs[]. */
202 return (void*) fn( (void*)arg );
203}
204
sewardj1c147ff2009-07-26 19:52:06 +0000205//-----------------------------------------------------------
206// glibc: pthread_create@GLIBC_2.0
207// glibc: pthread_create@@GLIBC_2.1
208// glibc: pthread_create@@GLIBC_2.2.5
209// darwin: pthread_create
210// darwin: pthread_create_suspended_np (trapped)
njnf76d27a2009-05-28 01:53:07 +0000211//
sewardj28a7f7d2009-07-26 20:15:37 +0000212/* ensure this has its own frame, so as to make it more distinguishable
213 in suppressions */
214__attribute__((noinline))
njnf76d27a2009-05-28 01:53:07 +0000215static int pthread_create_WRK(pthread_t *thread, const pthread_attr_t *attr,
216 void *(*start) (void *), void *arg)
sewardjb4112022007-11-09 22:49:28 +0000217{
218 int ret;
219 OrigFn fn;
220 volatile Word xargs[3];
221
222 VALGRIND_GET_ORIG_FN(fn);
223 if (TRACE_PTH_FNS) {
224 fprintf(stderr, "<< pthread_create wrapper"); fflush(stderr);
225 }
226 xargs[0] = (Word)start;
227 xargs[1] = (Word)arg;
228 xargs[2] = 1; /* serves as a spinlock -- sigh */
229
230 CALL_FN_W_WWWW(ret, fn, thread,attr,mythread_wrapper,&xargs[0]);
231
232 if (ret == 0) {
233 /* we have to wait for the child to notify the tool of its
234 pthread_t before continuing */
235 while (xargs[2] != 0) {
sewardjeafad3b2007-11-18 01:16:52 +0000236 /* Do nothing. We need to spin until the child writes to
237 xargs[2]. However, that can lead to starvation in the
238 child and very long delays (eg, tc19_shadowmem on
239 ppc64-linux Fedora Core 6). So yield the cpu if we can,
240 to let the child run at the earliest available
241 opportunity. */
242 sched_yield();
sewardjb4112022007-11-09 22:49:28 +0000243 }
244 } else {
245 DO_PthAPIerror( "pthread_create", ret );
246 }
247
248 if (TRACE_PTH_FNS) {
249 fprintf(stderr, " :: pth_create -> %d >>\n", ret);
250 }
251 return ret;
252}
sewardj1c147ff2009-07-26 19:52:06 +0000253#if defined(VGO_linux)
254 PTH_FUNC(int, pthreadZucreateZAZa, // pthread_create@*
255 pthread_t *thread, const pthread_attr_t *attr,
256 void *(*start) (void *), void *arg) {
257 return pthread_create_WRK(thread, attr, start, arg);
258 }
259#elif defined(VGO_darwin)
260 PTH_FUNC(int, pthreadZucreate, // pthread_create
261 pthread_t *thread, const pthread_attr_t *attr,
262 void *(*start) (void *), void *arg) {
263 return pthread_create_WRK(thread, attr, start, arg);
264 }
265 PTH_FUNC(int, pthreadZucreateZuZa, // pthread_create_*
266 pthread_t *thread, const pthread_attr_t *attr,
267 void *(*start) (void *), void *arg) {
268 // trap anything else
269 assert(0);
270 }
271#else
272# error "Unsupported OS"
273#endif
sewardjb4112022007-11-09 22:49:28 +0000274
sewardj1c147ff2009-07-26 19:52:06 +0000275
276//-----------------------------------------------------------
277// glibc: pthread_join
278// darwin: pthread_join
279// darwin: pthread_join$NOCANCEL$UNIX2003
280// darwin pthread_join$UNIX2003
281static int pthread_join_WRK(pthread_t thread, void** value_pointer)
sewardjb4112022007-11-09 22:49:28 +0000282{
283 int ret;
284 OrigFn fn;
285 VALGRIND_GET_ORIG_FN(fn);
286 if (TRACE_PTH_FNS) {
287 fprintf(stderr, "<< pthread_join wrapper"); fflush(stderr);
288 }
289
290 CALL_FN_W_WW(ret, fn, thread,value_pointer);
291
292 /* At least with NPTL as the thread library, this is safe because
293 it is guaranteed (by NPTL) that the joiner will completely gone
294 before pthread_join (the original) returns. See email below.*/
295 if (ret == 0 /*success*/) {
296 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_JOIN_POST, pthread_t,thread);
297 } else {
298 DO_PthAPIerror( "pthread_join", ret );
299 }
300
301 if (TRACE_PTH_FNS) {
302 fprintf(stderr, " :: pth_join -> %d >>\n", ret);
303 }
304 return ret;
305}
sewardj1c147ff2009-07-26 19:52:06 +0000306#if defined(VGO_linux)
307 PTH_FUNC(int, pthreadZujoin, // pthread_join
308 pthread_t thread, void** value_pointer) {
309 return pthread_join_WRK(thread, value_pointer);
310 }
311#elif defined(VGO_darwin)
312 PTH_FUNC(int, pthreadZujoinZa, // pthread_join*
313 pthread_t thread, void** value_pointer) {
314 return pthread_join_WRK(thread, value_pointer);
315 }
316#else
317# error "Unsupported OS"
318#endif
319
sewardjb4112022007-11-09 22:49:28 +0000320
321/* Behaviour of pthread_join on NPTL:
322
323Me:
324I have a question re the NPTL pthread_join implementation.
325
326 Suppose I am the thread 'stayer'.
327
328 If I call pthread_join(quitter), is it guaranteed that the
329 thread 'quitter' has really exited before pthread_join returns?
330
331 IOW, is it guaranteed that 'quitter' will not execute any further
332 instructions after pthread_join returns?
333
334I believe this is true based on the following analysis of
335glibc-2.5 sources. However am not 100% sure and would appreciate
336confirmation.
337
338 'quitter' will be running start_thread() in nptl/pthread_create.c
339
340 The last action of start_thread() is to exit via
341 __exit_thread_inline(0), which simply does sys_exit
342 (nptl/pthread_create.c:403)
343
344 'stayer' meanwhile is waiting for lll_wait_tid (pd->tid)
345 (call at nptl/pthread_join.c:89)
346
347 As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536,
348 lll_wait_tid will not return until kernel notifies via futex
349 wakeup that 'quitter' has terminated.
350
351 Hence pthread_join cannot return until 'quitter' really has
352 completely disappeared.
353
354Drepper:
355> As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536,
356> lll_wait_tid will not return until kernel notifies via futex
357> wakeup that 'quitter' has terminated.
358That's the key. The kernel resets the TID field after the thread is
359done. No way the joiner can return before the thread is gone.
360*/
361
362
363/*----------------------------------------------------------------*/
364/*--- pthread_mutex_t functions ---*/
365/*----------------------------------------------------------------*/
366
367/* Handled: pthread_mutex_init pthread_mutex_destroy
368 pthread_mutex_lock
369 pthread_mutex_trylock pthread_mutex_timedlock
370 pthread_mutex_unlock
sewardjb4112022007-11-09 22:49:28 +0000371*/
372
sewardj1c147ff2009-07-26 19:52:06 +0000373//-----------------------------------------------------------
374// glibc: pthread_mutex_init
375// darwin: pthread_mutex_init
sewardjb4112022007-11-09 22:49:28 +0000376PTH_FUNC(int, pthreadZumutexZuinit, // pthread_mutex_init
377 pthread_mutex_t *mutex,
378 pthread_mutexattr_t* attr)
379{
380 int ret;
381 long mbRec;
382 OrigFn fn;
383 VALGRIND_GET_ORIG_FN(fn);
384 if (TRACE_PTH_FNS) {
385 fprintf(stderr, "<< pthread_mxinit %p", mutex); fflush(stderr);
386 }
387
388 mbRec = 0;
389 if (attr) {
390 int ty, zzz;
391 zzz = pthread_mutexattr_gettype(attr, &ty);
392 if (zzz == 0 && ty == PTHREAD_MUTEX_RECURSIVE)
393 mbRec = 1;
394 }
395
396 CALL_FN_W_WW(ret, fn, mutex,attr);
397
398 if (ret == 0 /*success*/) {
399 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST,
400 pthread_mutex_t*,mutex, long,mbRec);
401 } else {
402 DO_PthAPIerror( "pthread_mutex_init", ret );
403 }
404
405 if (TRACE_PTH_FNS) {
406 fprintf(stderr, " :: mxinit -> %d >>\n", ret);
407 }
408 return ret;
409}
410
411
sewardj1c147ff2009-07-26 19:52:06 +0000412//-----------------------------------------------------------
413// glibc: pthread_mutex_destroy
414// darwin: pthread_mutex_destroy
sewardjb4112022007-11-09 22:49:28 +0000415PTH_FUNC(int, pthreadZumutexZudestroy, // pthread_mutex_destroy
416 pthread_mutex_t *mutex)
417{
418 int ret;
419 OrigFn fn;
420 VALGRIND_GET_ORIG_FN(fn);
421 if (TRACE_PTH_FNS) {
422 fprintf(stderr, "<< pthread_mxdestroy %p", mutex); fflush(stderr);
423 }
424
425 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE,
426 pthread_mutex_t*,mutex);
427
428 CALL_FN_W_W(ret, fn, mutex);
429
430 if (ret != 0) {
431 DO_PthAPIerror( "pthread_mutex_destroy", ret );
432 }
433
434 if (TRACE_PTH_FNS) {
435 fprintf(stderr, " :: mxdestroy -> %d >>\n", ret);
436 }
437 return ret;
438}
439
440
sewardj1c147ff2009-07-26 19:52:06 +0000441//-----------------------------------------------------------
442// glibc: pthread_mutex_lock
443// darwin: pthread_mutex_lock
sewardjb4112022007-11-09 22:49:28 +0000444PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock
445 pthread_mutex_t *mutex)
446{
447 int ret;
448 OrigFn fn;
449 VALGRIND_GET_ORIG_FN(fn);
450 if (TRACE_PTH_FNS) {
451 fprintf(stderr, "<< pthread_mxlock %p", mutex); fflush(stderr);
452 }
453
454 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
455 pthread_mutex_t*,mutex, long,0/*!isTryLock*/);
456
457 CALL_FN_W_W(ret, fn, mutex);
458
459 /* There's a hole here: libpthread now knows the lock is locked,
460 but the tool doesn't, so some other thread could run and detect
461 that the lock has been acquired by someone (this thread). Does
462 this matter? Not sure, but I don't think so. */
463
464 if (ret == 0 /*success*/) {
465 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
466 pthread_mutex_t*,mutex);
467 } else {
468 DO_PthAPIerror( "pthread_mutex_lock", ret );
469 }
470
471 if (TRACE_PTH_FNS) {
472 fprintf(stderr, " :: mxlock -> %d >>\n", ret);
473 }
474 return ret;
475}
476
477
sewardj1c147ff2009-07-26 19:52:06 +0000478//-----------------------------------------------------------
479// glibc: pthread_mutex_trylock
480// darwin: pthread_mutex_trylock
481//
sewardjb4112022007-11-09 22:49:28 +0000482// pthread_mutex_trylock. The handling needed here is very similar
483// to that for pthread_mutex_lock, except that we need to tell
484// the pre-lock creq that this is a trylock-style operation, and
485// therefore not to complain if the lock is nonrecursive and
486// already locked by this thread -- because then it'll just fail
487// immediately with EBUSY.
488PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock
489 pthread_mutex_t *mutex)
490{
491 int ret;
492 OrigFn fn;
493 VALGRIND_GET_ORIG_FN(fn);
494 if (TRACE_PTH_FNS) {
495 fprintf(stderr, "<< pthread_mxtrylock %p", mutex); fflush(stderr);
496 }
497
498 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
499 pthread_mutex_t*,mutex, long,1/*isTryLock*/);
500
501 CALL_FN_W_W(ret, fn, mutex);
502
503 /* There's a hole here: libpthread now knows the lock is locked,
504 but the tool doesn't, so some other thread could run and detect
505 that the lock has been acquired by someone (this thread). Does
506 this matter? Not sure, but I don't think so. */
507
508 if (ret == 0 /*success*/) {
509 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
510 pthread_mutex_t*,mutex);
511 } else {
512 if (ret != EBUSY)
513 DO_PthAPIerror( "pthread_mutex_trylock", ret );
514 }
515
516 if (TRACE_PTH_FNS) {
517 fprintf(stderr, " :: mxtrylock -> %d >>\n", ret);
518 }
519 return ret;
520}
521
522
sewardj1c147ff2009-07-26 19:52:06 +0000523//-----------------------------------------------------------
524// glibc: pthread_mutex_timedlock
525// darwin: (doesn't appear to exist)
526//
sewardjb4112022007-11-09 22:49:28 +0000527// pthread_mutex_timedlock. Identical logic to pthread_mutex_trylock.
528PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock
sewardj1c147ff2009-07-26 19:52:06 +0000529 pthread_mutex_t *mutex,
sewardjb4112022007-11-09 22:49:28 +0000530 void* timeout)
531{
532 int ret;
533 OrigFn fn;
534 VALGRIND_GET_ORIG_FN(fn);
535 if (TRACE_PTH_FNS) {
536 fprintf(stderr, "<< pthread_mxtimedlock %p %p", mutex, timeout);
537 fflush(stderr);
538 }
539
540 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
541 pthread_mutex_t*,mutex, long,1/*isTryLock-ish*/);
542
543 CALL_FN_W_WW(ret, fn, mutex,timeout);
544
545 /* There's a hole here: libpthread now knows the lock is locked,
546 but the tool doesn't, so some other thread could run and detect
547 that the lock has been acquired by someone (this thread). Does
548 this matter? Not sure, but I don't think so. */
549
550 if (ret == 0 /*success*/) {
551 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
552 pthread_mutex_t*,mutex);
553 } else {
554 if (ret != ETIMEDOUT)
555 DO_PthAPIerror( "pthread_mutex_timedlock", ret );
556 }
557
558 if (TRACE_PTH_FNS) {
559 fprintf(stderr, " :: mxtimedlock -> %d >>\n", ret);
560 }
561 return ret;
562}
563
564
sewardj1c147ff2009-07-26 19:52:06 +0000565//-----------------------------------------------------------
566// glibc: pthread_mutex_unlock
567// darwin: pthread_mutex_unlock
sewardjb4112022007-11-09 22:49:28 +0000568PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock
569 pthread_mutex_t *mutex)
570{
571 int ret;
572 OrigFn fn;
573 VALGRIND_GET_ORIG_FN(fn);
574
575 if (TRACE_PTH_FNS) {
576 fprintf(stderr, "<< pthread_mxunlk %p", mutex); fflush(stderr);
577 }
578
579 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
580 pthread_mutex_t*,mutex);
581
582 CALL_FN_W_W(ret, fn, mutex);
583
584 if (ret == 0 /*success*/) {
585 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST,
586 pthread_mutex_t*,mutex);
587 } else {
588 DO_PthAPIerror( "pthread_mutex_unlock", ret );
589 }
590
591 if (TRACE_PTH_FNS) {
592 fprintf(stderr, " mxunlk -> %d >>\n", ret);
593 }
594 return ret;
595}
596
597
598/*----------------------------------------------------------------*/
599/*--- pthread_cond_t functions ---*/
600/*----------------------------------------------------------------*/
601
602/* Handled: pthread_cond_wait pthread_cond_timedwait
603 pthread_cond_signal pthread_cond_broadcast
sewardjf98e1c02008-10-25 16:22:41 +0000604 pthread_cond_destroy
sewardjb4112022007-11-09 22:49:28 +0000605
sewardjf98e1c02008-10-25 16:22:41 +0000606 Unhandled: pthread_cond_init
607 -- is this important?
sewardjb4112022007-11-09 22:49:28 +0000608*/
609
sewardj1c147ff2009-07-26 19:52:06 +0000610//-----------------------------------------------------------
611// glibc: pthread_cond_wait@GLIBC_2.2.5
612// glibc: pthread_cond_wait@@GLIBC_2.3.2
613// darwin: pthread_cond_wait
614// darwin: pthread_cond_wait$NOCANCEL$UNIX2003
615// darwin: pthread_cond_wait$UNIX2003
616//
617static int pthread_cond_wait_WRK(pthread_cond_t* cond,
618 pthread_mutex_t* mutex)
sewardjb4112022007-11-09 22:49:28 +0000619{
620 int ret;
621 OrigFn fn;
622 unsigned long mutex_is_valid;
623
624 VALGRIND_GET_ORIG_FN(fn);
625
626 if (TRACE_PTH_FNS) {
627 fprintf(stderr, "<< pthread_cond_wait %p %p", cond, mutex);
628 fflush(stderr);
629 }
630
631 /* Tell the tool a cond-wait is about to happen, so it can check
632 for bogus argument values. In return it tells us whether it
633 thinks the mutex is valid or not. */
634 DO_CREQ_W_WW(mutex_is_valid,
635 _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE,
636 pthread_cond_t*,cond, pthread_mutex_t*,mutex);
637 assert(mutex_is_valid == 1 || mutex_is_valid == 0);
638
639 /* Tell the tool we're about to drop the mutex. This reflects the
640 fact that in a cond_wait, we show up holding the mutex, and the
641 call atomically drops the mutex and waits for the cv to be
642 signalled. */
643 if (mutex_is_valid) {
644 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
645 pthread_mutex_t*,mutex);
646 }
647
648 CALL_FN_W_WW(ret, fn, cond,mutex);
649
650 /* these conditionals look stupid, but compare w/ same logic for
651 pthread_cond_timedwait below */
652 if (ret == 0 && mutex_is_valid) {
653 /* and now we have the mutex again */
654 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
655 pthread_mutex_t*,mutex);
656 }
657
658 if (ret == 0 && mutex_is_valid) {
659 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST,
660 pthread_cond_t*,cond, pthread_mutex_t*,mutex);
661 }
662
663 if (ret != 0) {
664 DO_PthAPIerror( "pthread_cond_wait", ret );
665 }
666
667 if (TRACE_PTH_FNS) {
668 fprintf(stderr, " cowait -> %d >>\n", ret);
669 }
670
671 return ret;
672}
sewardj1c147ff2009-07-26 19:52:06 +0000673#if defined(VGO_linux)
674 PTH_FUNC(int, pthreadZucondZuwaitZAZa, // pthread_cond_wait@*
675 pthread_cond_t* cond, pthread_mutex_t* mutex) {
676 return pthread_cond_wait_WRK(cond, mutex);
677 }
678#elif defined(VGO_darwin)
679 PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait*
680 pthread_cond_t* cond, pthread_mutex_t* mutex) {
681 return pthread_cond_wait_WRK(cond, mutex);
682 }
683#else
684# error "Unsupported OS"
685#endif
sewardjb4112022007-11-09 22:49:28 +0000686
687
sewardj1c147ff2009-07-26 19:52:06 +0000688//-----------------------------------------------------------
689// glibc: pthread_cond_timedwait@@GLIBC_2.3.2
690// glibc: pthread_cond_timedwait@GLIBC_2.2.5
691// glibc: pthread_cond_timedwait@GLIBC_2.0
692// darwin: pthread_cond_timedwait
693// darwin: pthread_cond_timedwait$NOCANCEL$UNIX2003
694// darwin: pthread_cond_timedwait$UNIX2003
695// darwin: pthread_cond_timedwait_relative_np (trapped)
696//
697static int pthread_cond_timedwait_WRK(pthread_cond_t* cond,
698 pthread_mutex_t* mutex,
699 struct timespec* abstime)
sewardjb4112022007-11-09 22:49:28 +0000700{
701 int ret;
702 OrigFn fn;
703 unsigned long mutex_is_valid;
704 VALGRIND_GET_ORIG_FN(fn);
705
706 if (TRACE_PTH_FNS) {
707 fprintf(stderr, "<< pthread_cond_timedwait %p %p %p",
708 cond, mutex, abstime);
709 fflush(stderr);
710 }
711
712 /* Tell the tool a cond-wait is about to happen, so it can check
713 for bogus argument values. In return it tells us whether it
714 thinks the mutex is valid or not. */
715 DO_CREQ_W_WW(mutex_is_valid,
716 _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE,
717 pthread_cond_t*,cond, pthread_mutex_t*,mutex);
718 assert(mutex_is_valid == 1 || mutex_is_valid == 0);
719
720 /* Tell the tool we're about to drop the mutex. This reflects the
721 fact that in a cond_wait, we show up holding the mutex, and the
722 call atomically drops the mutex and waits for the cv to be
723 signalled. */
724 if (mutex_is_valid) {
725 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
726 pthread_mutex_t*,mutex);
727 }
728
729 CALL_FN_W_WWW(ret, fn, cond,mutex,abstime);
730
731 if ((ret == 0 || ret == ETIMEDOUT) && mutex_is_valid) {
732 /* and now we have the mutex again */
733 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
734 pthread_mutex_t*,mutex);
735 }
736
737 if (ret == 0 && mutex_is_valid) {
738 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST,
739 pthread_cond_t*,cond, pthread_mutex_t*,mutex);
740 }
741
742 if (ret != 0 && ret != ETIMEDOUT) {
743 DO_PthAPIerror( "pthread_cond_timedwait", ret );
744 }
745
746 if (TRACE_PTH_FNS) {
747 fprintf(stderr, " cotimedwait -> %d >>\n", ret);
748 }
749
750 return ret;
751}
sewardj1c147ff2009-07-26 19:52:06 +0000752#if defined(VGO_linux)
753 PTH_FUNC(int, pthreadZucondZutimedwaitZAZa, // pthread_cond_timedwait@*
754 pthread_cond_t* cond, pthread_mutex_t* mutex,
755 struct timespec* abstime) {
756 return pthread_cond_timedwait_WRK(cond, mutex, abstime);
757 }
758#elif defined(VGO_darwin)
759 PTH_FUNC(int, pthreadZucondZutimedwait, // pthread_cond_timedwait
760 pthread_cond_t* cond, pthread_mutex_t* mutex,
761 struct timespec* abstime) {
762 return pthread_cond_timedwait_WRK(cond, mutex, abstime);
763 }
764 PTH_FUNC(int, pthreadZucondZutimedwaitZDZa, // 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 PTH_FUNC(int, pthreadZucondZutimedwaitZuZa, // pthread_cond_timedwait_*
770 pthread_cond_t* cond, pthread_mutex_t* mutex,
771 struct timespec* abstime) {
772 assert(0);
773 }
774#else
775# error "Unsupported OS"
776#endif
sewardjb4112022007-11-09 22:49:28 +0000777
778
sewardj1c147ff2009-07-26 19:52:06 +0000779//-----------------------------------------------------------
780// glibc: pthread_cond_signal@GLIBC_2.0
781// glibc: pthread_cond_signal@GLIBC_2.2.5
782// glibc: pthread_cond_signal@@GLIBC_2.3.2
783// darwin: pthread_cond_signal
784// darwin: pthread_cond_signal_thread_np (don't intercept this)
785//
786static int pthread_cond_signal_WRK(pthread_cond_t* cond)
sewardjb4112022007-11-09 22:49:28 +0000787{
788 int ret;
789 OrigFn fn;
790 VALGRIND_GET_ORIG_FN(fn);
791
792 if (TRACE_PTH_FNS) {
793 fprintf(stderr, "<< pthread_cond_signal %p", cond);
794 fflush(stderr);
795 }
796
797 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_SIGNAL_PRE,
798 pthread_cond_t*,cond);
799
800 CALL_FN_W_W(ret, fn, cond);
801
802 if (ret != 0) {
803 DO_PthAPIerror( "pthread_cond_signal", ret );
804 }
805
806 if (TRACE_PTH_FNS) {
807 fprintf(stderr, " cosig -> %d >>\n", ret);
808 }
809
810 return ret;
811}
sewardj1c147ff2009-07-26 19:52:06 +0000812#if defined(VGO_linux)
813 PTH_FUNC(int, pthreadZucondZusignalZAZa, // pthread_cond_signal@*
814 pthread_cond_t* cond) {
815 return pthread_cond_signal_WRK(cond);
816 }
817#elif defined(VGO_darwin)
818 PTH_FUNC(int, pthreadZucondZusignal, // pthread_cond_signal
819 pthread_cond_t* cond) {
820 return pthread_cond_signal_WRK(cond);
821 }
822#else
823# error "Unsupported OS"
824#endif
sewardjb4112022007-11-09 22:49:28 +0000825
826
sewardj1c147ff2009-07-26 19:52:06 +0000827//-----------------------------------------------------------
828// glibc: pthread_cond_broadcast@GLIBC_2.0
829// glibc: pthread_cond_broadcast@GLIBC_2.2.5
830// glibc: pthread_cond_broadcast@@GLIBC_2.3.2
831// darwin: pthread_cond_broadcast
832//
sewardjb4112022007-11-09 22:49:28 +0000833// Note, this is pretty much identical, from a dependency-graph
834// point of view, with cond_signal, so the code is duplicated.
835// Maybe it should be commoned up.
sewardj1c147ff2009-07-26 19:52:06 +0000836//
837static int pthread_cond_broadcast_WRK(pthread_cond_t* cond)
sewardjb4112022007-11-09 22:49:28 +0000838{
839 int ret;
840 OrigFn fn;
841 VALGRIND_GET_ORIG_FN(fn);
842
843 if (TRACE_PTH_FNS) {
sewardj1c147ff2009-07-26 19:52:06 +0000844 fprintf(stderr, "<< pthread_cond_broadcast %p", cond);
sewardjb4112022007-11-09 22:49:28 +0000845 fflush(stderr);
846 }
847
848 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_BROADCAST_PRE,
849 pthread_cond_t*,cond);
850
851 CALL_FN_W_W(ret, fn, cond);
852
853 if (ret != 0) {
854 DO_PthAPIerror( "pthread_cond_broadcast", ret );
855 }
856
857 if (TRACE_PTH_FNS) {
858 fprintf(stderr, " cobro -> %d >>\n", ret);
859 }
860
861 return ret;
862}
sewardj1c147ff2009-07-26 19:52:06 +0000863#if defined(VGO_linux)
864 PTH_FUNC(int, pthreadZucondZubroadcastZAZa, // pthread_cond_broadcast@*
865 pthread_cond_t* cond) {
866 return pthread_cond_broadcast_WRK(cond);
867 }
868#elif defined(VGO_darwin)
869 PTH_FUNC(int, pthreadZucondZubroadcast, // pthread_cond_broadcast
870 pthread_cond_t* cond) {
871 return pthread_cond_broadcast_WRK(cond);
872 }
873#else
874# error "Unsupported OS"
875#endif
sewardjb4112022007-11-09 22:49:28 +0000876
877
sewardj1c147ff2009-07-26 19:52:06 +0000878//-----------------------------------------------------------
879// glibc: pthread_cond_destroy@@GLIBC_2.3.2
880// glibc: pthread_cond_destroy@GLIBC_2.2.5
881// glibc: pthread_cond_destroy@GLIBC_2.0
882// darwin: pthread_cond_destroy
883//
884static int pthread_cond_destroy_WRK(pthread_cond_t* cond)
sewardjf98e1c02008-10-25 16:22:41 +0000885{
886 int ret;
887 OrigFn fn;
888
889 VALGRIND_GET_ORIG_FN(fn);
890
891 if (TRACE_PTH_FNS) {
892 fprintf(stderr, "<< pthread_cond_destroy %p", cond);
893 fflush(stderr);
894 }
895
896 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_DESTROY_PRE,
897 pthread_cond_t*,cond);
898
899 CALL_FN_W_W(ret, fn, cond);
900
901 if (ret != 0) {
902 DO_PthAPIerror( "pthread_cond_destroy", ret );
903 }
904
905 if (TRACE_PTH_FNS) {
906 fprintf(stderr, " codestr -> %d >>\n", ret);
907 }
908
909 return ret;
910}
sewardj1c147ff2009-07-26 19:52:06 +0000911#if defined(VGO_linux)
912 PTH_FUNC(int, pthreadZucondZudestroyZAZa, // pthread_cond_destroy@*
913 pthread_cond_t* cond) {
914 return pthread_cond_destroy_WRK(cond);
915 }
916#elif defined(VGO_darwin)
917 PTH_FUNC(int, pthreadZucondZudestroy, // pthread_cond_destroy
918 pthread_cond_t* cond) {
919 return pthread_cond_destroy_WRK(cond);
920 }
921#else
922# error "Unsupported OS"
923#endif
sewardjf98e1c02008-10-25 16:22:41 +0000924
925
926/*----------------------------------------------------------------*/
927/*--- pthread_barrier_t functions ---*/
928/*----------------------------------------------------------------*/
929
njnf76d27a2009-05-28 01:53:07 +0000930#if defined(HAVE_PTHREAD_BARRIER_INIT)
931
sewardj9f569b72008-11-13 13:33:09 +0000932/* Handled: pthread_barrier_init
933 pthread_barrier_wait
934 pthread_barrier_destroy
935
936 Unhandled: pthread_barrierattr_destroy
937 pthread_barrierattr_getpshared
938 pthread_barrierattr_init
939 pthread_barrierattr_setpshared
940 -- are these important?
941*/
942
sewardj1c147ff2009-07-26 19:52:06 +0000943//-----------------------------------------------------------
944// glibc: pthread_barrier_init
945// darwin: (doesn't appear to exist)
sewardj9f569b72008-11-13 13:33:09 +0000946PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init
947 pthread_barrier_t* bar,
948 pthread_barrierattr_t* attr, unsigned long count)
sewardjf98e1c02008-10-25 16:22:41 +0000949{
950 int ret;
951 OrigFn fn;
952 VALGRIND_GET_ORIG_FN(fn);
953
954 if (TRACE_PTH_FNS) {
sewardj9f569b72008-11-13 13:33:09 +0000955 fprintf(stderr, "<< pthread_barrier_init %p %p %lu",
956 bar, attr, count);
sewardjf98e1c02008-10-25 16:22:41 +0000957 fflush(stderr);
958 }
959
sewardj9f569b72008-11-13 13:33:09 +0000960 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_BARRIER_INIT_PRE,
961 pthread_barrier_t*,bar,
962 unsigned long,count);
sewardjf98e1c02008-10-25 16:22:41 +0000963
sewardj9f569b72008-11-13 13:33:09 +0000964 CALL_FN_W_WWW(ret, fn, bar,attr,count);
sewardjf98e1c02008-10-25 16:22:41 +0000965
sewardj9f569b72008-11-13 13:33:09 +0000966 if (ret != 0) {
967 DO_PthAPIerror( "pthread_barrier_init", ret );
968 }
969
970 if (TRACE_PTH_FNS) {
971 fprintf(stderr, " pthread_barrier_init -> %d >>\n", ret);
972 }
973
974 return ret;
975}
976
977
sewardj1c147ff2009-07-26 19:52:06 +0000978//-----------------------------------------------------------
979// glibc: pthread_barrier_wait
980// darwin: (doesn't appear to exist)
sewardj9f569b72008-11-13 13:33:09 +0000981PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait
982 pthread_barrier_t* bar)
983{
984 int ret;
985 OrigFn fn;
986 VALGRIND_GET_ORIG_FN(fn);
987
988 if (TRACE_PTH_FNS) {
989 fprintf(stderr, "<< pthread_barrier_wait %p", bar);
990 fflush(stderr);
991 }
992
993 /* That this works correctly, and doesn't screw up when a thread
994 leaving the barrier races round to the front and re-enters while
995 other threads are still leaving it, is quite subtle. See
996 comments in the handler for PTHREAD_BARRIER_WAIT_PRE in
997 hg_main.c. */
998 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_WAIT_PRE,
999 pthread_barrier_t*,bar);
1000
1001 CALL_FN_W_W(ret, fn, bar);
1002
1003 if (ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
1004 DO_PthAPIerror( "pthread_barrier_wait", ret );
1005 }
sewardjf98e1c02008-10-25 16:22:41 +00001006
1007 if (TRACE_PTH_FNS) {
1008 fprintf(stderr, " pthread_barrier_wait -> %d >>\n", ret);
1009 }
1010
1011 return ret;
1012}
1013
1014
sewardj1c147ff2009-07-26 19:52:06 +00001015//-----------------------------------------------------------
1016// glibc: pthread_barrier_destroy
1017// darwin: (doesn't appear to exist)
sewardj9f569b72008-11-13 13:33:09 +00001018PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy
1019 pthread_barrier_t* bar)
1020{
1021 int ret;
1022 OrigFn fn;
1023 VALGRIND_GET_ORIG_FN(fn);
1024
1025 if (TRACE_PTH_FNS) {
1026 fprintf(stderr, "<< pthread_barrier_destroy %p", bar);
1027 fflush(stderr);
1028 }
1029
1030 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_DESTROY_PRE,
1031 pthread_barrier_t*,bar);
1032
1033 CALL_FN_W_W(ret, fn, bar);
1034
1035 if (ret != 0) {
1036 DO_PthAPIerror( "pthread_barrier_destroy", ret );
1037 }
1038
1039 if (TRACE_PTH_FNS) {
1040 fprintf(stderr, " pthread_barrier_destroy -> %d >>\n", ret);
1041 }
1042
1043 return ret;
1044}
sewardjf98e1c02008-10-25 16:22:41 +00001045
njnf76d27a2009-05-28 01:53:07 +00001046#endif // defined(HAVE_PTHREAD_BARRIER_INIT)
1047
sewardj5a644da2009-08-11 10:35:58 +00001048
1049/*----------------------------------------------------------------*/
1050/*--- pthread_spinlock_t functions ---*/
1051/*----------------------------------------------------------------*/
1052
1053#if defined(HAVE_PTHREAD_SPIN_LOCK)
1054
1055/* Handled: pthread_spin_init pthread_spin_destroy
1056 pthread_spin_lock pthread_spin_trylock
1057 pthread_spin_unlock
1058
1059 Unhandled:
1060*/
1061
1062/* This is a nasty kludge, in that glibc "knows" that initialising a
1063 spin lock unlocks it, and pthread_spin_{init,unlock} are names for
1064 the same function. Hence we have to have a wrapper which does both
1065 things, without knowing which the user intended to happen. */
1066
1067//-----------------------------------------------------------
1068// glibc: pthread_spin_init
1069// glibc: pthread_spin_unlock
1070// darwin: (doesn't appear to exist)
1071static int pthread_spin_init_or_unlock_WRK(pthread_spinlock_t* lock,
1072 int pshared) {
1073 int ret;
1074 OrigFn fn;
1075 VALGRIND_GET_ORIG_FN(fn);
1076 if (TRACE_PTH_FNS) {
1077 fprintf(stderr, "<< pthread_spin_iORu %p", lock); fflush(stderr);
1078 }
1079
1080 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_PRE,
1081 pthread_spinlock_t*, lock);
1082
1083 CALL_FN_W_WW(ret, fn, lock,pshared);
1084
1085 if (ret == 0 /*success*/) {
1086 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST,
1087 pthread_spinlock_t*,lock);
1088 } else {
1089 DO_PthAPIerror( "pthread_spinlock_{init,unlock}", ret );
1090 }
1091
1092 if (TRACE_PTH_FNS) {
1093 fprintf(stderr, " :: spiniORu -> %d >>\n", ret);
1094 }
1095 return ret;
1096}
1097#if defined(VGO_linux)
1098 PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init
1099 pthread_spinlock_t* lock, int pshared) {
1100 return pthread_spin_init_or_unlock_WRK(lock, pshared);
1101 }
1102 PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock
1103 pthread_spinlock_t* lock) {
1104 /* this is never actually called */
1105 return pthread_spin_init_or_unlock_WRK(lock, 0/*pshared*/);
1106 }
1107#elif defined(VGO_darwin)
1108#else
1109# error "Unsupported OS"
1110#endif
1111
1112
1113//-----------------------------------------------------------
1114// glibc: pthread_spin_destroy
1115// darwin: (doesn't appear to exist)
1116#if defined(VGO_linux)
1117
1118PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy
1119 pthread_spinlock_t* lock)
1120{
1121 int ret;
1122 OrigFn fn;
1123 VALGRIND_GET_ORIG_FN(fn);
1124 if (TRACE_PTH_FNS) {
1125 fprintf(stderr, "<< pthread_spin_destroy %p", lock);
1126 fflush(stderr);
1127 }
1128
1129 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_DESTROY_PRE,
1130 pthread_spinlock_t*,lock);
1131
1132 CALL_FN_W_W(ret, fn, lock);
1133
1134 if (ret != 0) {
1135 DO_PthAPIerror( "pthread_spin_destroy", ret );
1136 }
1137
1138 if (TRACE_PTH_FNS) {
1139 fprintf(stderr, " :: spindestroy -> %d >>\n", ret);
1140 }
1141 return ret;
1142}
1143
1144#elif defined(VGO_darwin)
1145#else
1146# error "Unsupported OS"
1147#endif
1148
1149
1150//-----------------------------------------------------------
1151// glibc: pthread_spin_lock
1152// darwin: (doesn't appear to exist)
1153#if defined(VGO_linux)
1154
1155PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock
1156 pthread_spinlock_t* lock)
1157{
1158 int ret;
1159 OrigFn fn;
1160 VALGRIND_GET_ORIG_FN(fn);
1161 if (TRACE_PTH_FNS) {
1162 fprintf(stderr, "<< pthread_spinlock %p", lock);
1163 fflush(stderr);
1164 }
1165
1166 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE,
1167 pthread_spinlock_t*,lock, long,0/*!isTryLock*/);
1168
1169 CALL_FN_W_W(ret, fn, lock);
1170
1171 /* There's a hole here: libpthread now knows the lock is locked,
1172 but the tool doesn't, so some other thread could run and detect
1173 that the lock has been acquired by someone (this thread). Does
1174 this matter? Not sure, but I don't think so. */
1175
1176 if (ret == 0 /*success*/) {
1177 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST,
1178 pthread_spinlock_t*,lock);
1179 } else {
1180 DO_PthAPIerror( "pthread_spin_lock", ret );
1181 }
1182
1183 if (TRACE_PTH_FNS) {
1184 fprintf(stderr, " :: spinlock -> %d >>\n", ret);
1185 }
1186 return ret;
1187}
1188
1189#elif defined(VGO_darwin)
1190#else
1191# error "Unsupported OS"
1192#endif
1193
1194
1195//-----------------------------------------------------------
1196// glibc: pthread_spin_trylock
1197// darwin: (doesn't appear to exist)
1198#if defined(VGO_linux)
1199
1200PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock
1201 pthread_spinlock_t* lock)
1202{
1203 int ret;
1204 OrigFn fn;
1205 VALGRIND_GET_ORIG_FN(fn);
1206 if (TRACE_PTH_FNS) {
1207 fprintf(stderr, "<< pthread_spin_trylock %p", lock);
1208 fflush(stderr);
1209 }
1210
1211 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE,
1212 pthread_spinlock_t*,lock, long,1/*isTryLock*/);
1213
1214 CALL_FN_W_W(ret, fn, lock);
1215
1216 /* There's a hole here: libpthread now knows the lock is locked,
1217 but the tool doesn't, so some other thread could run and detect
1218 that the lock has been acquired by someone (this thread). Does
1219 this matter? Not sure, but I don't think so. */
1220
1221 if (ret == 0 /*success*/) {
1222 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST,
1223 pthread_spinlock_t*,lock);
1224 } else {
1225 if (ret != EBUSY)
1226 DO_PthAPIerror( "pthread_spin_trylock", ret );
1227 }
1228
1229 if (TRACE_PTH_FNS) {
1230 fprintf(stderr, " :: spin_trylock -> %d >>\n", ret);
1231 }
1232 return ret;
1233}
1234
1235#elif defined(VGO_darwin)
1236#else
1237# error "Unsupported OS"
1238#endif
1239
1240#endif // defined(HAVE_PTHREAD_SPIN_LOCK)
1241
1242
sewardjb4112022007-11-09 22:49:28 +00001243/*----------------------------------------------------------------*/
1244/*--- pthread_rwlock_t functions ---*/
1245/*----------------------------------------------------------------*/
1246
1247/* Handled: pthread_rwlock_init pthread_rwlock_destroy
1248 pthread_rwlock_rdlock
1249 pthread_rwlock_wrlock
1250 pthread_rwlock_unlock
1251
1252 Unhandled: pthread_rwlock_timedrdlock
1253 pthread_rwlock_tryrdlock
1254
1255 pthread_rwlock_timedwrlock
1256 pthread_rwlock_trywrlock
1257*/
1258
sewardj1c147ff2009-07-26 19:52:06 +00001259//-----------------------------------------------------------
1260// glibc: pthread_rwlock_init
1261// darwin: pthread_rwlock_init
1262// darwin: pthread_rwlock_init$UNIX2003
1263static int pthread_rwlock_init_WRK(pthread_rwlock_t *rwl,
1264 pthread_rwlockattr_t* attr)
sewardjb4112022007-11-09 22:49:28 +00001265{
1266 int ret;
1267 OrigFn fn;
1268 VALGRIND_GET_ORIG_FN(fn);
1269 if (TRACE_PTH_FNS) {
1270 fprintf(stderr, "<< pthread_rwl_init %p", rwl); fflush(stderr);
1271 }
1272
1273 CALL_FN_W_WW(ret, fn, rwl,attr);
1274
1275 if (ret == 0 /*success*/) {
1276 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST,
1277 pthread_rwlock_t*,rwl);
1278 } else {
1279 DO_PthAPIerror( "pthread_rwlock_init", ret );
1280 }
1281
1282 if (TRACE_PTH_FNS) {
1283 fprintf(stderr, " :: rwl_init -> %d >>\n", ret);
1284 }
1285 return ret;
1286}
sewardj1c147ff2009-07-26 19:52:06 +00001287#if defined(VGO_linux)
1288 PTH_FUNC(int, pthreadZurwlockZuinit, // pthread_rwlock_init
1289 pthread_rwlock_t *rwl,
1290 pthread_rwlockattr_t* attr) {
1291 return pthread_rwlock_init_WRK(rwl, attr);
1292 }
1293#elif defined(VGO_darwin)
1294 PTH_FUNC(int, pthreadZurwlockZuinitZa, // pthread_rwlock_init*
1295 pthread_rwlock_t *rwl,
1296 pthread_rwlockattr_t* attr) {
1297 return pthread_rwlock_init_WRK(rwl, attr);
1298 }
1299#else
1300# error "Unsupported OS"
1301#endif
sewardjb4112022007-11-09 22:49:28 +00001302
1303
sewardj1c147ff2009-07-26 19:52:06 +00001304//-----------------------------------------------------------
1305// glibc: pthread_rwlock_destroy
1306// darwin: pthread_rwlock_destroy
1307// darwin: pthread_rwlock_destroy$UNIX2003
1308//
1309static int pthread_rwlock_destroy_WRK(pthread_rwlock_t* rwl)
sewardjb4112022007-11-09 22:49:28 +00001310{
1311 int ret;
1312 OrigFn fn;
1313 VALGRIND_GET_ORIG_FN(fn);
1314 if (TRACE_PTH_FNS) {
1315 fprintf(stderr, "<< pthread_rwl_destroy %p", rwl); fflush(stderr);
1316 }
1317
1318 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE,
1319 pthread_rwlock_t*,rwl);
1320
1321 CALL_FN_W_W(ret, fn, rwl);
1322
1323 if (ret != 0) {
1324 DO_PthAPIerror( "pthread_rwlock_destroy", ret );
1325 }
1326
1327 if (TRACE_PTH_FNS) {
1328 fprintf(stderr, " :: rwl_destroy -> %d >>\n", ret);
1329 }
1330 return ret;
1331}
sewardj1c147ff2009-07-26 19:52:06 +00001332#if defined(VGO_linux)
1333 PTH_FUNC(int, pthreadZurwlockZudestroy, // pthread_rwlock_destroy
1334 pthread_rwlock_t *rwl) {
1335 return pthread_rwlock_destroy_WRK(rwl);
1336 }
1337#elif defined(VGO_darwin)
1338 PTH_FUNC(int, pthreadZurwlockZudestroyZa, // pthread_rwlock_destroy*
1339 pthread_rwlock_t *rwl) {
1340 return pthread_rwlock_destroy_WRK(rwl);
1341 }
1342#else
1343# error "Unsupported OS"
1344#endif
sewardjb4112022007-11-09 22:49:28 +00001345
1346
sewardj1c147ff2009-07-26 19:52:06 +00001347//-----------------------------------------------------------
1348// glibc: pthread_rwlock_wrlock
1349// darwin: pthread_rwlock_wrlock
1350// darwin: pthread_rwlock_wrlock$UNIX2003
1351//
1352static int pthread_rwlock_wrlock_WRK(pthread_rwlock_t* rwlock)
sewardjb4112022007-11-09 22:49:28 +00001353{
1354 int ret;
1355 OrigFn fn;
1356 VALGRIND_GET_ORIG_FN(fn);
1357 if (TRACE_PTH_FNS) {
1358 fprintf(stderr, "<< pthread_rwl_wlk %p", rwlock); fflush(stderr);
1359 }
1360
sewardj789c3c52008-02-25 12:10:07 +00001361 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1362 pthread_rwlock_t*,rwlock,
1363 long,1/*isW*/, long,0/*!isTryLock*/);
sewardjb4112022007-11-09 22:49:28 +00001364
1365 CALL_FN_W_W(ret, fn, rwlock);
1366
1367 if (ret == 0 /*success*/) {
1368 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1369 pthread_rwlock_t*,rwlock, long,1/*isW*/);
1370 } else {
1371 DO_PthAPIerror( "pthread_rwlock_wrlock", ret );
1372 }
1373
1374 if (TRACE_PTH_FNS) {
1375 fprintf(stderr, " :: rwl_wlk -> %d >>\n", ret);
1376 }
1377 return ret;
1378}
sewardj1c147ff2009-07-26 19:52:06 +00001379#if defined(VGO_linux)
1380 PTH_FUNC(int, pthreadZurwlockZuwrlock, // pthread_rwlock_wrlock
1381 pthread_rwlock_t* rwlock) {
1382 return pthread_rwlock_wrlock_WRK(rwlock);
1383 }
1384#elif defined(VGO_darwin)
1385 PTH_FUNC(int, pthreadZurwlockZuwrlockZa, // pthread_rwlock_wrlock*
1386 pthread_rwlock_t* rwlock) {
1387 return pthread_rwlock_wrlock_WRK(rwlock);
1388 }
1389#else
1390# error "Unsupported OS"
1391#endif
sewardjb4112022007-11-09 22:49:28 +00001392
1393
sewardj1c147ff2009-07-26 19:52:06 +00001394//-----------------------------------------------------------
1395// glibc: pthread_rwlock_rdlock
1396// darwin: pthread_rwlock_rdlock
1397// darwin: pthread_rwlock_rdlock$UNIX2003
1398//
1399static int pthread_rwlock_rdlock_WRK(pthread_rwlock_t* rwlock)
sewardjb4112022007-11-09 22:49:28 +00001400{
1401 int ret;
1402 OrigFn fn;
1403 VALGRIND_GET_ORIG_FN(fn);
1404 if (TRACE_PTH_FNS) {
1405 fprintf(stderr, "<< pthread_rwl_rlk %p", rwlock); fflush(stderr);
1406 }
1407
sewardj789c3c52008-02-25 12:10:07 +00001408 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1409 pthread_rwlock_t*,rwlock,
1410 long,0/*!isW*/, long,0/*!isTryLock*/);
sewardjb4112022007-11-09 22:49:28 +00001411
1412 CALL_FN_W_W(ret, fn, rwlock);
1413
1414 if (ret == 0 /*success*/) {
1415 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1416 pthread_rwlock_t*,rwlock, long,0/*!isW*/);
1417 } else {
1418 DO_PthAPIerror( "pthread_rwlock_rdlock", ret );
1419 }
1420
1421 if (TRACE_PTH_FNS) {
1422 fprintf(stderr, " :: rwl_rlk -> %d >>\n", ret);
1423 }
1424 return ret;
1425}
sewardj1c147ff2009-07-26 19:52:06 +00001426#if defined(VGO_linux)
1427 PTH_FUNC(int, pthreadZurwlockZurdlock, // pthread_rwlock_rdlock
1428 pthread_rwlock_t* rwlock) {
1429 return pthread_rwlock_rdlock_WRK(rwlock);
1430 }
1431#elif defined(VGO_darwin)
1432 PTH_FUNC(int, pthreadZurwlockZurdlockZa, // pthread_rwlock_rdlock*
1433 pthread_rwlock_t* rwlock) {
1434 return pthread_rwlock_rdlock_WRK(rwlock);
1435 }
1436#else
1437# error "Unsupported OS"
1438#endif
sewardjb4112022007-11-09 22:49:28 +00001439
1440
sewardj1c147ff2009-07-26 19:52:06 +00001441//-----------------------------------------------------------
1442// glibc: pthread_rwlock_trywrlock
1443// darwin: pthread_rwlock_trywrlock
1444// darwin: pthread_rwlock_trywrlock$UNIX2003
1445//
1446static int pthread_rwlock_trywrlock_WRK(pthread_rwlock_t* rwlock)
sewardj789c3c52008-02-25 12:10:07 +00001447{
1448 int ret;
1449 OrigFn fn;
1450 VALGRIND_GET_ORIG_FN(fn);
1451 if (TRACE_PTH_FNS) {
1452 fprintf(stderr, "<< pthread_rwl_trywlk %p", rwlock); fflush(stderr);
1453 }
1454
1455 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1456 pthread_rwlock_t*,rwlock,
1457 long,1/*isW*/, long,1/*isTryLock*/);
1458
1459 CALL_FN_W_W(ret, fn, rwlock);
1460
1461 /* There's a hole here: libpthread now knows the lock is locked,
1462 but the tool doesn't, so some other thread could run and detect
1463 that the lock has been acquired by someone (this thread). Does
1464 this matter? Not sure, but I don't think so. */
1465
1466 if (ret == 0 /*success*/) {
1467 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1468 pthread_rwlock_t*,rwlock, long,1/*isW*/);
1469 } else {
1470 if (ret != EBUSY)
1471 DO_PthAPIerror( "pthread_rwlock_trywrlock", ret );
1472 }
1473
1474 if (TRACE_PTH_FNS) {
1475 fprintf(stderr, " :: rwl_trywlk -> %d >>\n", ret);
1476 }
1477 return ret;
1478}
sewardj1c147ff2009-07-26 19:52:06 +00001479#if defined(VGO_linux)
1480 PTH_FUNC(int, pthreadZurwlockZutrywrlock, // pthread_rwlock_trywrlock
1481 pthread_rwlock_t* rwlock) {
1482 return pthread_rwlock_trywrlock_WRK(rwlock);
1483 }
1484#elif defined(VGO_darwin)
1485 PTH_FUNC(int, pthreadZurwlockZutrywrlockZa, // pthread_rwlock_trywrlock*
1486 pthread_rwlock_t* rwlock) {
1487 return pthread_rwlock_trywrlock_WRK(rwlock);
1488 }
1489#else
1490# error "Unsupported OS"
1491#endif
sewardj789c3c52008-02-25 12:10:07 +00001492
1493
sewardj1c147ff2009-07-26 19:52:06 +00001494//-----------------------------------------------------------
1495// glibc: pthread_rwlock_tryrdlock
1496// darwin: pthread_rwlock_trywrlock
1497// darwin: pthread_rwlock_trywrlock$UNIX2003
1498//
1499static int pthread_rwlock_tryrdlock_WRK(pthread_rwlock_t* rwlock)
sewardj789c3c52008-02-25 12:10:07 +00001500{
1501 int ret;
1502 OrigFn fn;
1503 VALGRIND_GET_ORIG_FN(fn);
1504 if (TRACE_PTH_FNS) {
1505 fprintf(stderr, "<< pthread_rwl_tryrlk %p", rwlock); fflush(stderr);
1506 }
1507
1508 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1509 pthread_rwlock_t*,rwlock,
1510 long,0/*!isW*/, long,1/*isTryLock*/);
1511
1512 CALL_FN_W_W(ret, fn, rwlock);
1513
1514 /* There's a hole here: libpthread now knows the lock is locked,
1515 but the tool doesn't, so some other thread could run and detect
1516 that the lock has been acquired by someone (this thread). Does
1517 this matter? Not sure, but I don't think so. */
1518
1519 if (ret == 0 /*success*/) {
1520 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1521 pthread_rwlock_t*,rwlock, long,0/*!isW*/);
1522 } else {
1523 if (ret != EBUSY)
1524 DO_PthAPIerror( "pthread_rwlock_tryrdlock", ret );
1525 }
1526
1527 if (TRACE_PTH_FNS) {
1528 fprintf(stderr, " :: rwl_tryrlk -> %d >>\n", ret);
1529 }
1530 return ret;
1531}
sewardj1c147ff2009-07-26 19:52:06 +00001532#if defined(VGO_linux)
1533 PTH_FUNC(int, pthreadZurwlockZutryrdlock, // pthread_rwlock_tryrdlock
1534 pthread_rwlock_t* rwlock) {
1535 return pthread_rwlock_tryrdlock_WRK(rwlock);
1536 }
1537#elif defined(VGO_darwin)
1538 PTH_FUNC(int, pthreadZurwlockZutryrdlockZa, // pthread_rwlock_tryrdlock*
1539 pthread_rwlock_t* rwlock) {
1540 return pthread_rwlock_tryrdlock_WRK(rwlock);
1541 }
1542#else
1543# error "Unsupported OS"
1544#endif
sewardj789c3c52008-02-25 12:10:07 +00001545
1546
sewardj1c147ff2009-07-26 19:52:06 +00001547//-----------------------------------------------------------
1548// glibc: pthread_rwlock_unlock
1549// darwin: pthread_rwlock_unlock
1550// darwin: pthread_rwlock_unlock$UNIX2003
1551static int pthread_rwlock_unlock_WRK(pthread_rwlock_t* rwlock)
sewardjb4112022007-11-09 22:49:28 +00001552{
1553 int ret;
1554 OrigFn fn;
1555 VALGRIND_GET_ORIG_FN(fn);
1556 if (TRACE_PTH_FNS) {
1557 fprintf(stderr, "<< pthread_rwl_unlk %p", rwlock); fflush(stderr);
1558 }
1559
1560 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE,
1561 pthread_rwlock_t*,rwlock);
1562
1563 CALL_FN_W_W(ret, fn, rwlock);
1564
1565 if (ret == 0 /*success*/) {
1566 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST,
1567 pthread_rwlock_t*,rwlock);
1568 } else {
1569 DO_PthAPIerror( "pthread_rwlock_unlock", ret );
1570 }
1571
1572 if (TRACE_PTH_FNS) {
1573 fprintf(stderr, " :: rwl_unlk -> %d >>\n", ret);
1574 }
1575 return ret;
1576}
sewardj1c147ff2009-07-26 19:52:06 +00001577#if defined(VGO_linux)
1578 PTH_FUNC(int, pthreadZurwlockZuunlock, // pthread_rwlock_unlock
1579 pthread_rwlock_t* rwlock) {
1580 return pthread_rwlock_unlock_WRK(rwlock);
1581 }
1582#elif defined(VGO_darwin)
1583 PTH_FUNC(int, pthreadZurwlockZuunlockZa, // pthread_rwlock_unlock*
1584 pthread_rwlock_t* rwlock) {
1585 return pthread_rwlock_unlock_WRK(rwlock);
1586 }
1587#else
1588# error "Unsupported OS"
1589#endif
sewardjb4112022007-11-09 22:49:28 +00001590
1591
1592/*----------------------------------------------------------------*/
1593/*--- POSIX semaphores ---*/
1594/*----------------------------------------------------------------*/
1595
1596#include <semaphore.h>
sewardj28a7f7d2009-07-26 20:15:37 +00001597#include <fcntl.h> /* O_CREAT */
sewardjb4112022007-11-09 22:49:28 +00001598
1599#define TRACE_SEM_FNS 0
1600
1601/* Handled:
1602 int sem_init(sem_t *sem, int pshared, unsigned value);
1603 int sem_destroy(sem_t *sem);
1604 int sem_wait(sem_t *sem);
1605 int sem_post(sem_t *sem);
sewardj1c147ff2009-07-26 19:52:06 +00001606 sem_t* sem_open(const char *name, int oflag,
1607 ... [mode_t mode, unsigned value]);
1608 [complete with its idiotic semantics]
1609 int sem_close(sem_t* sem);
sewardjb4112022007-11-09 22:49:28 +00001610
1611 Unhandled:
1612 int sem_trywait(sem_t *sem);
1613 int sem_timedwait(sem_t *restrict sem,
1614 const struct timespec *restrict abs_timeout);
1615*/
1616
sewardj1c147ff2009-07-26 19:52:06 +00001617//-----------------------------------------------------------
1618// glibc: sem_init@@GLIBC_2.2.5
1619// glibc: sem_init@@GLIBC_2.1
1620// glibc: sem_init@GLIBC_2.0
1621// darwin: sem_init
1622//
1623static int sem_init_WRK(sem_t* sem, int pshared, unsigned long value)
sewardjb4112022007-11-09 22:49:28 +00001624{
1625 OrigFn fn;
1626 int ret;
1627 VALGRIND_GET_ORIG_FN(fn);
1628
1629 if (TRACE_SEM_FNS) {
1630 fprintf(stderr, "<< sem_init(%p,%d,%lu) ", sem,pshared,value);
1631 fflush(stderr);
1632 }
1633
1634 CALL_FN_W_WWW(ret, fn, sem,pshared,value);
1635
1636 if (ret == 0) {
sewardj11e352f2007-11-30 11:11:02 +00001637 DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST,
1638 sem_t*, sem, unsigned long, value);
sewardjb4112022007-11-09 22:49:28 +00001639 } else {
1640 DO_PthAPIerror( "sem_init", errno );
1641 }
1642
1643 if (TRACE_SEM_FNS) {
1644 fprintf(stderr, " sem_init -> %d >>\n", ret);
1645 fflush(stderr);
1646 }
1647
1648 return ret;
1649}
sewardj1c147ff2009-07-26 19:52:06 +00001650#if defined(VGO_linux)
1651 PTH_FUNC(int, semZuinitZAZa, // sem_init@*
1652 sem_t* sem, int pshared, unsigned long value) {
1653 return sem_init_WRK(sem, pshared, value);
1654 }
1655#elif defined(VGO_darwin)
1656 PTH_FUNC(int, semZuinit, // sem_init
1657 sem_t* sem, int pshared, unsigned long value) {
1658 return sem_init_WRK(sem, pshared, value);
1659 }
1660#else
1661# error "Unsupported OS"
1662#endif
sewardjb4112022007-11-09 22:49:28 +00001663
1664
sewardj1c147ff2009-07-26 19:52:06 +00001665//-----------------------------------------------------------
1666// glibc: sem_destroy@GLIBC_2.0
1667// glibc: sem_destroy@@GLIBC_2.1
1668// glibc: sem_destroy@@GLIBC_2.2.5
1669// darwin: sem_destroy
1670static int sem_destroy_WRK(sem_t* sem)
sewardjb4112022007-11-09 22:49:28 +00001671{
1672 OrigFn fn;
1673 int ret;
1674 VALGRIND_GET_ORIG_FN(fn);
1675
1676 if (TRACE_SEM_FNS) {
1677 fprintf(stderr, "<< sem_destroy(%p) ", sem);
1678 fflush(stderr);
1679 }
1680
sewardj11e352f2007-11-30 11:11:02 +00001681 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, sem_t*, sem);
sewardjb4112022007-11-09 22:49:28 +00001682
1683 CALL_FN_W_W(ret, fn, sem);
1684
1685 if (ret != 0) {
1686 DO_PthAPIerror( "sem_destroy", errno );
1687 }
1688
1689 if (TRACE_SEM_FNS) {
1690 fprintf(stderr, " sem_destroy -> %d >>\n", ret);
1691 fflush(stderr);
1692 }
1693
1694 return ret;
1695}
sewardj1c147ff2009-07-26 19:52:06 +00001696#if defined(VGO_linux)
1697 PTH_FUNC(int, semZudestroyZAZa, // sem_destroy*
1698 sem_t* sem) {
1699 return sem_destroy_WRK(sem);
1700 }
1701#elif defined(VGO_darwin)
1702 PTH_FUNC(int, semZudestroy, // sem_destroy
1703 sem_t* sem) {
1704 return sem_destroy_WRK(sem);
1705 }
1706#else
1707# error "Unsupported OS"
1708#endif
sewardjb4112022007-11-09 22:49:28 +00001709
1710
sewardj1c147ff2009-07-26 19:52:06 +00001711//-----------------------------------------------------------
1712// glibc: sem_wait
1713// glibc: sem_wait@GLIBC_2.0
1714// glibc: sem_wait@@GLIBC_2.1
1715// darwin: sem_wait
1716// darwin: sem_wait$NOCANCEL$UNIX2003
1717// darwin: sem_wait$UNIX2003
1718//
sewardjb4112022007-11-09 22:49:28 +00001719/* wait: decrement semaphore - acquire lockage */
1720static int sem_wait_WRK(sem_t* sem)
1721{
1722 OrigFn fn;
1723 int ret;
1724 VALGRIND_GET_ORIG_FN(fn);
1725
1726 if (TRACE_SEM_FNS) {
1727 fprintf(stderr, "<< sem_wait(%p) ", sem);
1728 fflush(stderr);
1729 }
1730
1731 CALL_FN_W_W(ret, fn, sem);
1732
1733 if (ret == 0) {
sewardj11e352f2007-11-30 11:11:02 +00001734 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_WAIT_POST, sem_t*,sem);
sewardjb4112022007-11-09 22:49:28 +00001735 } else {
1736 DO_PthAPIerror( "sem_wait", errno );
1737 }
1738
1739 if (TRACE_SEM_FNS) {
1740 fprintf(stderr, " sem_wait -> %d >>\n", ret);
1741 fflush(stderr);
1742 }
1743
1744 return ret;
1745}
sewardj1c147ff2009-07-26 19:52:06 +00001746#if defined(VGO_linux)
1747 PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */
1748 return sem_wait_WRK(sem);
1749 }
1750 PTH_FUNC(int, semZuwaitZAZa, sem_t* sem) { /* sem_wait@* */
1751 return sem_wait_WRK(sem);
1752 }
1753#elif defined(VGO_darwin)
1754 PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */
1755 return sem_wait_WRK(sem);
1756 }
1757 PTH_FUNC(int, semZuwaitZDZa, sem_t* sem) { /* sem_wait$* */
1758 return sem_wait_WRK(sem);
1759 }
1760#else
1761# error "Unsupported OS"
1762#endif
sewardjb4112022007-11-09 22:49:28 +00001763
1764
sewardj1c147ff2009-07-26 19:52:06 +00001765//-----------------------------------------------------------
1766// glibc: sem_post
1767// glibc: sem_post@GLIBC_2.0
1768// glibc: sem_post@@GLIBC_2.1
1769// darwin: sem_post
1770//
sewardjb4112022007-11-09 22:49:28 +00001771/* post: increment semaphore - release lockage */
1772static int sem_post_WRK(sem_t* sem)
1773{
1774 OrigFn fn;
1775 int ret;
1776
1777 VALGRIND_GET_ORIG_FN(fn);
1778
1779 if (TRACE_SEM_FNS) {
1780 fprintf(stderr, "<< sem_post(%p) ", sem);
1781 fflush(stderr);
1782 }
1783
sewardj11e352f2007-11-30 11:11:02 +00001784 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_POST_PRE, sem_t*,sem);
sewardjb4112022007-11-09 22:49:28 +00001785
1786 CALL_FN_W_W(ret, fn, sem);
1787
1788 if (ret != 0) {
1789 DO_PthAPIerror( "sem_post", errno );
1790 }
1791
1792 if (TRACE_SEM_FNS) {
1793 fprintf(stderr, " sem_post -> %d >>\n", ret);
1794 fflush(stderr);
1795 }
1796
1797 return ret;
1798}
sewardj1c147ff2009-07-26 19:52:06 +00001799#if defined(VGO_linux)
1800 PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */
1801 return sem_post_WRK(sem);
1802 }
1803 PTH_FUNC(int, semZupostZAZa, sem_t* sem) { /* sem_post@* */
1804 return sem_post_WRK(sem);
1805 }
1806#elif defined(VGO_darwin)
1807 PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */
1808 return sem_post_WRK(sem);
1809 }
1810#else
1811# error "Unsupported OS"
1812#endif
1813
1814
1815//-----------------------------------------------------------
1816// glibc: sem_open
1817// darwin: sem_open
1818//
1819PTH_FUNC(sem_t*, semZuopen,
1820 const char* name, long oflag,
1821 long mode, unsigned long value)
1822{
1823 /* A copy of sem_init_WRK (more or less). Is this correct? */
1824 OrigFn fn;
1825 sem_t* ret;
1826 VALGRIND_GET_ORIG_FN(fn);
1827
1828 if (TRACE_SEM_FNS) {
1829 fprintf(stderr, "<< sem_open(\"%s\",%ld,%lx,%lu) ",
1830 name,oflag,mode,value);
1831 fflush(stderr);
1832 }
1833
1834 CALL_FN_W_WWWW(ret, fn, name,oflag,mode,value);
1835
1836 if (ret != SEM_FAILED && (oflag & O_CREAT)) {
1837 DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST,
1838 sem_t*, ret, unsigned long, value);
1839 }
1840 if (ret == SEM_FAILED) {
1841 DO_PthAPIerror( "sem_open", errno );
1842 }
1843
1844 if (TRACE_SEM_FNS) {
1845 fprintf(stderr, " sem_open -> %p >>\n", ret);
1846 fflush(stderr);
1847 }
1848
1849 return ret;
sewardjb4112022007-11-09 22:49:28 +00001850}
1851
1852
sewardj1c147ff2009-07-26 19:52:06 +00001853//-----------------------------------------------------------
1854// glibc: sem_close
1855// darwin: sem_close
1856PTH_FUNC(int, sem_close, sem_t* sem)
1857{
1858 OrigFn fn;
1859 int ret;
1860 VALGRIND_GET_ORIG_FN(fn);
1861
1862 if (TRACE_SEM_FNS) {
1863 fprintf(stderr, "<< sem_close(%p) ", sem);
1864 fflush(stderr);
1865 }
1866
1867 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, sem_t*, sem);
1868
1869 CALL_FN_W_W(ret, fn, sem);
1870
1871 if (ret != 0) {
1872 DO_PthAPIerror( "sem_close", errno );
1873 }
1874
1875 if (TRACE_SEM_FNS) {
1876 fprintf(stderr, " close -> %d >>\n", ret);
1877 fflush(stderr);
1878 }
1879
1880 return ret;
1881}
1882
sewardjb4112022007-11-09 22:49:28 +00001883
1884/*----------------------------------------------------------------*/
1885/*--- Qt 4 threading functions (w/ GNU name mangling) ---*/
1886/*----------------------------------------------------------------*/
1887
sewardj38e0cf92008-11-19 10:40:56 +00001888/* Handled:
1889 QMutex::lock()
1890 QMutex::unlock()
1891 QMutex::tryLock()
1892 QMutex::tryLock(int)
sewardjb4112022007-11-09 22:49:28 +00001893
sewardj38e0cf92008-11-19 10:40:56 +00001894 QMutex::QMutex(QMutex::RecursionMode) _ZN6QMutexC1ENS_13RecursionModeE
1895 QMutex::QMutex(QMutex::RecursionMode) _ZN6QMutexC2ENS_13RecursionModeE
1896 QMutex::~QMutex() _ZN6QMutexD1Ev
1897 QMutex::~QMutex() _ZN6QMutexD2Ev
sewardjb4112022007-11-09 22:49:28 +00001898
sewardj38e0cf92008-11-19 10:40:56 +00001899 Unhandled:
1900 QReadWriteLock::lockForRead()
1901 QReadWriteLock::lockForWrite()
1902 QReadWriteLock::unlock()
1903 QReadWriteLock::tryLockForRead(int)
1904 QReadWriteLock::tryLockForRead()
1905 QReadWriteLock::tryLockForWrite(int)
1906 QReadWriteLock::tryLockForWrite()
1907
1908 QWaitCondition::wait(QMutex*, unsigned long)
1909 QWaitCondition::wakeAll()
1910 QWaitCondition::wakeOne()
1911
1912 QSemaphore::*
1913*/
1914/* More comments, 19 Nov 08, based on assessment of qt-4.5.0TP1,
1915 at least on Unix:
1916
1917 It's apparently only necessary to intercept QMutex, since that is
1918 not implemented using pthread_mutex_t; instead Qt4 has its own
1919 implementation based on atomics (to check the non-contended case)
1920 and pthread_cond_wait (to wait in the contended case).
1921
1922 QReadWriteLock is built on top of QMutex, counters, and a wait
1923 queue. So we don't need to handle it specially once QMutex
1924 handling is correct -- presumably the dependencies through QMutex
1925 are sufficient to avoid any false race reports. On the other hand,
1926 it is an open question whether too many dependencies are observed
1927 -- in which case we may miss races (false negatives). I suspect
1928 this is likely to be the case, unfortunately.
1929
1930 QWaitCondition is built on pthread_cond_t, pthread_mutex_t, QMutex
1931 and QReadWriteLock. Same compositional-correctness justificiation
1932 and limitations as fro QReadWriteLock.
1933
1934 Ditto QSemaphore (from cursory examination).
1935
1936 Does it matter that only QMutex is handled directly? Open
1937 question. From testing with drd/tests/qt4_* and with KDE4 apps, it
1938 appears that no false errors are reported; however it is not clear
1939 if this is causing false negatives.
1940
1941 Another problem with Qt4 is thread exiting. Threads are created
1942 with pthread_create (fine); but they detach and simply exit when
1943 done. There is no use of pthread_join, and the provided
1944 wait-for-a-thread-to-exit mechanism (QThread::wait, I believe)
1945 relies on a system of mutexes and flags. I suspect this also
1946 causes too many dependencies to appear. Consequently H sometimes
1947 fails to detect races at exit in some very short-lived racy
1948 programs, because it appears that a thread can exit _and_ have an
1949 observed dependency edge back to the main thread (presumably)
1950 before the main thread reaps the child (that is, calls
1951 QThread::wait).
1952
1953 This theory is supported by the observation that if all threads are
1954 made to wait at a pthread_barrier_t immediately before they exit,
1955 then H's detection of races in such programs becomes reliable;
1956 without the barrier, it is varies from run to run, depending
1957 (according to investigation) on whether aforementioned
1958 exit-before-reaping behaviour happens or not.
1959
1960 Finally, why is it necessary to intercept the QMutex constructors
1961 and destructors? The constructors are intercepted only as a matter
1962 of convenience, so H can print accurate "first observed at"
1963 clauses. However, it is actually necessary to intercept the
1964 destructors (as it is with pthread_mutex_destroy) in order that
1965 locks get removed from LAOG when they are destroyed.
sewardjb4112022007-11-09 22:49:28 +00001966*/
1967
1968// soname is libQtCore.so.4 ; match against libQtCore.so*
1969#define QT4_FUNC(ret_ty, f, args...) \
sewardj38e0cf92008-11-19 10:40:56 +00001970 ret_ty I_WRAP_SONAME_FNNAME_ZU(libQtCoreZdsoZa,f)(args); \
1971 ret_ty I_WRAP_SONAME_FNNAME_ZU(libQtCoreZdsoZa,f)(args)
sewardjb4112022007-11-09 22:49:28 +00001972
sewardj1c147ff2009-07-26 19:52:06 +00001973//-----------------------------------------------------------
sewardjb4112022007-11-09 22:49:28 +00001974// QMutex::lock()
sewardj38e0cf92008-11-19 10:40:56 +00001975QT4_FUNC(void, _ZN6QMutex4lockEv, void* self)
sewardjb4112022007-11-09 22:49:28 +00001976{
1977 OrigFn fn;
1978 VALGRIND_GET_ORIG_FN(fn);
1979 if (TRACE_QT4_FNS) {
1980 fprintf(stderr, "<< QMutex::lock %p", self); fflush(stderr);
1981 }
1982
1983 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
1984 void*,self, long,0/*!isTryLock*/);
1985
1986 CALL_FN_v_W(fn, self);
1987
1988 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
1989 void*, self);
1990
1991 if (TRACE_QT4_FNS) {
1992 fprintf(stderr, " :: Q::lock done >>\n");
1993 }
1994}
1995
sewardj1c147ff2009-07-26 19:52:06 +00001996//-----------------------------------------------------------
sewardjb4112022007-11-09 22:49:28 +00001997// QMutex::unlock()
sewardj38e0cf92008-11-19 10:40:56 +00001998QT4_FUNC(void, _ZN6QMutex6unlockEv, void* self)
sewardjb4112022007-11-09 22:49:28 +00001999{
2000 OrigFn fn;
2001 VALGRIND_GET_ORIG_FN(fn);
2002
2003 if (TRACE_QT4_FNS) {
2004 fprintf(stderr, "<< QMutex::unlock %p", self); fflush(stderr);
2005 }
2006
2007 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
2008 void*, self);
2009
2010 CALL_FN_v_W(fn, self);
2011
2012 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST,
2013 void*, self);
2014
2015 if (TRACE_QT4_FNS) {
2016 fprintf(stderr, " Q::unlock done >>\n");
2017 }
2018}
2019
sewardj1c147ff2009-07-26 19:52:06 +00002020//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002021// bool QMutex::tryLock()
sewardjb4112022007-11-09 22:49:28 +00002022// using 'long' to mimic C++ 'bool'
sewardj38e0cf92008-11-19 10:40:56 +00002023QT4_FUNC(long, _ZN6QMutex7tryLockEv, void* self)
sewardjb4112022007-11-09 22:49:28 +00002024{
2025 OrigFn fn;
2026 long ret;
2027 VALGRIND_GET_ORIG_FN(fn);
2028 if (TRACE_QT4_FNS) {
2029 fprintf(stderr, "<< QMutex::tryLock %p", self); fflush(stderr);
2030 }
2031
2032 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
2033 void*,self, long,1/*isTryLock*/);
2034
2035 CALL_FN_W_W(ret, fn, self);
2036
2037 // assumes that only the low 8 bits of the 'bool' are significant
2038 if (ret & 0xFF) {
2039 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
2040 void*, self);
2041 }
2042
2043 if (TRACE_QT4_FNS) {
2044 fprintf(stderr, " :: Q::tryLock -> %lu >>\n", ret);
2045 }
2046
2047 return ret;
2048}
2049
sewardj1c147ff2009-07-26 19:52:06 +00002050//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002051// bool QMutex::tryLock(int)
2052// using 'long' to mimic C++ 'bool'
2053QT4_FUNC(long, _ZN6QMutex7tryLockEi, void* self, long arg2)
sewardjb4112022007-11-09 22:49:28 +00002054{
2055 OrigFn fn;
sewardj38e0cf92008-11-19 10:40:56 +00002056 long ret;
sewardjb4112022007-11-09 22:49:28 +00002057 VALGRIND_GET_ORIG_FN(fn);
2058 if (TRACE_QT4_FNS) {
sewardj38e0cf92008-11-19 10:40:56 +00002059 fprintf(stderr, "<< QMutex::tryLock(int) %p %d", self, (int)arg2);
sewardjb4112022007-11-09 22:49:28 +00002060 fflush(stderr);
2061 }
2062
sewardj38e0cf92008-11-19 10:40:56 +00002063 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
2064 void*,self, long,1/*isTryLock*/);
sewardjb4112022007-11-09 22:49:28 +00002065
sewardj38e0cf92008-11-19 10:40:56 +00002066 CALL_FN_W_WW(ret, fn, self,arg2);
sewardjb4112022007-11-09 22:49:28 +00002067
sewardj38e0cf92008-11-19 10:40:56 +00002068 // assumes that only the low 8 bits of the 'bool' are significant
2069 if (ret & 0xFF) {
2070 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
2071 void*, self);
2072 }
sewardjb4112022007-11-09 22:49:28 +00002073
2074 if (TRACE_QT4_FNS) {
sewardj38e0cf92008-11-19 10:40:56 +00002075 fprintf(stderr, " :: Q::tryLock(int) -> %lu >>\n", ret);
sewardjb4112022007-11-09 22:49:28 +00002076 }
sewardj38e0cf92008-11-19 10:40:56 +00002077
2078 return ret;
sewardjb4112022007-11-09 22:49:28 +00002079}
2080
sewardj38e0cf92008-11-19 10:40:56 +00002081
sewardj1c147ff2009-07-26 19:52:06 +00002082//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002083// It's not really very clear what the args are here. But from
2084// a bit of dataflow analysis of the generated machine code of
2085// the original function, it appears this takes two args, and
2086// returns nothing. Nevertheless preserve return value just in
2087// case. A bit of debug printing indicates that the first arg
2088// is that of the mutex and the second is either zero or one,
2089// probably being the recursion mode, therefore.
2090// QMutex::QMutex(QMutex::RecursionMode) ("C1ENS" variant)
2091QT4_FUNC(void*, _ZN6QMutexC1ENS_13RecursionModeE,
2092 void* mutex,
2093 long recmode)
sewardjb4112022007-11-09 22:49:28 +00002094{
2095 OrigFn fn;
sewardj38e0cf92008-11-19 10:40:56 +00002096 long ret;
sewardjb4112022007-11-09 22:49:28 +00002097 VALGRIND_GET_ORIG_FN(fn);
sewardj38e0cf92008-11-19 10:40:56 +00002098 CALL_FN_W_WW(ret, fn, mutex, recmode);
2099 // fprintf(stderr, "QMutex constructor 1: %p <- %p %p\n", ret, arg1, arg2);
2100 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST,
2101 void*,mutex, long,1/*mbRec*/);
2102 return (void*)ret;
sewardjb4112022007-11-09 22:49:28 +00002103}
2104
sewardj1c147ff2009-07-26 19:52:06 +00002105//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002106// QMutex::~QMutex() ("D1Ev" variant)
2107QT4_FUNC(void*, _ZN6QMutexD1Ev, void* mutex)
sewardjb4112022007-11-09 22:49:28 +00002108{
2109 OrigFn fn;
sewardj38e0cf92008-11-19 10:40:56 +00002110 long ret;
sewardjb4112022007-11-09 22:49:28 +00002111 VALGRIND_GET_ORIG_FN(fn);
sewardj38e0cf92008-11-19 10:40:56 +00002112 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE,
2113 void*,mutex);
2114 CALL_FN_W_W(ret, fn, mutex);
2115 return (void*)ret;
sewardjb4112022007-11-09 22:49:28 +00002116}
2117
2118
sewardj1c147ff2009-07-26 19:52:06 +00002119//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002120// QMutex::QMutex(QMutex::RecursionMode) ("C2ENS" variant)
2121QT4_FUNC(void*, _ZN6QMutexC2ENS_13RecursionModeE,
2122 void* mutex,
2123 long recmode)
2124{
2125 assert(0);
2126}
2127
sewardj1c147ff2009-07-26 19:52:06 +00002128
2129//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00002130// QMutex::~QMutex() ("D2Ev" variant)
2131QT4_FUNC(void*, _ZN6QMutexD2Ev, void* mutex)
2132{
2133 assert(0);
2134}
2135
2136
2137// QReadWriteLock is not intercepted directly. See comments
2138// above.
2139
2140//// QReadWriteLock::lockForRead()
2141//// _ZN14QReadWriteLock11lockForReadEv == QReadWriteLock::lockForRead()
2142//QT4_FUNC(void, ZuZZN14QReadWriteLock11lockForReadEv,
2143// // _ZN14QReadWriteLock11lockForReadEv
2144// void* self)
2145//{
2146// OrigFn fn;
2147// VALGRIND_GET_ORIG_FN(fn);
2148// if (TRACE_QT4_FNS) {
2149// fprintf(stderr, "<< QReadWriteLock::lockForRead %p", self);
2150// fflush(stderr);
2151// }
2152//
2153// DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
2154// void*,self,
2155// long,0/*!isW*/, long,0/*!isTryLock*/);
2156//
2157// CALL_FN_v_W(fn, self);
2158//
2159// DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
2160// void*,self, long,0/*!isW*/);
2161//
2162// if (TRACE_QT4_FNS) {
2163// fprintf(stderr, " :: Q::lockForRead :: done >>\n");
2164// }
2165//}
2166//
2167//// QReadWriteLock::lockForWrite()
2168//// _ZN14QReadWriteLock12lockForWriteEv == QReadWriteLock::lockForWrite()
2169//QT4_FUNC(void, ZuZZN14QReadWriteLock12lockForWriteEv,
2170// // _ZN14QReadWriteLock12lockForWriteEv
2171// void* self)
2172//{
2173// OrigFn fn;
2174// VALGRIND_GET_ORIG_FN(fn);
2175// if (TRACE_QT4_FNS) {
2176// fprintf(stderr, "<< QReadWriteLock::lockForWrite %p", self);
2177// fflush(stderr);
2178// }
2179//
2180// DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
2181// void*,self,
2182// long,1/*isW*/, long,0/*!isTryLock*/);
2183//
2184// CALL_FN_v_W(fn, self);
2185//
2186// DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
2187// void*,self, long,1/*isW*/);
2188//
2189// if (TRACE_QT4_FNS) {
2190// fprintf(stderr, " :: Q::lockForWrite :: done >>\n");
2191// }
2192//}
2193//
2194//// QReadWriteLock::unlock()
2195//// _ZN14QReadWriteLock6unlockEv == QReadWriteLock::unlock()
2196//QT4_FUNC(void, ZuZZN14QReadWriteLock6unlockEv,
2197// // _ZN14QReadWriteLock6unlockEv
2198// void* self)
2199//{
2200// OrigFn fn;
2201// VALGRIND_GET_ORIG_FN(fn);
2202// if (TRACE_QT4_FNS) {
2203// fprintf(stderr, "<< QReadWriteLock::unlock %p", self);
2204// fflush(stderr);
2205// }
2206//
2207// DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE,
2208// void*,self);
2209//
2210// CALL_FN_v_W(fn, self);
2211//
2212// DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST,
2213// void*,self);
2214//
2215// if (TRACE_QT4_FNS) {
2216// fprintf(stderr, " :: Q::unlock :: done >>\n");
2217// }
2218//}
2219
2220
2221/*----------------------------------------------------------------*/
2222/*--- Replacements for basic string functions, that don't ---*/
sewardjb80f0c92008-11-19 16:33:59 +00002223/*--- overrun the input arrays. ---*/
sewardj38e0cf92008-11-19 10:40:56 +00002224/*----------------------------------------------------------------*/
2225
2226/* Copied verbatim from memcheck/mc_replace_strmem.c. When copying
2227 new functions, please keep them in the same order as they appear in
2228 mc_replace_strmem.c. */
2229
sewardj38e0cf92008-11-19 10:40:56 +00002230
2231#define STRCHR(soname, fnname) \
2232 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
2233 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
2234 { \
2235 UChar ch = (UChar)((UInt)c); \
2236 UChar* p = (UChar*)s; \
2237 while (True) { \
2238 if (*p == ch) return p; \
2239 if (*p == 0) return NULL; \
2240 p++; \
2241 } \
2242 }
2243
2244// Apparently index() is the same thing as strchr()
njne6154662009-02-10 04:23:41 +00002245STRCHR(VG_Z_LIBC_SONAME, strchr)
njne6154662009-02-10 04:23:41 +00002246STRCHR(VG_Z_LIBC_SONAME, index)
njnb4cfbc42009-05-04 04:20:02 +00002247#if defined(VGO_linux)
2248STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
njne6154662009-02-10 04:23:41 +00002249STRCHR(VG_Z_LD_LINUX_SO_2, index)
njnb4cfbc42009-05-04 04:20:02 +00002250STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
njne6154662009-02-10 04:23:41 +00002251STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
njnb4cfbc42009-05-04 04:20:02 +00002252#endif
sewardj38e0cf92008-11-19 10:40:56 +00002253
2254
2255// Note that this replacement often doesn't get used because gcc inlines
2256// calls to strlen() with its own built-in version. This can be very
2257// confusing if you aren't expecting it. Other small functions in this file
2258// may also be inline by gcc.
2259#define STRLEN(soname, fnname) \
2260 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
2261 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
2262 { \
2263 SizeT i = 0; \
2264 while (str[i] != 0) i++; \
2265 return i; \
2266 }
2267
njne6154662009-02-10 04:23:41 +00002268STRLEN(VG_Z_LIBC_SONAME, strlen)
njnb4cfbc42009-05-04 04:20:02 +00002269#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +00002270STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
2271STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
njnb4cfbc42009-05-04 04:20:02 +00002272#endif
sewardj38e0cf92008-11-19 10:40:56 +00002273
2274
2275#define STRCPY(soname, fnname) \
2276 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
2277 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
2278 { \
2279 const Char* dst_orig = dst; \
2280 \
2281 while (*src) *dst++ = *src++; \
2282 *dst = 0; \
2283 \
2284 return (char*)dst_orig; \
2285 }
2286
njne6154662009-02-10 04:23:41 +00002287STRCPY(VG_Z_LIBC_SONAME, strcpy)
sewardj38e0cf92008-11-19 10:40:56 +00002288
2289
2290#define STRCMP(soname, fnname) \
2291 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2292 ( const char* s1, const char* s2 ); \
2293 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2294 ( const char* s1, const char* s2 ) \
2295 { \
2296 register unsigned char c1; \
2297 register unsigned char c2; \
2298 while (True) { \
2299 c1 = *(unsigned char *)s1; \
2300 c2 = *(unsigned char *)s2; \
2301 if (c1 != c2) break; \
2302 if (c1 == 0) break; \
2303 s1++; s2++; \
2304 } \
2305 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
2306 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
2307 return 0; \
2308 }
2309
njne6154662009-02-10 04:23:41 +00002310STRCMP(VG_Z_LIBC_SONAME, strcmp)
njnb4cfbc42009-05-04 04:20:02 +00002311#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +00002312STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
2313STRCMP(VG_Z_LD64_SO_1, strcmp)
njnb4cfbc42009-05-04 04:20:02 +00002314#endif
sewardj38e0cf92008-11-19 10:40:56 +00002315
2316
2317#define MEMCPY(soname, fnname) \
2318 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2319 ( void *dst, const void *src, SizeT len ); \
2320 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2321 ( void *dst, const void *src, SizeT len ) \
2322 { \
2323 register char *d; \
2324 register char *s; \
2325 \
2326 if (len == 0) \
2327 return dst; \
2328 \
2329 if ( dst > src ) { \
2330 d = (char *)dst + len - 1; \
2331 s = (char *)src + len - 1; \
2332 while ( len >= 4 ) { \
2333 *d-- = *s--; \
2334 *d-- = *s--; \
2335 *d-- = *s--; \
2336 *d-- = *s--; \
2337 len -= 4; \
2338 } \
2339 while ( len-- ) { \
2340 *d-- = *s--; \
2341 } \
2342 } else if ( dst < src ) { \
2343 d = (char *)dst; \
2344 s = (char *)src; \
2345 while ( len >= 4 ) { \
2346 *d++ = *s++; \
2347 *d++ = *s++; \
2348 *d++ = *s++; \
2349 *d++ = *s++; \
2350 len -= 4; \
2351 } \
2352 while ( len-- ) { \
2353 *d++ = *s++; \
2354 } \
2355 } \
2356 return dst; \
2357 }
2358
njne6154662009-02-10 04:23:41 +00002359MEMCPY(VG_Z_LIBC_SONAME, memcpy)
njnb4cfbc42009-05-04 04:20:02 +00002360#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +00002361MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
2362MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
njnb4cfbc42009-05-04 04:20:02 +00002363#endif
sewardj38e0cf92008-11-19 10:40:56 +00002364/* icc9 blats these around all over the place. Not only in the main
2365 executable but various .so's. They are highly tuned and read
2366 memory beyond the source boundary (although work correctly and
2367 never go across page boundaries), so give errors when run natively,
2368 at least for misaligned source arg. Just intercepting in the exe
2369 only until we understand more about the problem. See
2370 http://bugs.kde.org/show_bug.cgi?id=139776
2371 */
2372MEMCPY(NONE, _intel_fast_memcpy)
2373
2374
sewardjb4112022007-11-09 22:49:28 +00002375/*--------------------------------------------------------------------*/
2376/*--- end tc_intercepts.c ---*/
2377/*--------------------------------------------------------------------*/