blob: 38b00de22f39c92e824efee7375e61bd72c2b1c6 [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//
njnf76d27a2009-05-28 01:53:07 +0000211static int pthread_create_WRK(pthread_t *thread, const pthread_attr_t *attr,
212 void *(*start) (void *), void *arg)
sewardjb4112022007-11-09 22:49:28 +0000213{
214 int ret;
215 OrigFn fn;
216 volatile Word xargs[3];
217
218 VALGRIND_GET_ORIG_FN(fn);
219 if (TRACE_PTH_FNS) {
220 fprintf(stderr, "<< pthread_create wrapper"); fflush(stderr);
221 }
222 xargs[0] = (Word)start;
223 xargs[1] = (Word)arg;
224 xargs[2] = 1; /* serves as a spinlock -- sigh */
225
226 CALL_FN_W_WWWW(ret, fn, thread,attr,mythread_wrapper,&xargs[0]);
227
228 if (ret == 0) {
229 /* we have to wait for the child to notify the tool of its
230 pthread_t before continuing */
231 while (xargs[2] != 0) {
sewardjeafad3b2007-11-18 01:16:52 +0000232 /* Do nothing. We need to spin until the child writes to
233 xargs[2]. However, that can lead to starvation in the
234 child and very long delays (eg, tc19_shadowmem on
235 ppc64-linux Fedora Core 6). So yield the cpu if we can,
236 to let the child run at the earliest available
237 opportunity. */
238 sched_yield();
sewardjb4112022007-11-09 22:49:28 +0000239 }
240 } else {
241 DO_PthAPIerror( "pthread_create", ret );
242 }
243
244 if (TRACE_PTH_FNS) {
245 fprintf(stderr, " :: pth_create -> %d >>\n", ret);
246 }
247 return ret;
248}
sewardj1c147ff2009-07-26 19:52:06 +0000249#if defined(VGO_linux)
250 PTH_FUNC(int, pthreadZucreateZAZa, // pthread_create@*
251 pthread_t *thread, const pthread_attr_t *attr,
252 void *(*start) (void *), void *arg) {
253 return pthread_create_WRK(thread, attr, start, arg);
254 }
255#elif defined(VGO_darwin)
256 PTH_FUNC(int, pthreadZucreate, // pthread_create
257 pthread_t *thread, const pthread_attr_t *attr,
258 void *(*start) (void *), void *arg) {
259 return pthread_create_WRK(thread, attr, start, arg);
260 }
261 PTH_FUNC(int, pthreadZucreateZuZa, // pthread_create_*
262 pthread_t *thread, const pthread_attr_t *attr,
263 void *(*start) (void *), void *arg) {
264 // trap anything else
265 assert(0);
266 }
267#else
268# error "Unsupported OS"
269#endif
sewardjb4112022007-11-09 22:49:28 +0000270
sewardj1c147ff2009-07-26 19:52:06 +0000271
272//-----------------------------------------------------------
273// glibc: pthread_join
274// darwin: pthread_join
275// darwin: pthread_join$NOCANCEL$UNIX2003
276// darwin pthread_join$UNIX2003
277static int pthread_join_WRK(pthread_t thread, void** value_pointer)
sewardjb4112022007-11-09 22:49:28 +0000278{
279 int ret;
280 OrigFn fn;
281 VALGRIND_GET_ORIG_FN(fn);
282 if (TRACE_PTH_FNS) {
283 fprintf(stderr, "<< pthread_join wrapper"); fflush(stderr);
284 }
285
286 CALL_FN_W_WW(ret, fn, thread,value_pointer);
287
288 /* At least with NPTL as the thread library, this is safe because
289 it is guaranteed (by NPTL) that the joiner will completely gone
290 before pthread_join (the original) returns. See email below.*/
291 if (ret == 0 /*success*/) {
292 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_JOIN_POST, pthread_t,thread);
293 } else {
294 DO_PthAPIerror( "pthread_join", ret );
295 }
296
297 if (TRACE_PTH_FNS) {
298 fprintf(stderr, " :: pth_join -> %d >>\n", ret);
299 }
300 return ret;
301}
sewardj1c147ff2009-07-26 19:52:06 +0000302#if defined(VGO_linux)
303 PTH_FUNC(int, pthreadZujoin, // pthread_join
304 pthread_t thread, void** value_pointer) {
305 return pthread_join_WRK(thread, value_pointer);
306 }
307#elif defined(VGO_darwin)
308 PTH_FUNC(int, pthreadZujoinZa, // pthread_join*
309 pthread_t thread, void** value_pointer) {
310 return pthread_join_WRK(thread, value_pointer);
311 }
312#else
313# error "Unsupported OS"
314#endif
315
sewardjb4112022007-11-09 22:49:28 +0000316
317/* Behaviour of pthread_join on NPTL:
318
319Me:
320I have a question re the NPTL pthread_join implementation.
321
322 Suppose I am the thread 'stayer'.
323
324 If I call pthread_join(quitter), is it guaranteed that the
325 thread 'quitter' has really exited before pthread_join returns?
326
327 IOW, is it guaranteed that 'quitter' will not execute any further
328 instructions after pthread_join returns?
329
330I believe this is true based on the following analysis of
331glibc-2.5 sources. However am not 100% sure and would appreciate
332confirmation.
333
334 'quitter' will be running start_thread() in nptl/pthread_create.c
335
336 The last action of start_thread() is to exit via
337 __exit_thread_inline(0), which simply does sys_exit
338 (nptl/pthread_create.c:403)
339
340 'stayer' meanwhile is waiting for lll_wait_tid (pd->tid)
341 (call at nptl/pthread_join.c:89)
342
343 As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536,
344 lll_wait_tid will not return until kernel notifies via futex
345 wakeup that 'quitter' has terminated.
346
347 Hence pthread_join cannot return until 'quitter' really has
348 completely disappeared.
349
350Drepper:
351> As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536,
352> lll_wait_tid will not return until kernel notifies via futex
353> wakeup that 'quitter' has terminated.
354That's the key. The kernel resets the TID field after the thread is
355done. No way the joiner can return before the thread is gone.
356*/
357
358
359/*----------------------------------------------------------------*/
360/*--- pthread_mutex_t functions ---*/
361/*----------------------------------------------------------------*/
362
363/* Handled: pthread_mutex_init pthread_mutex_destroy
364 pthread_mutex_lock
365 pthread_mutex_trylock pthread_mutex_timedlock
366 pthread_mutex_unlock
367
368 Unhandled: pthread_spin_init pthread_spin_destroy
369 pthread_spin_lock
370 pthread_spin_trylock
371 pthread_spin_unlock
372*/
373
sewardj1c147ff2009-07-26 19:52:06 +0000374//-----------------------------------------------------------
375// glibc: pthread_mutex_init
376// darwin: pthread_mutex_init
sewardjb4112022007-11-09 22:49:28 +0000377PTH_FUNC(int, pthreadZumutexZuinit, // pthread_mutex_init
378 pthread_mutex_t *mutex,
379 pthread_mutexattr_t* attr)
380{
381 int ret;
382 long mbRec;
383 OrigFn fn;
384 VALGRIND_GET_ORIG_FN(fn);
385 if (TRACE_PTH_FNS) {
386 fprintf(stderr, "<< pthread_mxinit %p", mutex); fflush(stderr);
387 }
388
389 mbRec = 0;
390 if (attr) {
391 int ty, zzz;
392 zzz = pthread_mutexattr_gettype(attr, &ty);
393 if (zzz == 0 && ty == PTHREAD_MUTEX_RECURSIVE)
394 mbRec = 1;
395 }
396
397 CALL_FN_W_WW(ret, fn, mutex,attr);
398
399 if (ret == 0 /*success*/) {
400 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST,
401 pthread_mutex_t*,mutex, long,mbRec);
402 } else {
403 DO_PthAPIerror( "pthread_mutex_init", ret );
404 }
405
406 if (TRACE_PTH_FNS) {
407 fprintf(stderr, " :: mxinit -> %d >>\n", ret);
408 }
409 return ret;
410}
411
412
sewardj1c147ff2009-07-26 19:52:06 +0000413//-----------------------------------------------------------
414// glibc: pthread_mutex_destroy
415// darwin: pthread_mutex_destroy
sewardjb4112022007-11-09 22:49:28 +0000416PTH_FUNC(int, pthreadZumutexZudestroy, // pthread_mutex_destroy
417 pthread_mutex_t *mutex)
418{
419 int ret;
420 OrigFn fn;
421 VALGRIND_GET_ORIG_FN(fn);
422 if (TRACE_PTH_FNS) {
423 fprintf(stderr, "<< pthread_mxdestroy %p", mutex); fflush(stderr);
424 }
425
426 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE,
427 pthread_mutex_t*,mutex);
428
429 CALL_FN_W_W(ret, fn, mutex);
430
431 if (ret != 0) {
432 DO_PthAPIerror( "pthread_mutex_destroy", ret );
433 }
434
435 if (TRACE_PTH_FNS) {
436 fprintf(stderr, " :: mxdestroy -> %d >>\n", ret);
437 }
438 return ret;
439}
440
441
sewardj1c147ff2009-07-26 19:52:06 +0000442//-----------------------------------------------------------
443// glibc: pthread_mutex_lock
444// darwin: pthread_mutex_lock
sewardjb4112022007-11-09 22:49:28 +0000445PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock
446 pthread_mutex_t *mutex)
447{
448 int ret;
449 OrigFn fn;
450 VALGRIND_GET_ORIG_FN(fn);
451 if (TRACE_PTH_FNS) {
452 fprintf(stderr, "<< pthread_mxlock %p", mutex); fflush(stderr);
453 }
454
455 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
456 pthread_mutex_t*,mutex, long,0/*!isTryLock*/);
457
458 CALL_FN_W_W(ret, fn, mutex);
459
460 /* There's a hole here: libpthread now knows the lock is locked,
461 but the tool doesn't, so some other thread could run and detect
462 that the lock has been acquired by someone (this thread). Does
463 this matter? Not sure, but I don't think so. */
464
465 if (ret == 0 /*success*/) {
466 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
467 pthread_mutex_t*,mutex);
468 } else {
469 DO_PthAPIerror( "pthread_mutex_lock", ret );
470 }
471
472 if (TRACE_PTH_FNS) {
473 fprintf(stderr, " :: mxlock -> %d >>\n", ret);
474 }
475 return ret;
476}
477
478
sewardj1c147ff2009-07-26 19:52:06 +0000479//-----------------------------------------------------------
480// glibc: pthread_mutex_trylock
481// darwin: pthread_mutex_trylock
482//
sewardjb4112022007-11-09 22:49:28 +0000483// pthread_mutex_trylock. The handling needed here is very similar
484// to that for pthread_mutex_lock, except that we need to tell
485// the pre-lock creq that this is a trylock-style operation, and
486// therefore not to complain if the lock is nonrecursive and
487// already locked by this thread -- because then it'll just fail
488// immediately with EBUSY.
489PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock
490 pthread_mutex_t *mutex)
491{
492 int ret;
493 OrigFn fn;
494 VALGRIND_GET_ORIG_FN(fn);
495 if (TRACE_PTH_FNS) {
496 fprintf(stderr, "<< pthread_mxtrylock %p", mutex); fflush(stderr);
497 }
498
499 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
500 pthread_mutex_t*,mutex, long,1/*isTryLock*/);
501
502 CALL_FN_W_W(ret, fn, mutex);
503
504 /* There's a hole here: libpthread now knows the lock is locked,
505 but the tool doesn't, so some other thread could run and detect
506 that the lock has been acquired by someone (this thread). Does
507 this matter? Not sure, but I don't think so. */
508
509 if (ret == 0 /*success*/) {
510 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
511 pthread_mutex_t*,mutex);
512 } else {
513 if (ret != EBUSY)
514 DO_PthAPIerror( "pthread_mutex_trylock", ret );
515 }
516
517 if (TRACE_PTH_FNS) {
518 fprintf(stderr, " :: mxtrylock -> %d >>\n", ret);
519 }
520 return ret;
521}
522
523
sewardj1c147ff2009-07-26 19:52:06 +0000524//-----------------------------------------------------------
525// glibc: pthread_mutex_timedlock
526// darwin: (doesn't appear to exist)
527//
sewardjb4112022007-11-09 22:49:28 +0000528// pthread_mutex_timedlock. Identical logic to pthread_mutex_trylock.
529PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock
sewardj1c147ff2009-07-26 19:52:06 +0000530 pthread_mutex_t *mutex,
sewardjb4112022007-11-09 22:49:28 +0000531 void* timeout)
532{
533 int ret;
534 OrigFn fn;
535 VALGRIND_GET_ORIG_FN(fn);
536 if (TRACE_PTH_FNS) {
537 fprintf(stderr, "<< pthread_mxtimedlock %p %p", mutex, timeout);
538 fflush(stderr);
539 }
540
541 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
542 pthread_mutex_t*,mutex, long,1/*isTryLock-ish*/);
543
544 CALL_FN_W_WW(ret, fn, mutex,timeout);
545
546 /* There's a hole here: libpthread now knows the lock is locked,
547 but the tool doesn't, so some other thread could run and detect
548 that the lock has been acquired by someone (this thread). Does
549 this matter? Not sure, but I don't think so. */
550
551 if (ret == 0 /*success*/) {
552 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
553 pthread_mutex_t*,mutex);
554 } else {
555 if (ret != ETIMEDOUT)
556 DO_PthAPIerror( "pthread_mutex_timedlock", ret );
557 }
558
559 if (TRACE_PTH_FNS) {
560 fprintf(stderr, " :: mxtimedlock -> %d >>\n", ret);
561 }
562 return ret;
563}
564
565
sewardj1c147ff2009-07-26 19:52:06 +0000566//-----------------------------------------------------------
567// glibc: pthread_mutex_unlock
568// darwin: pthread_mutex_unlock
sewardjb4112022007-11-09 22:49:28 +0000569PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock
570 pthread_mutex_t *mutex)
571{
572 int ret;
573 OrigFn fn;
574 VALGRIND_GET_ORIG_FN(fn);
575
576 if (TRACE_PTH_FNS) {
577 fprintf(stderr, "<< pthread_mxunlk %p", mutex); fflush(stderr);
578 }
579
580 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
581 pthread_mutex_t*,mutex);
582
583 CALL_FN_W_W(ret, fn, mutex);
584
585 if (ret == 0 /*success*/) {
586 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST,
587 pthread_mutex_t*,mutex);
588 } else {
589 DO_PthAPIerror( "pthread_mutex_unlock", ret );
590 }
591
592 if (TRACE_PTH_FNS) {
593 fprintf(stderr, " mxunlk -> %d >>\n", ret);
594 }
595 return ret;
596}
597
598
599/*----------------------------------------------------------------*/
600/*--- pthread_cond_t functions ---*/
601/*----------------------------------------------------------------*/
602
603/* Handled: pthread_cond_wait pthread_cond_timedwait
604 pthread_cond_signal pthread_cond_broadcast
sewardjf98e1c02008-10-25 16:22:41 +0000605 pthread_cond_destroy
sewardjb4112022007-11-09 22:49:28 +0000606
sewardjf98e1c02008-10-25 16:22:41 +0000607 Unhandled: pthread_cond_init
608 -- is this important?
sewardjb4112022007-11-09 22:49:28 +0000609*/
610
sewardj1c147ff2009-07-26 19:52:06 +0000611//-----------------------------------------------------------
612// glibc: pthread_cond_wait@GLIBC_2.2.5
613// glibc: pthread_cond_wait@@GLIBC_2.3.2
614// darwin: pthread_cond_wait
615// darwin: pthread_cond_wait$NOCANCEL$UNIX2003
616// darwin: pthread_cond_wait$UNIX2003
617//
618static int pthread_cond_wait_WRK(pthread_cond_t* cond,
619 pthread_mutex_t* mutex)
sewardjb4112022007-11-09 22:49:28 +0000620{
621 int ret;
622 OrigFn fn;
623 unsigned long mutex_is_valid;
624
625 VALGRIND_GET_ORIG_FN(fn);
626
627 if (TRACE_PTH_FNS) {
628 fprintf(stderr, "<< pthread_cond_wait %p %p", cond, mutex);
629 fflush(stderr);
630 }
631
632 /* Tell the tool a cond-wait is about to happen, so it can check
633 for bogus argument values. In return it tells us whether it
634 thinks the mutex is valid or not. */
635 DO_CREQ_W_WW(mutex_is_valid,
636 _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE,
637 pthread_cond_t*,cond, pthread_mutex_t*,mutex);
638 assert(mutex_is_valid == 1 || mutex_is_valid == 0);
639
640 /* Tell the tool we're about to drop the mutex. This reflects the
641 fact that in a cond_wait, we show up holding the mutex, and the
642 call atomically drops the mutex and waits for the cv to be
643 signalled. */
644 if (mutex_is_valid) {
645 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
646 pthread_mutex_t*,mutex);
647 }
648
649 CALL_FN_W_WW(ret, fn, cond,mutex);
650
651 /* these conditionals look stupid, but compare w/ same logic for
652 pthread_cond_timedwait below */
653 if (ret == 0 && mutex_is_valid) {
654 /* and now we have the mutex again */
655 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
656 pthread_mutex_t*,mutex);
657 }
658
659 if (ret == 0 && mutex_is_valid) {
660 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST,
661 pthread_cond_t*,cond, pthread_mutex_t*,mutex);
662 }
663
664 if (ret != 0) {
665 DO_PthAPIerror( "pthread_cond_wait", ret );
666 }
667
668 if (TRACE_PTH_FNS) {
669 fprintf(stderr, " cowait -> %d >>\n", ret);
670 }
671
672 return ret;
673}
sewardj1c147ff2009-07-26 19:52:06 +0000674#if defined(VGO_linux)
675 PTH_FUNC(int, pthreadZucondZuwaitZAZa, // pthread_cond_wait@*
676 pthread_cond_t* cond, pthread_mutex_t* mutex) {
677 return pthread_cond_wait_WRK(cond, mutex);
678 }
679#elif defined(VGO_darwin)
680 PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait*
681 pthread_cond_t* cond, pthread_mutex_t* mutex) {
682 return pthread_cond_wait_WRK(cond, mutex);
683 }
684#else
685# error "Unsupported OS"
686#endif
sewardjb4112022007-11-09 22:49:28 +0000687
688
sewardj1c147ff2009-07-26 19:52:06 +0000689//-----------------------------------------------------------
690// glibc: pthread_cond_timedwait@@GLIBC_2.3.2
691// glibc: pthread_cond_timedwait@GLIBC_2.2.5
692// glibc: pthread_cond_timedwait@GLIBC_2.0
693// darwin: pthread_cond_timedwait
694// darwin: pthread_cond_timedwait$NOCANCEL$UNIX2003
695// darwin: pthread_cond_timedwait$UNIX2003
696// darwin: pthread_cond_timedwait_relative_np (trapped)
697//
698static int pthread_cond_timedwait_WRK(pthread_cond_t* cond,
699 pthread_mutex_t* mutex,
700 struct timespec* abstime)
sewardjb4112022007-11-09 22:49:28 +0000701{
702 int ret;
703 OrigFn fn;
704 unsigned long mutex_is_valid;
705 VALGRIND_GET_ORIG_FN(fn);
706
707 if (TRACE_PTH_FNS) {
708 fprintf(stderr, "<< pthread_cond_timedwait %p %p %p",
709 cond, mutex, abstime);
710 fflush(stderr);
711 }
712
713 /* Tell the tool a cond-wait is about to happen, so it can check
714 for bogus argument values. In return it tells us whether it
715 thinks the mutex is valid or not. */
716 DO_CREQ_W_WW(mutex_is_valid,
717 _VG_USERREQ__HG_PTHREAD_COND_WAIT_PRE,
718 pthread_cond_t*,cond, pthread_mutex_t*,mutex);
719 assert(mutex_is_valid == 1 || mutex_is_valid == 0);
720
721 /* Tell the tool we're about to drop the mutex. This reflects the
722 fact that in a cond_wait, we show up holding the mutex, and the
723 call atomically drops the mutex and waits for the cv to be
724 signalled. */
725 if (mutex_is_valid) {
726 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
727 pthread_mutex_t*,mutex);
728 }
729
730 CALL_FN_W_WWW(ret, fn, cond,mutex,abstime);
731
732 if ((ret == 0 || ret == ETIMEDOUT) && mutex_is_valid) {
733 /* and now we have the mutex again */
734 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
735 pthread_mutex_t*,mutex);
736 }
737
738 if (ret == 0 && mutex_is_valid) {
739 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_COND_WAIT_POST,
740 pthread_cond_t*,cond, pthread_mutex_t*,mutex);
741 }
742
743 if (ret != 0 && ret != ETIMEDOUT) {
744 DO_PthAPIerror( "pthread_cond_timedwait", ret );
745 }
746
747 if (TRACE_PTH_FNS) {
748 fprintf(stderr, " cotimedwait -> %d >>\n", ret);
749 }
750
751 return ret;
752}
sewardj1c147ff2009-07-26 19:52:06 +0000753#if defined(VGO_linux)
754 PTH_FUNC(int, pthreadZucondZutimedwaitZAZa, // pthread_cond_timedwait@*
755 pthread_cond_t* cond, pthread_mutex_t* mutex,
756 struct timespec* abstime) {
757 return pthread_cond_timedwait_WRK(cond, mutex, abstime);
758 }
759#elif defined(VGO_darwin)
760 PTH_FUNC(int, pthreadZucondZutimedwait, // pthread_cond_timedwait
761 pthread_cond_t* cond, pthread_mutex_t* mutex,
762 struct timespec* abstime) {
763 return pthread_cond_timedwait_WRK(cond, mutex, abstime);
764 }
765 PTH_FUNC(int, pthreadZucondZutimedwaitZDZa, // pthread_cond_timedwait$*
766 pthread_cond_t* cond, pthread_mutex_t* mutex,
767 struct timespec* abstime) {
768 return pthread_cond_timedwait_WRK(cond, mutex, abstime);
769 }
770 PTH_FUNC(int, pthreadZucondZutimedwaitZuZa, // pthread_cond_timedwait_*
771 pthread_cond_t* cond, pthread_mutex_t* mutex,
772 struct timespec* abstime) {
773 assert(0);
774 }
775#else
776# error "Unsupported OS"
777#endif
sewardjb4112022007-11-09 22:49:28 +0000778
779
sewardj1c147ff2009-07-26 19:52:06 +0000780//-----------------------------------------------------------
781// glibc: pthread_cond_signal@GLIBC_2.0
782// glibc: pthread_cond_signal@GLIBC_2.2.5
783// glibc: pthread_cond_signal@@GLIBC_2.3.2
784// darwin: pthread_cond_signal
785// darwin: pthread_cond_signal_thread_np (don't intercept this)
786//
787static int pthread_cond_signal_WRK(pthread_cond_t* cond)
sewardjb4112022007-11-09 22:49:28 +0000788{
789 int ret;
790 OrigFn fn;
791 VALGRIND_GET_ORIG_FN(fn);
792
793 if (TRACE_PTH_FNS) {
794 fprintf(stderr, "<< pthread_cond_signal %p", cond);
795 fflush(stderr);
796 }
797
798 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_SIGNAL_PRE,
799 pthread_cond_t*,cond);
800
801 CALL_FN_W_W(ret, fn, cond);
802
803 if (ret != 0) {
804 DO_PthAPIerror( "pthread_cond_signal", ret );
805 }
806
807 if (TRACE_PTH_FNS) {
808 fprintf(stderr, " cosig -> %d >>\n", ret);
809 }
810
811 return ret;
812}
sewardj1c147ff2009-07-26 19:52:06 +0000813#if defined(VGO_linux)
814 PTH_FUNC(int, pthreadZucondZusignalZAZa, // pthread_cond_signal@*
815 pthread_cond_t* cond) {
816 return pthread_cond_signal_WRK(cond);
817 }
818#elif defined(VGO_darwin)
819 PTH_FUNC(int, pthreadZucondZusignal, // pthread_cond_signal
820 pthread_cond_t* cond) {
821 return pthread_cond_signal_WRK(cond);
822 }
823#else
824# error "Unsupported OS"
825#endif
sewardjb4112022007-11-09 22:49:28 +0000826
827
sewardj1c147ff2009-07-26 19:52:06 +0000828//-----------------------------------------------------------
829// glibc: pthread_cond_broadcast@GLIBC_2.0
830// glibc: pthread_cond_broadcast@GLIBC_2.2.5
831// glibc: pthread_cond_broadcast@@GLIBC_2.3.2
832// darwin: pthread_cond_broadcast
833//
sewardjb4112022007-11-09 22:49:28 +0000834// Note, this is pretty much identical, from a dependency-graph
835// point of view, with cond_signal, so the code is duplicated.
836// Maybe it should be commoned up.
sewardj1c147ff2009-07-26 19:52:06 +0000837//
838static int pthread_cond_broadcast_WRK(pthread_cond_t* cond)
sewardjb4112022007-11-09 22:49:28 +0000839{
840 int ret;
841 OrigFn fn;
842 VALGRIND_GET_ORIG_FN(fn);
843
844 if (TRACE_PTH_FNS) {
sewardj1c147ff2009-07-26 19:52:06 +0000845 fprintf(stderr, "<< pthread_cond_broadcast %p", cond);
sewardjb4112022007-11-09 22:49:28 +0000846 fflush(stderr);
847 }
848
849 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_BROADCAST_PRE,
850 pthread_cond_t*,cond);
851
852 CALL_FN_W_W(ret, fn, cond);
853
854 if (ret != 0) {
855 DO_PthAPIerror( "pthread_cond_broadcast", ret );
856 }
857
858 if (TRACE_PTH_FNS) {
859 fprintf(stderr, " cobro -> %d >>\n", ret);
860 }
861
862 return ret;
863}
sewardj1c147ff2009-07-26 19:52:06 +0000864#if defined(VGO_linux)
865 PTH_FUNC(int, pthreadZucondZubroadcastZAZa, // pthread_cond_broadcast@*
866 pthread_cond_t* cond) {
867 return pthread_cond_broadcast_WRK(cond);
868 }
869#elif defined(VGO_darwin)
870 PTH_FUNC(int, pthreadZucondZubroadcast, // pthread_cond_broadcast
871 pthread_cond_t* cond) {
872 return pthread_cond_broadcast_WRK(cond);
873 }
874#else
875# error "Unsupported OS"
876#endif
sewardjb4112022007-11-09 22:49:28 +0000877
878
sewardj1c147ff2009-07-26 19:52:06 +0000879//-----------------------------------------------------------
880// glibc: pthread_cond_destroy@@GLIBC_2.3.2
881// glibc: pthread_cond_destroy@GLIBC_2.2.5
882// glibc: pthread_cond_destroy@GLIBC_2.0
883// darwin: pthread_cond_destroy
884//
885static int pthread_cond_destroy_WRK(pthread_cond_t* cond)
sewardjf98e1c02008-10-25 16:22:41 +0000886{
887 int ret;
888 OrigFn fn;
889
890 VALGRIND_GET_ORIG_FN(fn);
891
892 if (TRACE_PTH_FNS) {
893 fprintf(stderr, "<< pthread_cond_destroy %p", cond);
894 fflush(stderr);
895 }
896
897 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_COND_DESTROY_PRE,
898 pthread_cond_t*,cond);
899
900 CALL_FN_W_W(ret, fn, cond);
901
902 if (ret != 0) {
903 DO_PthAPIerror( "pthread_cond_destroy", ret );
904 }
905
906 if (TRACE_PTH_FNS) {
907 fprintf(stderr, " codestr -> %d >>\n", ret);
908 }
909
910 return ret;
911}
sewardj1c147ff2009-07-26 19:52:06 +0000912#if defined(VGO_linux)
913 PTH_FUNC(int, pthreadZucondZudestroyZAZa, // pthread_cond_destroy@*
914 pthread_cond_t* cond) {
915 return pthread_cond_destroy_WRK(cond);
916 }
917#elif defined(VGO_darwin)
918 PTH_FUNC(int, pthreadZucondZudestroy, // pthread_cond_destroy
919 pthread_cond_t* cond) {
920 return pthread_cond_destroy_WRK(cond);
921 }
922#else
923# error "Unsupported OS"
924#endif
sewardjf98e1c02008-10-25 16:22:41 +0000925
926
927/*----------------------------------------------------------------*/
928/*--- pthread_barrier_t functions ---*/
929/*----------------------------------------------------------------*/
930
njnf76d27a2009-05-28 01:53:07 +0000931#if defined(HAVE_PTHREAD_BARRIER_INIT)
932
sewardj9f569b72008-11-13 13:33:09 +0000933/* Handled: pthread_barrier_init
934 pthread_barrier_wait
935 pthread_barrier_destroy
936
937 Unhandled: pthread_barrierattr_destroy
938 pthread_barrierattr_getpshared
939 pthread_barrierattr_init
940 pthread_barrierattr_setpshared
941 -- are these important?
942*/
943
sewardj1c147ff2009-07-26 19:52:06 +0000944//-----------------------------------------------------------
945// glibc: pthread_barrier_init
946// darwin: (doesn't appear to exist)
sewardj9f569b72008-11-13 13:33:09 +0000947PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init
948 pthread_barrier_t* bar,
949 pthread_barrierattr_t* attr, unsigned long count)
sewardjf98e1c02008-10-25 16:22:41 +0000950{
951 int ret;
952 OrigFn fn;
953 VALGRIND_GET_ORIG_FN(fn);
954
955 if (TRACE_PTH_FNS) {
sewardj9f569b72008-11-13 13:33:09 +0000956 fprintf(stderr, "<< pthread_barrier_init %p %p %lu",
957 bar, attr, count);
sewardjf98e1c02008-10-25 16:22:41 +0000958 fflush(stderr);
959 }
960
sewardj9f569b72008-11-13 13:33:09 +0000961 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_BARRIER_INIT_PRE,
962 pthread_barrier_t*,bar,
963 unsigned long,count);
sewardjf98e1c02008-10-25 16:22:41 +0000964
sewardj9f569b72008-11-13 13:33:09 +0000965 CALL_FN_W_WWW(ret, fn, bar,attr,count);
sewardjf98e1c02008-10-25 16:22:41 +0000966
sewardj9f569b72008-11-13 13:33:09 +0000967 if (ret != 0) {
968 DO_PthAPIerror( "pthread_barrier_init", ret );
969 }
970
971 if (TRACE_PTH_FNS) {
972 fprintf(stderr, " pthread_barrier_init -> %d >>\n", ret);
973 }
974
975 return ret;
976}
977
978
sewardj1c147ff2009-07-26 19:52:06 +0000979//-----------------------------------------------------------
980// glibc: pthread_barrier_wait
981// darwin: (doesn't appear to exist)
sewardj9f569b72008-11-13 13:33:09 +0000982PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait
983 pthread_barrier_t* bar)
984{
985 int ret;
986 OrigFn fn;
987 VALGRIND_GET_ORIG_FN(fn);
988
989 if (TRACE_PTH_FNS) {
990 fprintf(stderr, "<< pthread_barrier_wait %p", bar);
991 fflush(stderr);
992 }
993
994 /* That this works correctly, and doesn't screw up when a thread
995 leaving the barrier races round to the front and re-enters while
996 other threads are still leaving it, is quite subtle. See
997 comments in the handler for PTHREAD_BARRIER_WAIT_PRE in
998 hg_main.c. */
999 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_WAIT_PRE,
1000 pthread_barrier_t*,bar);
1001
1002 CALL_FN_W_W(ret, fn, bar);
1003
1004 if (ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD) {
1005 DO_PthAPIerror( "pthread_barrier_wait", ret );
1006 }
sewardjf98e1c02008-10-25 16:22:41 +00001007
1008 if (TRACE_PTH_FNS) {
1009 fprintf(stderr, " pthread_barrier_wait -> %d >>\n", ret);
1010 }
1011
1012 return ret;
1013}
1014
1015
sewardj1c147ff2009-07-26 19:52:06 +00001016//-----------------------------------------------------------
1017// glibc: pthread_barrier_destroy
1018// darwin: (doesn't appear to exist)
sewardj9f569b72008-11-13 13:33:09 +00001019PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy
1020 pthread_barrier_t* bar)
1021{
1022 int ret;
1023 OrigFn fn;
1024 VALGRIND_GET_ORIG_FN(fn);
1025
1026 if (TRACE_PTH_FNS) {
1027 fprintf(stderr, "<< pthread_barrier_destroy %p", bar);
1028 fflush(stderr);
1029 }
1030
1031 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_BARRIER_DESTROY_PRE,
1032 pthread_barrier_t*,bar);
1033
1034 CALL_FN_W_W(ret, fn, bar);
1035
1036 if (ret != 0) {
1037 DO_PthAPIerror( "pthread_barrier_destroy", ret );
1038 }
1039
1040 if (TRACE_PTH_FNS) {
1041 fprintf(stderr, " pthread_barrier_destroy -> %d >>\n", ret);
1042 }
1043
1044 return ret;
1045}
sewardjf98e1c02008-10-25 16:22:41 +00001046
njnf76d27a2009-05-28 01:53:07 +00001047#endif // defined(HAVE_PTHREAD_BARRIER_INIT)
1048
sewardjb4112022007-11-09 22:49:28 +00001049/*----------------------------------------------------------------*/
1050/*--- pthread_rwlock_t functions ---*/
1051/*----------------------------------------------------------------*/
1052
1053/* Handled: pthread_rwlock_init pthread_rwlock_destroy
1054 pthread_rwlock_rdlock
1055 pthread_rwlock_wrlock
1056 pthread_rwlock_unlock
1057
1058 Unhandled: pthread_rwlock_timedrdlock
1059 pthread_rwlock_tryrdlock
1060
1061 pthread_rwlock_timedwrlock
1062 pthread_rwlock_trywrlock
1063*/
1064
sewardj1c147ff2009-07-26 19:52:06 +00001065//-----------------------------------------------------------
1066// glibc: pthread_rwlock_init
1067// darwin: pthread_rwlock_init
1068// darwin: pthread_rwlock_init$UNIX2003
1069static int pthread_rwlock_init_WRK(pthread_rwlock_t *rwl,
1070 pthread_rwlockattr_t* attr)
sewardjb4112022007-11-09 22:49:28 +00001071{
1072 int ret;
1073 OrigFn fn;
1074 VALGRIND_GET_ORIG_FN(fn);
1075 if (TRACE_PTH_FNS) {
1076 fprintf(stderr, "<< pthread_rwl_init %p", rwl); fflush(stderr);
1077 }
1078
1079 CALL_FN_W_WW(ret, fn, rwl,attr);
1080
1081 if (ret == 0 /*success*/) {
1082 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST,
1083 pthread_rwlock_t*,rwl);
1084 } else {
1085 DO_PthAPIerror( "pthread_rwlock_init", ret );
1086 }
1087
1088 if (TRACE_PTH_FNS) {
1089 fprintf(stderr, " :: rwl_init -> %d >>\n", ret);
1090 }
1091 return ret;
1092}
sewardj1c147ff2009-07-26 19:52:06 +00001093#if defined(VGO_linux)
1094 PTH_FUNC(int, pthreadZurwlockZuinit, // pthread_rwlock_init
1095 pthread_rwlock_t *rwl,
1096 pthread_rwlockattr_t* attr) {
1097 return pthread_rwlock_init_WRK(rwl, attr);
1098 }
1099#elif defined(VGO_darwin)
1100 PTH_FUNC(int, pthreadZurwlockZuinitZa, // pthread_rwlock_init*
1101 pthread_rwlock_t *rwl,
1102 pthread_rwlockattr_t* attr) {
1103 return pthread_rwlock_init_WRK(rwl, attr);
1104 }
1105#else
1106# error "Unsupported OS"
1107#endif
sewardjb4112022007-11-09 22:49:28 +00001108
1109
sewardj1c147ff2009-07-26 19:52:06 +00001110//-----------------------------------------------------------
1111// glibc: pthread_rwlock_destroy
1112// darwin: pthread_rwlock_destroy
1113// darwin: pthread_rwlock_destroy$UNIX2003
1114//
1115static int pthread_rwlock_destroy_WRK(pthread_rwlock_t* rwl)
sewardjb4112022007-11-09 22:49:28 +00001116{
1117 int ret;
1118 OrigFn fn;
1119 VALGRIND_GET_ORIG_FN(fn);
1120 if (TRACE_PTH_FNS) {
1121 fprintf(stderr, "<< pthread_rwl_destroy %p", rwl); fflush(stderr);
1122 }
1123
1124 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE,
1125 pthread_rwlock_t*,rwl);
1126
1127 CALL_FN_W_W(ret, fn, rwl);
1128
1129 if (ret != 0) {
1130 DO_PthAPIerror( "pthread_rwlock_destroy", ret );
1131 }
1132
1133 if (TRACE_PTH_FNS) {
1134 fprintf(stderr, " :: rwl_destroy -> %d >>\n", ret);
1135 }
1136 return ret;
1137}
sewardj1c147ff2009-07-26 19:52:06 +00001138#if defined(VGO_linux)
1139 PTH_FUNC(int, pthreadZurwlockZudestroy, // pthread_rwlock_destroy
1140 pthread_rwlock_t *rwl) {
1141 return pthread_rwlock_destroy_WRK(rwl);
1142 }
1143#elif defined(VGO_darwin)
1144 PTH_FUNC(int, pthreadZurwlockZudestroyZa, // pthread_rwlock_destroy*
1145 pthread_rwlock_t *rwl) {
1146 return pthread_rwlock_destroy_WRK(rwl);
1147 }
1148#else
1149# error "Unsupported OS"
1150#endif
sewardjb4112022007-11-09 22:49:28 +00001151
1152
sewardj1c147ff2009-07-26 19:52:06 +00001153//-----------------------------------------------------------
1154// glibc: pthread_rwlock_wrlock
1155// darwin: pthread_rwlock_wrlock
1156// darwin: pthread_rwlock_wrlock$UNIX2003
1157//
1158static int pthread_rwlock_wrlock_WRK(pthread_rwlock_t* rwlock)
sewardjb4112022007-11-09 22:49:28 +00001159{
1160 int ret;
1161 OrigFn fn;
1162 VALGRIND_GET_ORIG_FN(fn);
1163 if (TRACE_PTH_FNS) {
1164 fprintf(stderr, "<< pthread_rwl_wlk %p", rwlock); fflush(stderr);
1165 }
1166
sewardj789c3c52008-02-25 12:10:07 +00001167 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1168 pthread_rwlock_t*,rwlock,
1169 long,1/*isW*/, long,0/*!isTryLock*/);
sewardjb4112022007-11-09 22:49:28 +00001170
1171 CALL_FN_W_W(ret, fn, rwlock);
1172
1173 if (ret == 0 /*success*/) {
1174 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1175 pthread_rwlock_t*,rwlock, long,1/*isW*/);
1176 } else {
1177 DO_PthAPIerror( "pthread_rwlock_wrlock", ret );
1178 }
1179
1180 if (TRACE_PTH_FNS) {
1181 fprintf(stderr, " :: rwl_wlk -> %d >>\n", ret);
1182 }
1183 return ret;
1184}
sewardj1c147ff2009-07-26 19:52:06 +00001185#if defined(VGO_linux)
1186 PTH_FUNC(int, pthreadZurwlockZuwrlock, // pthread_rwlock_wrlock
1187 pthread_rwlock_t* rwlock) {
1188 return pthread_rwlock_wrlock_WRK(rwlock);
1189 }
1190#elif defined(VGO_darwin)
1191 PTH_FUNC(int, pthreadZurwlockZuwrlockZa, // pthread_rwlock_wrlock*
1192 pthread_rwlock_t* rwlock) {
1193 return pthread_rwlock_wrlock_WRK(rwlock);
1194 }
1195#else
1196# error "Unsupported OS"
1197#endif
sewardjb4112022007-11-09 22:49:28 +00001198
1199
sewardj1c147ff2009-07-26 19:52:06 +00001200//-----------------------------------------------------------
1201// glibc: pthread_rwlock_rdlock
1202// darwin: pthread_rwlock_rdlock
1203// darwin: pthread_rwlock_rdlock$UNIX2003
1204//
1205static int pthread_rwlock_rdlock_WRK(pthread_rwlock_t* rwlock)
sewardjb4112022007-11-09 22:49:28 +00001206{
1207 int ret;
1208 OrigFn fn;
1209 VALGRIND_GET_ORIG_FN(fn);
1210 if (TRACE_PTH_FNS) {
1211 fprintf(stderr, "<< pthread_rwl_rlk %p", rwlock); fflush(stderr);
1212 }
1213
sewardj789c3c52008-02-25 12:10:07 +00001214 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1215 pthread_rwlock_t*,rwlock,
1216 long,0/*!isW*/, long,0/*!isTryLock*/);
sewardjb4112022007-11-09 22:49:28 +00001217
1218 CALL_FN_W_W(ret, fn, rwlock);
1219
1220 if (ret == 0 /*success*/) {
1221 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1222 pthread_rwlock_t*,rwlock, long,0/*!isW*/);
1223 } else {
1224 DO_PthAPIerror( "pthread_rwlock_rdlock", ret );
1225 }
1226
1227 if (TRACE_PTH_FNS) {
1228 fprintf(stderr, " :: rwl_rlk -> %d >>\n", ret);
1229 }
1230 return ret;
1231}
sewardj1c147ff2009-07-26 19:52:06 +00001232#if defined(VGO_linux)
1233 PTH_FUNC(int, pthreadZurwlockZurdlock, // pthread_rwlock_rdlock
1234 pthread_rwlock_t* rwlock) {
1235 return pthread_rwlock_rdlock_WRK(rwlock);
1236 }
1237#elif defined(VGO_darwin)
1238 PTH_FUNC(int, pthreadZurwlockZurdlockZa, // pthread_rwlock_rdlock*
1239 pthread_rwlock_t* rwlock) {
1240 return pthread_rwlock_rdlock_WRK(rwlock);
1241 }
1242#else
1243# error "Unsupported OS"
1244#endif
sewardjb4112022007-11-09 22:49:28 +00001245
1246
sewardj1c147ff2009-07-26 19:52:06 +00001247//-----------------------------------------------------------
1248// glibc: pthread_rwlock_trywrlock
1249// darwin: pthread_rwlock_trywrlock
1250// darwin: pthread_rwlock_trywrlock$UNIX2003
1251//
1252static int pthread_rwlock_trywrlock_WRK(pthread_rwlock_t* rwlock)
sewardj789c3c52008-02-25 12:10:07 +00001253{
1254 int ret;
1255 OrigFn fn;
1256 VALGRIND_GET_ORIG_FN(fn);
1257 if (TRACE_PTH_FNS) {
1258 fprintf(stderr, "<< pthread_rwl_trywlk %p", rwlock); fflush(stderr);
1259 }
1260
1261 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1262 pthread_rwlock_t*,rwlock,
1263 long,1/*isW*/, long,1/*isTryLock*/);
1264
1265 CALL_FN_W_W(ret, fn, rwlock);
1266
1267 /* There's a hole here: libpthread now knows the lock is locked,
1268 but the tool doesn't, so some other thread could run and detect
1269 that the lock has been acquired by someone (this thread). Does
1270 this matter? Not sure, but I don't think so. */
1271
1272 if (ret == 0 /*success*/) {
1273 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1274 pthread_rwlock_t*,rwlock, long,1/*isW*/);
1275 } else {
1276 if (ret != EBUSY)
1277 DO_PthAPIerror( "pthread_rwlock_trywrlock", ret );
1278 }
1279
1280 if (TRACE_PTH_FNS) {
1281 fprintf(stderr, " :: rwl_trywlk -> %d >>\n", ret);
1282 }
1283 return ret;
1284}
sewardj1c147ff2009-07-26 19:52:06 +00001285#if defined(VGO_linux)
1286 PTH_FUNC(int, pthreadZurwlockZutrywrlock, // pthread_rwlock_trywrlock
1287 pthread_rwlock_t* rwlock) {
1288 return pthread_rwlock_trywrlock_WRK(rwlock);
1289 }
1290#elif defined(VGO_darwin)
1291 PTH_FUNC(int, pthreadZurwlockZutrywrlockZa, // pthread_rwlock_trywrlock*
1292 pthread_rwlock_t* rwlock) {
1293 return pthread_rwlock_trywrlock_WRK(rwlock);
1294 }
1295#else
1296# error "Unsupported OS"
1297#endif
sewardj789c3c52008-02-25 12:10:07 +00001298
1299
sewardj1c147ff2009-07-26 19:52:06 +00001300//-----------------------------------------------------------
1301// glibc: pthread_rwlock_tryrdlock
1302// darwin: pthread_rwlock_trywrlock
1303// darwin: pthread_rwlock_trywrlock$UNIX2003
1304//
1305static int pthread_rwlock_tryrdlock_WRK(pthread_rwlock_t* rwlock)
sewardj789c3c52008-02-25 12:10:07 +00001306{
1307 int ret;
1308 OrigFn fn;
1309 VALGRIND_GET_ORIG_FN(fn);
1310 if (TRACE_PTH_FNS) {
1311 fprintf(stderr, "<< pthread_rwl_tryrlk %p", rwlock); fflush(stderr);
1312 }
1313
1314 DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1315 pthread_rwlock_t*,rwlock,
1316 long,0/*!isW*/, long,1/*isTryLock*/);
1317
1318 CALL_FN_W_W(ret, fn, rwlock);
1319
1320 /* There's a hole here: libpthread now knows the lock is locked,
1321 but the tool doesn't, so some other thread could run and detect
1322 that the lock has been acquired by someone (this thread). Does
1323 this matter? Not sure, but I don't think so. */
1324
1325 if (ret == 0 /*success*/) {
1326 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1327 pthread_rwlock_t*,rwlock, long,0/*!isW*/);
1328 } else {
1329 if (ret != EBUSY)
1330 DO_PthAPIerror( "pthread_rwlock_tryrdlock", ret );
1331 }
1332
1333 if (TRACE_PTH_FNS) {
1334 fprintf(stderr, " :: rwl_tryrlk -> %d >>\n", ret);
1335 }
1336 return ret;
1337}
sewardj1c147ff2009-07-26 19:52:06 +00001338#if defined(VGO_linux)
1339 PTH_FUNC(int, pthreadZurwlockZutryrdlock, // pthread_rwlock_tryrdlock
1340 pthread_rwlock_t* rwlock) {
1341 return pthread_rwlock_tryrdlock_WRK(rwlock);
1342 }
1343#elif defined(VGO_darwin)
1344 PTH_FUNC(int, pthreadZurwlockZutryrdlockZa, // pthread_rwlock_tryrdlock*
1345 pthread_rwlock_t* rwlock) {
1346 return pthread_rwlock_tryrdlock_WRK(rwlock);
1347 }
1348#else
1349# error "Unsupported OS"
1350#endif
sewardj789c3c52008-02-25 12:10:07 +00001351
1352
sewardj1c147ff2009-07-26 19:52:06 +00001353//-----------------------------------------------------------
1354// glibc: pthread_rwlock_unlock
1355// darwin: pthread_rwlock_unlock
1356// darwin: pthread_rwlock_unlock$UNIX2003
1357static int pthread_rwlock_unlock_WRK(pthread_rwlock_t* rwlock)
sewardjb4112022007-11-09 22:49:28 +00001358{
1359 int ret;
1360 OrigFn fn;
1361 VALGRIND_GET_ORIG_FN(fn);
1362 if (TRACE_PTH_FNS) {
1363 fprintf(stderr, "<< pthread_rwl_unlk %p", rwlock); fflush(stderr);
1364 }
1365
1366 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE,
1367 pthread_rwlock_t*,rwlock);
1368
1369 CALL_FN_W_W(ret, fn, rwlock);
1370
1371 if (ret == 0 /*success*/) {
1372 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST,
1373 pthread_rwlock_t*,rwlock);
1374 } else {
1375 DO_PthAPIerror( "pthread_rwlock_unlock", ret );
1376 }
1377
1378 if (TRACE_PTH_FNS) {
1379 fprintf(stderr, " :: rwl_unlk -> %d >>\n", ret);
1380 }
1381 return ret;
1382}
sewardj1c147ff2009-07-26 19:52:06 +00001383#if defined(VGO_linux)
1384 PTH_FUNC(int, pthreadZurwlockZuunlock, // pthread_rwlock_unlock
1385 pthread_rwlock_t* rwlock) {
1386 return pthread_rwlock_unlock_WRK(rwlock);
1387 }
1388#elif defined(VGO_darwin)
1389 PTH_FUNC(int, pthreadZurwlockZuunlockZa, // pthread_rwlock_unlock*
1390 pthread_rwlock_t* rwlock) {
1391 return pthread_rwlock_unlock_WRK(rwlock);
1392 }
1393#else
1394# error "Unsupported OS"
1395#endif
sewardjb4112022007-11-09 22:49:28 +00001396
1397
1398/*----------------------------------------------------------------*/
1399/*--- POSIX semaphores ---*/
1400/*----------------------------------------------------------------*/
1401
1402#include <semaphore.h>
1403
1404#define TRACE_SEM_FNS 0
1405
1406/* Handled:
1407 int sem_init(sem_t *sem, int pshared, unsigned value);
1408 int sem_destroy(sem_t *sem);
1409 int sem_wait(sem_t *sem);
1410 int sem_post(sem_t *sem);
sewardj1c147ff2009-07-26 19:52:06 +00001411 sem_t* sem_open(const char *name, int oflag,
1412 ... [mode_t mode, unsigned value]);
1413 [complete with its idiotic semantics]
1414 int sem_close(sem_t* sem);
sewardjb4112022007-11-09 22:49:28 +00001415
1416 Unhandled:
1417 int sem_trywait(sem_t *sem);
1418 int sem_timedwait(sem_t *restrict sem,
1419 const struct timespec *restrict abs_timeout);
1420*/
1421
sewardj1c147ff2009-07-26 19:52:06 +00001422//-----------------------------------------------------------
1423// glibc: sem_init@@GLIBC_2.2.5
1424// glibc: sem_init@@GLIBC_2.1
1425// glibc: sem_init@GLIBC_2.0
1426// darwin: sem_init
1427//
1428static int sem_init_WRK(sem_t* sem, int pshared, unsigned long value)
sewardjb4112022007-11-09 22:49:28 +00001429{
1430 OrigFn fn;
1431 int ret;
1432 VALGRIND_GET_ORIG_FN(fn);
1433
1434 if (TRACE_SEM_FNS) {
1435 fprintf(stderr, "<< sem_init(%p,%d,%lu) ", sem,pshared,value);
1436 fflush(stderr);
1437 }
1438
1439 CALL_FN_W_WWW(ret, fn, sem,pshared,value);
1440
1441 if (ret == 0) {
sewardj11e352f2007-11-30 11:11:02 +00001442 DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST,
1443 sem_t*, sem, unsigned long, value);
sewardjb4112022007-11-09 22:49:28 +00001444 } else {
1445 DO_PthAPIerror( "sem_init", errno );
1446 }
1447
1448 if (TRACE_SEM_FNS) {
1449 fprintf(stderr, " sem_init -> %d >>\n", ret);
1450 fflush(stderr);
1451 }
1452
1453 return ret;
1454}
sewardj1c147ff2009-07-26 19:52:06 +00001455#if defined(VGO_linux)
1456 PTH_FUNC(int, semZuinitZAZa, // sem_init@*
1457 sem_t* sem, int pshared, unsigned long value) {
1458 return sem_init_WRK(sem, pshared, value);
1459 }
1460#elif defined(VGO_darwin)
1461 PTH_FUNC(int, semZuinit, // sem_init
1462 sem_t* sem, int pshared, unsigned long value) {
1463 return sem_init_WRK(sem, pshared, value);
1464 }
1465#else
1466# error "Unsupported OS"
1467#endif
sewardjb4112022007-11-09 22:49:28 +00001468
1469
sewardj1c147ff2009-07-26 19:52:06 +00001470//-----------------------------------------------------------
1471// glibc: sem_destroy@GLIBC_2.0
1472// glibc: sem_destroy@@GLIBC_2.1
1473// glibc: sem_destroy@@GLIBC_2.2.5
1474// darwin: sem_destroy
1475static int sem_destroy_WRK(sem_t* sem)
sewardjb4112022007-11-09 22:49:28 +00001476{
1477 OrigFn fn;
1478 int ret;
1479 VALGRIND_GET_ORIG_FN(fn);
1480
1481 if (TRACE_SEM_FNS) {
1482 fprintf(stderr, "<< sem_destroy(%p) ", sem);
1483 fflush(stderr);
1484 }
1485
sewardj11e352f2007-11-30 11:11:02 +00001486 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, sem_t*, sem);
sewardjb4112022007-11-09 22:49:28 +00001487
1488 CALL_FN_W_W(ret, fn, sem);
1489
1490 if (ret != 0) {
1491 DO_PthAPIerror( "sem_destroy", errno );
1492 }
1493
1494 if (TRACE_SEM_FNS) {
1495 fprintf(stderr, " sem_destroy -> %d >>\n", ret);
1496 fflush(stderr);
1497 }
1498
1499 return ret;
1500}
sewardj1c147ff2009-07-26 19:52:06 +00001501#if defined(VGO_linux)
1502 PTH_FUNC(int, semZudestroyZAZa, // sem_destroy*
1503 sem_t* sem) {
1504 return sem_destroy_WRK(sem);
1505 }
1506#elif defined(VGO_darwin)
1507 PTH_FUNC(int, semZudestroy, // sem_destroy
1508 sem_t* sem) {
1509 return sem_destroy_WRK(sem);
1510 }
1511#else
1512# error "Unsupported OS"
1513#endif
sewardjb4112022007-11-09 22:49:28 +00001514
1515
sewardj1c147ff2009-07-26 19:52:06 +00001516//-----------------------------------------------------------
1517// glibc: sem_wait
1518// glibc: sem_wait@GLIBC_2.0
1519// glibc: sem_wait@@GLIBC_2.1
1520// darwin: sem_wait
1521// darwin: sem_wait$NOCANCEL$UNIX2003
1522// darwin: sem_wait$UNIX2003
1523//
sewardjb4112022007-11-09 22:49:28 +00001524/* wait: decrement semaphore - acquire lockage */
1525static int sem_wait_WRK(sem_t* sem)
1526{
1527 OrigFn fn;
1528 int ret;
1529 VALGRIND_GET_ORIG_FN(fn);
1530
1531 if (TRACE_SEM_FNS) {
1532 fprintf(stderr, "<< sem_wait(%p) ", sem);
1533 fflush(stderr);
1534 }
1535
1536 CALL_FN_W_W(ret, fn, sem);
1537
1538 if (ret == 0) {
sewardj11e352f2007-11-30 11:11:02 +00001539 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_WAIT_POST, sem_t*,sem);
sewardjb4112022007-11-09 22:49:28 +00001540 } else {
1541 DO_PthAPIerror( "sem_wait", errno );
1542 }
1543
1544 if (TRACE_SEM_FNS) {
1545 fprintf(stderr, " sem_wait -> %d >>\n", ret);
1546 fflush(stderr);
1547 }
1548
1549 return ret;
1550}
sewardj1c147ff2009-07-26 19:52:06 +00001551#if defined(VGO_linux)
1552 PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */
1553 return sem_wait_WRK(sem);
1554 }
1555 PTH_FUNC(int, semZuwaitZAZa, sem_t* sem) { /* sem_wait@* */
1556 return sem_wait_WRK(sem);
1557 }
1558#elif defined(VGO_darwin)
1559 PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */
1560 return sem_wait_WRK(sem);
1561 }
1562 PTH_FUNC(int, semZuwaitZDZa, sem_t* sem) { /* sem_wait$* */
1563 return sem_wait_WRK(sem);
1564 }
1565#else
1566# error "Unsupported OS"
1567#endif
sewardjb4112022007-11-09 22:49:28 +00001568
1569
sewardj1c147ff2009-07-26 19:52:06 +00001570//-----------------------------------------------------------
1571// glibc: sem_post
1572// glibc: sem_post@GLIBC_2.0
1573// glibc: sem_post@@GLIBC_2.1
1574// darwin: sem_post
1575//
sewardjb4112022007-11-09 22:49:28 +00001576/* post: increment semaphore - release lockage */
1577static int sem_post_WRK(sem_t* sem)
1578{
1579 OrigFn fn;
1580 int ret;
1581
1582 VALGRIND_GET_ORIG_FN(fn);
1583
1584 if (TRACE_SEM_FNS) {
1585 fprintf(stderr, "<< sem_post(%p) ", sem);
1586 fflush(stderr);
1587 }
1588
sewardj11e352f2007-11-30 11:11:02 +00001589 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_POST_PRE, sem_t*,sem);
sewardjb4112022007-11-09 22:49:28 +00001590
1591 CALL_FN_W_W(ret, fn, sem);
1592
1593 if (ret != 0) {
1594 DO_PthAPIerror( "sem_post", errno );
1595 }
1596
1597 if (TRACE_SEM_FNS) {
1598 fprintf(stderr, " sem_post -> %d >>\n", ret);
1599 fflush(stderr);
1600 }
1601
1602 return ret;
1603}
sewardj1c147ff2009-07-26 19:52:06 +00001604#if defined(VGO_linux)
1605 PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */
1606 return sem_post_WRK(sem);
1607 }
1608 PTH_FUNC(int, semZupostZAZa, sem_t* sem) { /* sem_post@* */
1609 return sem_post_WRK(sem);
1610 }
1611#elif defined(VGO_darwin)
1612 PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */
1613 return sem_post_WRK(sem);
1614 }
1615#else
1616# error "Unsupported OS"
1617#endif
1618
1619
1620//-----------------------------------------------------------
1621// glibc: sem_open
1622// darwin: sem_open
1623//
1624PTH_FUNC(sem_t*, semZuopen,
1625 const char* name, long oflag,
1626 long mode, unsigned long value)
1627{
1628 /* A copy of sem_init_WRK (more or less). Is this correct? */
1629 OrigFn fn;
1630 sem_t* ret;
1631 VALGRIND_GET_ORIG_FN(fn);
1632
1633 if (TRACE_SEM_FNS) {
1634 fprintf(stderr, "<< sem_open(\"%s\",%ld,%lx,%lu) ",
1635 name,oflag,mode,value);
1636 fflush(stderr);
1637 }
1638
1639 CALL_FN_W_WWWW(ret, fn, name,oflag,mode,value);
1640
1641 if (ret != SEM_FAILED && (oflag & O_CREAT)) {
1642 DO_CREQ_v_WW(_VG_USERREQ__HG_POSIX_SEM_INIT_POST,
1643 sem_t*, ret, unsigned long, value);
1644 }
1645 if (ret == SEM_FAILED) {
1646 DO_PthAPIerror( "sem_open", errno );
1647 }
1648
1649 if (TRACE_SEM_FNS) {
1650 fprintf(stderr, " sem_open -> %p >>\n", ret);
1651 fflush(stderr);
1652 }
1653
1654 return ret;
sewardjb4112022007-11-09 22:49:28 +00001655}
1656
1657
sewardj1c147ff2009-07-26 19:52:06 +00001658//-----------------------------------------------------------
1659// glibc: sem_close
1660// darwin: sem_close
1661PTH_FUNC(int, sem_close, sem_t* sem)
1662{
1663 OrigFn fn;
1664 int ret;
1665 VALGRIND_GET_ORIG_FN(fn);
1666
1667 if (TRACE_SEM_FNS) {
1668 fprintf(stderr, "<< sem_close(%p) ", sem);
1669 fflush(stderr);
1670 }
1671
1672 DO_CREQ_v_W(_VG_USERREQ__HG_POSIX_SEM_DESTROY_PRE, sem_t*, sem);
1673
1674 CALL_FN_W_W(ret, fn, sem);
1675
1676 if (ret != 0) {
1677 DO_PthAPIerror( "sem_close", errno );
1678 }
1679
1680 if (TRACE_SEM_FNS) {
1681 fprintf(stderr, " close -> %d >>\n", ret);
1682 fflush(stderr);
1683 }
1684
1685 return ret;
1686}
1687
sewardjb4112022007-11-09 22:49:28 +00001688
1689/*----------------------------------------------------------------*/
1690/*--- Qt 4 threading functions (w/ GNU name mangling) ---*/
1691/*----------------------------------------------------------------*/
1692
sewardj38e0cf92008-11-19 10:40:56 +00001693/* Handled:
1694 QMutex::lock()
1695 QMutex::unlock()
1696 QMutex::tryLock()
1697 QMutex::tryLock(int)
sewardjb4112022007-11-09 22:49:28 +00001698
sewardj38e0cf92008-11-19 10:40:56 +00001699 QMutex::QMutex(QMutex::RecursionMode) _ZN6QMutexC1ENS_13RecursionModeE
1700 QMutex::QMutex(QMutex::RecursionMode) _ZN6QMutexC2ENS_13RecursionModeE
1701 QMutex::~QMutex() _ZN6QMutexD1Ev
1702 QMutex::~QMutex() _ZN6QMutexD2Ev
sewardjb4112022007-11-09 22:49:28 +00001703
sewardj38e0cf92008-11-19 10:40:56 +00001704 Unhandled:
1705 QReadWriteLock::lockForRead()
1706 QReadWriteLock::lockForWrite()
1707 QReadWriteLock::unlock()
1708 QReadWriteLock::tryLockForRead(int)
1709 QReadWriteLock::tryLockForRead()
1710 QReadWriteLock::tryLockForWrite(int)
1711 QReadWriteLock::tryLockForWrite()
1712
1713 QWaitCondition::wait(QMutex*, unsigned long)
1714 QWaitCondition::wakeAll()
1715 QWaitCondition::wakeOne()
1716
1717 QSemaphore::*
1718*/
1719/* More comments, 19 Nov 08, based on assessment of qt-4.5.0TP1,
1720 at least on Unix:
1721
1722 It's apparently only necessary to intercept QMutex, since that is
1723 not implemented using pthread_mutex_t; instead Qt4 has its own
1724 implementation based on atomics (to check the non-contended case)
1725 and pthread_cond_wait (to wait in the contended case).
1726
1727 QReadWriteLock is built on top of QMutex, counters, and a wait
1728 queue. So we don't need to handle it specially once QMutex
1729 handling is correct -- presumably the dependencies through QMutex
1730 are sufficient to avoid any false race reports. On the other hand,
1731 it is an open question whether too many dependencies are observed
1732 -- in which case we may miss races (false negatives). I suspect
1733 this is likely to be the case, unfortunately.
1734
1735 QWaitCondition is built on pthread_cond_t, pthread_mutex_t, QMutex
1736 and QReadWriteLock. Same compositional-correctness justificiation
1737 and limitations as fro QReadWriteLock.
1738
1739 Ditto QSemaphore (from cursory examination).
1740
1741 Does it matter that only QMutex is handled directly? Open
1742 question. From testing with drd/tests/qt4_* and with KDE4 apps, it
1743 appears that no false errors are reported; however it is not clear
1744 if this is causing false negatives.
1745
1746 Another problem with Qt4 is thread exiting. Threads are created
1747 with pthread_create (fine); but they detach and simply exit when
1748 done. There is no use of pthread_join, and the provided
1749 wait-for-a-thread-to-exit mechanism (QThread::wait, I believe)
1750 relies on a system of mutexes and flags. I suspect this also
1751 causes too many dependencies to appear. Consequently H sometimes
1752 fails to detect races at exit in some very short-lived racy
1753 programs, because it appears that a thread can exit _and_ have an
1754 observed dependency edge back to the main thread (presumably)
1755 before the main thread reaps the child (that is, calls
1756 QThread::wait).
1757
1758 This theory is supported by the observation that if all threads are
1759 made to wait at a pthread_barrier_t immediately before they exit,
1760 then H's detection of races in such programs becomes reliable;
1761 without the barrier, it is varies from run to run, depending
1762 (according to investigation) on whether aforementioned
1763 exit-before-reaping behaviour happens or not.
1764
1765 Finally, why is it necessary to intercept the QMutex constructors
1766 and destructors? The constructors are intercepted only as a matter
1767 of convenience, so H can print accurate "first observed at"
1768 clauses. However, it is actually necessary to intercept the
1769 destructors (as it is with pthread_mutex_destroy) in order that
1770 locks get removed from LAOG when they are destroyed.
sewardjb4112022007-11-09 22:49:28 +00001771*/
1772
1773// soname is libQtCore.so.4 ; match against libQtCore.so*
1774#define QT4_FUNC(ret_ty, f, args...) \
sewardj38e0cf92008-11-19 10:40:56 +00001775 ret_ty I_WRAP_SONAME_FNNAME_ZU(libQtCoreZdsoZa,f)(args); \
1776 ret_ty I_WRAP_SONAME_FNNAME_ZU(libQtCoreZdsoZa,f)(args)
sewardjb4112022007-11-09 22:49:28 +00001777
sewardj1c147ff2009-07-26 19:52:06 +00001778//-----------------------------------------------------------
sewardjb4112022007-11-09 22:49:28 +00001779// QMutex::lock()
sewardj38e0cf92008-11-19 10:40:56 +00001780QT4_FUNC(void, _ZN6QMutex4lockEv, void* self)
sewardjb4112022007-11-09 22:49:28 +00001781{
1782 OrigFn fn;
1783 VALGRIND_GET_ORIG_FN(fn);
1784 if (TRACE_QT4_FNS) {
1785 fprintf(stderr, "<< QMutex::lock %p", self); fflush(stderr);
1786 }
1787
1788 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
1789 void*,self, long,0/*!isTryLock*/);
1790
1791 CALL_FN_v_W(fn, self);
1792
1793 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
1794 void*, self);
1795
1796 if (TRACE_QT4_FNS) {
1797 fprintf(stderr, " :: Q::lock done >>\n");
1798 }
1799}
1800
sewardj1c147ff2009-07-26 19:52:06 +00001801//-----------------------------------------------------------
sewardjb4112022007-11-09 22:49:28 +00001802// QMutex::unlock()
sewardj38e0cf92008-11-19 10:40:56 +00001803QT4_FUNC(void, _ZN6QMutex6unlockEv, void* self)
sewardjb4112022007-11-09 22:49:28 +00001804{
1805 OrigFn fn;
1806 VALGRIND_GET_ORIG_FN(fn);
1807
1808 if (TRACE_QT4_FNS) {
1809 fprintf(stderr, "<< QMutex::unlock %p", self); fflush(stderr);
1810 }
1811
1812 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_PRE,
1813 void*, self);
1814
1815 CALL_FN_v_W(fn, self);
1816
1817 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_UNLOCK_POST,
1818 void*, self);
1819
1820 if (TRACE_QT4_FNS) {
1821 fprintf(stderr, " Q::unlock done >>\n");
1822 }
1823}
1824
sewardj1c147ff2009-07-26 19:52:06 +00001825//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00001826// bool QMutex::tryLock()
sewardjb4112022007-11-09 22:49:28 +00001827// using 'long' to mimic C++ 'bool'
sewardj38e0cf92008-11-19 10:40:56 +00001828QT4_FUNC(long, _ZN6QMutex7tryLockEv, void* self)
sewardjb4112022007-11-09 22:49:28 +00001829{
1830 OrigFn fn;
1831 long ret;
1832 VALGRIND_GET_ORIG_FN(fn);
1833 if (TRACE_QT4_FNS) {
1834 fprintf(stderr, "<< QMutex::tryLock %p", self); fflush(stderr);
1835 }
1836
1837 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
1838 void*,self, long,1/*isTryLock*/);
1839
1840 CALL_FN_W_W(ret, fn, self);
1841
1842 // assumes that only the low 8 bits of the 'bool' are significant
1843 if (ret & 0xFF) {
1844 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
1845 void*, self);
1846 }
1847
1848 if (TRACE_QT4_FNS) {
1849 fprintf(stderr, " :: Q::tryLock -> %lu >>\n", ret);
1850 }
1851
1852 return ret;
1853}
1854
sewardj1c147ff2009-07-26 19:52:06 +00001855//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00001856// bool QMutex::tryLock(int)
1857// using 'long' to mimic C++ 'bool'
1858QT4_FUNC(long, _ZN6QMutex7tryLockEi, void* self, long arg2)
sewardjb4112022007-11-09 22:49:28 +00001859{
1860 OrigFn fn;
sewardj38e0cf92008-11-19 10:40:56 +00001861 long ret;
sewardjb4112022007-11-09 22:49:28 +00001862 VALGRIND_GET_ORIG_FN(fn);
1863 if (TRACE_QT4_FNS) {
sewardj38e0cf92008-11-19 10:40:56 +00001864 fprintf(stderr, "<< QMutex::tryLock(int) %p %d", self, (int)arg2);
sewardjb4112022007-11-09 22:49:28 +00001865 fflush(stderr);
1866 }
1867
sewardj38e0cf92008-11-19 10:40:56 +00001868 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_PRE,
1869 void*,self, long,1/*isTryLock*/);
sewardjb4112022007-11-09 22:49:28 +00001870
sewardj38e0cf92008-11-19 10:40:56 +00001871 CALL_FN_W_WW(ret, fn, self,arg2);
sewardjb4112022007-11-09 22:49:28 +00001872
sewardj38e0cf92008-11-19 10:40:56 +00001873 // assumes that only the low 8 bits of the 'bool' are significant
1874 if (ret & 0xFF) {
1875 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_LOCK_POST,
1876 void*, self);
1877 }
sewardjb4112022007-11-09 22:49:28 +00001878
1879 if (TRACE_QT4_FNS) {
sewardj38e0cf92008-11-19 10:40:56 +00001880 fprintf(stderr, " :: Q::tryLock(int) -> %lu >>\n", ret);
sewardjb4112022007-11-09 22:49:28 +00001881 }
sewardj38e0cf92008-11-19 10:40:56 +00001882
1883 return ret;
sewardjb4112022007-11-09 22:49:28 +00001884}
1885
sewardj38e0cf92008-11-19 10:40:56 +00001886
sewardj1c147ff2009-07-26 19:52:06 +00001887//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00001888// It's not really very clear what the args are here. But from
1889// a bit of dataflow analysis of the generated machine code of
1890// the original function, it appears this takes two args, and
1891// returns nothing. Nevertheless preserve return value just in
1892// case. A bit of debug printing indicates that the first arg
1893// is that of the mutex and the second is either zero or one,
1894// probably being the recursion mode, therefore.
1895// QMutex::QMutex(QMutex::RecursionMode) ("C1ENS" variant)
1896QT4_FUNC(void*, _ZN6QMutexC1ENS_13RecursionModeE,
1897 void* mutex,
1898 long recmode)
sewardjb4112022007-11-09 22:49:28 +00001899{
1900 OrigFn fn;
sewardj38e0cf92008-11-19 10:40:56 +00001901 long ret;
sewardjb4112022007-11-09 22:49:28 +00001902 VALGRIND_GET_ORIG_FN(fn);
sewardj38e0cf92008-11-19 10:40:56 +00001903 CALL_FN_W_WW(ret, fn, mutex, recmode);
1904 // fprintf(stderr, "QMutex constructor 1: %p <- %p %p\n", ret, arg1, arg2);
1905 DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_MUTEX_INIT_POST,
1906 void*,mutex, long,1/*mbRec*/);
1907 return (void*)ret;
sewardjb4112022007-11-09 22:49:28 +00001908}
1909
sewardj1c147ff2009-07-26 19:52:06 +00001910//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00001911// QMutex::~QMutex() ("D1Ev" variant)
1912QT4_FUNC(void*, _ZN6QMutexD1Ev, void* mutex)
sewardjb4112022007-11-09 22:49:28 +00001913{
1914 OrigFn fn;
sewardj38e0cf92008-11-19 10:40:56 +00001915 long ret;
sewardjb4112022007-11-09 22:49:28 +00001916 VALGRIND_GET_ORIG_FN(fn);
sewardj38e0cf92008-11-19 10:40:56 +00001917 DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_MUTEX_DESTROY_PRE,
1918 void*,mutex);
1919 CALL_FN_W_W(ret, fn, mutex);
1920 return (void*)ret;
sewardjb4112022007-11-09 22:49:28 +00001921}
1922
1923
sewardj1c147ff2009-07-26 19:52:06 +00001924//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00001925// QMutex::QMutex(QMutex::RecursionMode) ("C2ENS" variant)
1926QT4_FUNC(void*, _ZN6QMutexC2ENS_13RecursionModeE,
1927 void* mutex,
1928 long recmode)
1929{
1930 assert(0);
1931}
1932
sewardj1c147ff2009-07-26 19:52:06 +00001933
1934//-----------------------------------------------------------
sewardj38e0cf92008-11-19 10:40:56 +00001935// QMutex::~QMutex() ("D2Ev" variant)
1936QT4_FUNC(void*, _ZN6QMutexD2Ev, void* mutex)
1937{
1938 assert(0);
1939}
1940
1941
1942// QReadWriteLock is not intercepted directly. See comments
1943// above.
1944
1945//// QReadWriteLock::lockForRead()
1946//// _ZN14QReadWriteLock11lockForReadEv == QReadWriteLock::lockForRead()
1947//QT4_FUNC(void, ZuZZN14QReadWriteLock11lockForReadEv,
1948// // _ZN14QReadWriteLock11lockForReadEv
1949// void* self)
1950//{
1951// OrigFn fn;
1952// VALGRIND_GET_ORIG_FN(fn);
1953// if (TRACE_QT4_FNS) {
1954// fprintf(stderr, "<< QReadWriteLock::lockForRead %p", self);
1955// fflush(stderr);
1956// }
1957//
1958// DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1959// void*,self,
1960// long,0/*!isW*/, long,0/*!isTryLock*/);
1961//
1962// CALL_FN_v_W(fn, self);
1963//
1964// DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1965// void*,self, long,0/*!isW*/);
1966//
1967// if (TRACE_QT4_FNS) {
1968// fprintf(stderr, " :: Q::lockForRead :: done >>\n");
1969// }
1970//}
1971//
1972//// QReadWriteLock::lockForWrite()
1973//// _ZN14QReadWriteLock12lockForWriteEv == QReadWriteLock::lockForWrite()
1974//QT4_FUNC(void, ZuZZN14QReadWriteLock12lockForWriteEv,
1975// // _ZN14QReadWriteLock12lockForWriteEv
1976// void* self)
1977//{
1978// OrigFn fn;
1979// VALGRIND_GET_ORIG_FN(fn);
1980// if (TRACE_QT4_FNS) {
1981// fprintf(stderr, "<< QReadWriteLock::lockForWrite %p", self);
1982// fflush(stderr);
1983// }
1984//
1985// DO_CREQ_v_WWW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_PRE,
1986// void*,self,
1987// long,1/*isW*/, long,0/*!isTryLock*/);
1988//
1989// CALL_FN_v_W(fn, self);
1990//
1991// DO_CREQ_v_WW(_VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST,
1992// void*,self, long,1/*isW*/);
1993//
1994// if (TRACE_QT4_FNS) {
1995// fprintf(stderr, " :: Q::lockForWrite :: done >>\n");
1996// }
1997//}
1998//
1999//// QReadWriteLock::unlock()
2000//// _ZN14QReadWriteLock6unlockEv == QReadWriteLock::unlock()
2001//QT4_FUNC(void, ZuZZN14QReadWriteLock6unlockEv,
2002// // _ZN14QReadWriteLock6unlockEv
2003// void* self)
2004//{
2005// OrigFn fn;
2006// VALGRIND_GET_ORIG_FN(fn);
2007// if (TRACE_QT4_FNS) {
2008// fprintf(stderr, "<< QReadWriteLock::unlock %p", self);
2009// fflush(stderr);
2010// }
2011//
2012// DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE,
2013// void*,self);
2014//
2015// CALL_FN_v_W(fn, self);
2016//
2017// DO_CREQ_v_W(_VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_POST,
2018// void*,self);
2019//
2020// if (TRACE_QT4_FNS) {
2021// fprintf(stderr, " :: Q::unlock :: done >>\n");
2022// }
2023//}
2024
2025
2026/*----------------------------------------------------------------*/
2027/*--- Replacements for basic string functions, that don't ---*/
sewardjb80f0c92008-11-19 16:33:59 +00002028/*--- overrun the input arrays. ---*/
sewardj38e0cf92008-11-19 10:40:56 +00002029/*----------------------------------------------------------------*/
2030
2031/* Copied verbatim from memcheck/mc_replace_strmem.c. When copying
2032 new functions, please keep them in the same order as they appear in
2033 mc_replace_strmem.c. */
2034
sewardj38e0cf92008-11-19 10:40:56 +00002035
2036#define STRCHR(soname, fnname) \
2037 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
2038 char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
2039 { \
2040 UChar ch = (UChar)((UInt)c); \
2041 UChar* p = (UChar*)s; \
2042 while (True) { \
2043 if (*p == ch) return p; \
2044 if (*p == 0) return NULL; \
2045 p++; \
2046 } \
2047 }
2048
2049// Apparently index() is the same thing as strchr()
njne6154662009-02-10 04:23:41 +00002050STRCHR(VG_Z_LIBC_SONAME, strchr)
njne6154662009-02-10 04:23:41 +00002051STRCHR(VG_Z_LIBC_SONAME, index)
njnb4cfbc42009-05-04 04:20:02 +00002052#if defined(VGO_linux)
2053STRCHR(VG_Z_LD_LINUX_SO_2, strchr)
njne6154662009-02-10 04:23:41 +00002054STRCHR(VG_Z_LD_LINUX_SO_2, index)
njnb4cfbc42009-05-04 04:20:02 +00002055STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, strchr)
njne6154662009-02-10 04:23:41 +00002056STRCHR(VG_Z_LD_LINUX_X86_64_SO_2, index)
njnb4cfbc42009-05-04 04:20:02 +00002057#endif
sewardj38e0cf92008-11-19 10:40:56 +00002058
2059
2060// Note that this replacement often doesn't get used because gcc inlines
2061// calls to strlen() with its own built-in version. This can be very
2062// confusing if you aren't expecting it. Other small functions in this file
2063// may also be inline by gcc.
2064#define STRLEN(soname, fnname) \
2065 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
2066 SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
2067 { \
2068 SizeT i = 0; \
2069 while (str[i] != 0) i++; \
2070 return i; \
2071 }
2072
njne6154662009-02-10 04:23:41 +00002073STRLEN(VG_Z_LIBC_SONAME, strlen)
njnb4cfbc42009-05-04 04:20:02 +00002074#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +00002075STRLEN(VG_Z_LD_LINUX_SO_2, strlen)
2076STRLEN(VG_Z_LD_LINUX_X86_64_SO_2, strlen)
njnb4cfbc42009-05-04 04:20:02 +00002077#endif
sewardj38e0cf92008-11-19 10:40:56 +00002078
2079
2080#define STRCPY(soname, fnname) \
2081 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
2082 char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
2083 { \
2084 const Char* dst_orig = dst; \
2085 \
2086 while (*src) *dst++ = *src++; \
2087 *dst = 0; \
2088 \
2089 return (char*)dst_orig; \
2090 }
2091
njne6154662009-02-10 04:23:41 +00002092STRCPY(VG_Z_LIBC_SONAME, strcpy)
sewardj38e0cf92008-11-19 10:40:56 +00002093
2094
2095#define STRCMP(soname, fnname) \
2096 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2097 ( const char* s1, const char* s2 ); \
2098 int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2099 ( const char* s1, const char* s2 ) \
2100 { \
2101 register unsigned char c1; \
2102 register unsigned char c2; \
2103 while (True) { \
2104 c1 = *(unsigned char *)s1; \
2105 c2 = *(unsigned char *)s2; \
2106 if (c1 != c2) break; \
2107 if (c1 == 0) break; \
2108 s1++; s2++; \
2109 } \
2110 if ((unsigned char)c1 < (unsigned char)c2) return -1; \
2111 if ((unsigned char)c1 > (unsigned char)c2) return 1; \
2112 return 0; \
2113 }
2114
njne6154662009-02-10 04:23:41 +00002115STRCMP(VG_Z_LIBC_SONAME, strcmp)
njnb4cfbc42009-05-04 04:20:02 +00002116#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +00002117STRCMP(VG_Z_LD_LINUX_X86_64_SO_2, strcmp)
2118STRCMP(VG_Z_LD64_SO_1, strcmp)
njnb4cfbc42009-05-04 04:20:02 +00002119#endif
sewardj38e0cf92008-11-19 10:40:56 +00002120
2121
2122#define MEMCPY(soname, fnname) \
2123 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2124 ( void *dst, const void *src, SizeT len ); \
2125 void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2126 ( void *dst, const void *src, SizeT len ) \
2127 { \
2128 register char *d; \
2129 register char *s; \
2130 \
2131 if (len == 0) \
2132 return dst; \
2133 \
2134 if ( dst > src ) { \
2135 d = (char *)dst + len - 1; \
2136 s = (char *)src + len - 1; \
2137 while ( len >= 4 ) { \
2138 *d-- = *s--; \
2139 *d-- = *s--; \
2140 *d-- = *s--; \
2141 *d-- = *s--; \
2142 len -= 4; \
2143 } \
2144 while ( len-- ) { \
2145 *d-- = *s--; \
2146 } \
2147 } else if ( dst < src ) { \
2148 d = (char *)dst; \
2149 s = (char *)src; \
2150 while ( len >= 4 ) { \
2151 *d++ = *s++; \
2152 *d++ = *s++; \
2153 *d++ = *s++; \
2154 *d++ = *s++; \
2155 len -= 4; \
2156 } \
2157 while ( len-- ) { \
2158 *d++ = *s++; \
2159 } \
2160 } \
2161 return dst; \
2162 }
2163
njne6154662009-02-10 04:23:41 +00002164MEMCPY(VG_Z_LIBC_SONAME, memcpy)
njnb4cfbc42009-05-04 04:20:02 +00002165#if defined(VGO_linux)
njne6154662009-02-10 04:23:41 +00002166MEMCPY(VG_Z_LD_SO_1, memcpy) /* ld.so.1 */
2167MEMCPY(VG_Z_LD64_SO_1, memcpy) /* ld64.so.1 */
njnb4cfbc42009-05-04 04:20:02 +00002168#endif
sewardj38e0cf92008-11-19 10:40:56 +00002169/* icc9 blats these around all over the place. Not only in the main
2170 executable but various .so's. They are highly tuned and read
2171 memory beyond the source boundary (although work correctly and
2172 never go across page boundaries), so give errors when run natively,
2173 at least for misaligned source arg. Just intercepting in the exe
2174 only until we understand more about the problem. See
2175 http://bugs.kde.org/show_bug.cgi?id=139776
2176 */
2177MEMCPY(NONE, _intel_fast_memcpy)
2178
2179
sewardjb4112022007-11-09 22:49:28 +00002180/*--------------------------------------------------------------------*/
2181/*--- end tc_intercepts.c ---*/
2182/*--------------------------------------------------------------------*/