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