blob: 5ed7a5bc8529698f0637f84d1b6af66b7d6bdcf7 [file] [log] [blame]
sewardjaf44c822007-11-25 14:01:38 +00001
2/*--------------------------------------------------------------------*/
sewardj85642922008-01-14 11:54:56 +00003/*--- Client-space code for drd. drd_intercepts.c ---*/
sewardjaf44c822007-11-25 14:01:38 +00004/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of drd, a data race detector.
8
sewardj85642922008-01-14 11:54:56 +00009 Copyright (C) 2006-2008 Bart Van Assche
sewardjaf44c822007-11-25 14:01:38 +000010 bart.vanassche@gmail.com
11
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 02111-1307, USA.
26
27 The GNU General Public License is contained in the file COPYING.
28*/
29
30/* ---------------------------------------------------------------------
31 ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU.
32
33 These functions are not called directly - they're the targets of code
34 redirection or load notifications (see pub_core_redir.h for info).
35 They're named weirdly so that the intercept code can find them when the
36 shared object is initially loaded.
37
38 Note that this filename has the "drd_" prefix because it can appear
39 in stack traces, and the "drd_" makes it a little clearer that it
40 originates from Valgrind.
41 ------------------------------------------------------------------ */
42
43// Make sure pthread_spinlock_t is available on glibc 2.3.2 systems.
44#ifndef _GNU_SOURCE
45#define _GNU_SOURCE
46#endif
47
48#include <assert.h>
49#include <inttypes.h> // uintptr_t
sewardj85642922008-01-14 11:54:56 +000050#include <pthread.h>
51#include <semaphore.h>
sewardjaf44c822007-11-25 14:01:38 +000052#include <stdio.h>
53#include <unistd.h>
sewardjaf44c822007-11-25 14:01:38 +000054#include "drd_clientreq.h"
sewardj85642922008-01-14 11:54:56 +000055#include "pub_tool_redir.h"
sewardjaf44c822007-11-25 14:01:38 +000056
57
58// Defines.
59
60#define PTH_FUNC(ret_ty, f, args...) \
61 ret_ty VG_WRAP_FUNCTION_ZZ(libpthreadZdsoZd0,f)(args); \
62 ret_ty VG_WRAP_FUNCTION_ZZ(libpthreadZdsoZd0,f)(args)
63
64
65// Local data structures.
66
67typedef struct
68{
69 void* (*start)(void*);
70 void* arg;
71 int detachstate;
72#if 0
73 pthread_mutex_t mutex;
74 pthread_cond_t cond;
75#else
76 int wrapper_started;
77#endif
78} VgPosixThreadArgs;
79
80
81// Local variables.
82
83static int vg_main_thread_state_is_set = 0;
84
85
86// Function definitions.
87
bart5357fcb2008-02-27 15:46:00 +000088static MutexT pthread_to_drd_mutex_type(const int kind)
89{
90 switch (kind)
91 {
92 /* PTHREAD_MUTEX_RECURSIVE_NP */
93 case PTHREAD_MUTEX_RECURSIVE:
94 return mutex_type_recursive_mutex;
95 /* PTHREAD_MUTEX_ERRORCHECK_NP */
96 case PTHREAD_MUTEX_ERRORCHECK:
97 return mutex_type_errorcheck_mutex;
98 /* PTHREAD_MUTEX_TIMED_NP */
99 /* PTHREAD_MUTEX_NORMAL */
100 case PTHREAD_MUTEX_DEFAULT:
101 case PTHREAD_MUTEX_ADAPTIVE_NP:
102 return mutex_type_default_mutex;
103#if 0
104 case -1:
105 printf("Warning: changed mutex type from -1 into %d\n",
106 mutex_type_default_mutex);
107 return mutex_type_default_mutex;
108#endif
109 }
110#if 0
111 printf("mutex->__data.__kind = %d\n", kind);
112 assert(0);
113#endif
114 return mutex_type_default_mutex;
115}
116
117static MutexT mutex_type(pthread_mutex_t* mutex)
118{
bartc9463c42008-02-28 07:36:04 +0000119#if defined(_PTHREAD_DESCR_DEFINED)
120 // Linuxthreads.
121 const int kind = mutex->__m_kind;
122#elif defined(__SIZEOF_PTHREAD_MUTEX_T)
123 // NPTL.
124 const int kind = mutex->__data.__kind;
125#else
126 // Another POSIX threads implementation. Regression tests will fail.
127 const int kind = PTHREAD_MUTEX_DEFAULT;
128#endif
129 return pthread_to_drd_mutex_type(kind);
bart5357fcb2008-02-27 15:46:00 +0000130}
131
sewardjaf44c822007-11-25 14:01:38 +0000132static void vg_start_suppression(const void* const p, size_t const size)
133{
134 int res;
135 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_SUPPRESSION,
136 p, size, 0, 0, 0);
137}
138
139#if 0
140static void vg_finish_suppression(const void* const p, size_t const size)
141{
142 int res;
143 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_FINISH_SUPPRESSION,
144 p, size, 0, 0, 0);
145}
146#endif
147
148static void vg_start_recording(void)
149{
150 int res;
151 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_RECORDING,
152 pthread_self(), 0, 0, 0, 0);
153}
154
155static void vg_stop_recording(void)
156{
157 int res;
158 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_STOP_RECORDING,
159 pthread_self(), 0, 0, 0, 0);
160}
161
162static void vg_set_joinable(const pthread_t tid, const int joinable)
163{
164 int res;
165 assert(joinable == 0 || joinable == 1);
sewardjaf44c822007-11-25 14:01:38 +0000166 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__SET_JOINABLE,
167 tid, joinable, 0, 0, 0);
168}
169
170static void* vg_thread_wrapper(void* arg)
171{
172 int res;
173 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK,
174 0, 0, 0, 0, 0);
175
176 {
177 VgPosixThreadArgs* const arg_ptr = (VgPosixThreadArgs*)arg;
178 VgPosixThreadArgs const arg_copy = *arg_ptr;
179 void* result;
180
181#if 0
182 pthread_mutex_lock(arg_ptr->mutex);
183 pthread_cond_signal(arg_ptr->cond);
184 pthread_mutex_unlock(arg_ptr->mutex);
185#else
186 arg_ptr->wrapper_started = 1;
187#endif
188
189 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
190 pthread_self(), 0, 0, 0, 0);
191 vg_set_joinable(pthread_self(),
192 arg_copy.detachstate == PTHREAD_CREATE_JOINABLE);
193 result = (arg_copy.start)(arg_copy.arg);
194 return result;
195 }
196}
197
198static void vg_set_main_thread_state(void)
199{
200 int res;
201
202 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK,
203 0, 0, 0, 0, 0);
204
sewardjaf44c822007-11-25 14:01:38 +0000205 // Make sure that DRD knows about the main thread's POSIX thread ID.
206 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
207 pthread_self(), 0, 0, 0, 0);
208
209}
210
211// pthread_create
sewardj347eeba2008-01-21 14:19:07 +0000212PTH_FUNC(int, pthreadZucreateZa, // pthread_create*
sewardjaf44c822007-11-25 14:01:38 +0000213 pthread_t *thread, const pthread_attr_t *attr,
214 void *(*start) (void *), void *arg)
215{
216 int ret;
217 OrigFn fn;
218 VgPosixThreadArgs vgargs;
219
220 VALGRIND_GET_ORIG_FN(fn);
221
222 if (vg_main_thread_state_is_set == 0)
223 {
224 vg_set_main_thread_state();
225 vg_main_thread_state_is_set = 1;
226 }
227 vg_start_suppression(&vgargs.wrapper_started,
228 sizeof(vgargs.wrapper_started));
229 vgargs.start = start;
230 vgargs.arg = arg;
231 vgargs.wrapper_started = 0;
232 vgargs.detachstate = PTHREAD_CREATE_JOINABLE;
233 if (attr)
234 {
235 if (pthread_attr_getdetachstate(attr, &vgargs.detachstate) != 0)
236 {
237 assert(0);
238 }
sewardjaf44c822007-11-25 14:01:38 +0000239 }
240 assert(vgargs.detachstate == PTHREAD_CREATE_JOINABLE
241 || vgargs.detachstate == PTHREAD_CREATE_DETACHED);
242#if 0
243 pthread_mutex_init(&vgargs.mutex, 0);
244 pthread_cond_init(&vgargs.cond, 0);
245 pthread_mutex_lock(&vgargs.mutex);
246#endif
247 vg_stop_recording();
248 CALL_FN_W_WWWW(ret, fn, thread, attr, vg_thread_wrapper, &vgargs);
249 vg_start_recording();
250#if 0
251 pthread_cond_wait(&vgargs.cond, &vgargs.mutex);
252 pthread_mutex_unlock(&vgargs.mutex);
253 pthread_cond_destroy(&vgargs.cond);
254 pthread_mutex_destroy(&vgargs.mutex);
255#else
256 // Yes, you see it correctly, busy waiting ... The problem is that
257 // POSIX threads functions cannot be called here -- the functions defined
sewardj85642922008-01-14 11:54:56 +0000258 // in this file (drd_intercepts.c) would be called instead of those in
sewardjaf44c822007-11-25 14:01:38 +0000259 // libpthread.so. This loop is necessary because vgargs is allocated on the
260 // stack, and the created thread reads it.
sewardje0744f02007-12-01 02:09:50 +0000261 if (ret == 0)
sewardjaf44c822007-11-25 14:01:38 +0000262 {
sewardje0744f02007-12-01 02:09:50 +0000263 while (! vgargs.wrapper_started)
264 {
265 sched_yield();
266 }
sewardjaf44c822007-11-25 14:01:38 +0000267 }
268#endif
269 return ret;
270}
271
272// pthread_join
273PTH_FUNC(int, pthreadZujoin, // pthread_join
274 pthread_t pt_joinee, void **thread_return)
275{
276 int ret;
277 int res;
278 OrigFn fn;
279
280 VALGRIND_GET_ORIG_FN(fn);
281 CALL_FN_W_WW(ret, fn, pt_joinee, thread_return);
282 if (ret == 0)
283 {
284 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_JOIN,
285 pt_joinee, 0, 0, 0, 0);
286 }
287 return ret;
288}
289
290// pthread_detach
291PTH_FUNC(int, pthreadZudetach, pthread_t pt_thread)
292{
293 int ret;
294 OrigFn fn;
295 VALGRIND_GET_ORIG_FN(fn);
296 {
297 CALL_FN_W_W(ret, fn, pt_thread);
298 if (ret == 0)
299 {
300 vg_set_joinable(pt_thread, 0);
301 }
302 }
303 return ret;
304}
305
306// pthread_mutex_init
307PTH_FUNC(int, pthreadZumutexZuinit,
308 pthread_mutex_t *mutex,
309 const pthread_mutexattr_t* attr)
310{
311 int ret;
312 int res;
313 OrigFn fn;
bart5357fcb2008-02-27 15:46:00 +0000314 int mt = PTHREAD_MUTEX_DEFAULT;
sewardjaf44c822007-11-25 14:01:38 +0000315 VALGRIND_GET_ORIG_FN(fn);
bart5357fcb2008-02-27 15:46:00 +0000316 if (attr)
317 pthread_mutexattr_gettype(attr, &mt);
sewardjaf44c822007-11-25 14:01:38 +0000318 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT,
bart5357fcb2008-02-27 15:46:00 +0000319 mutex, sizeof(*mutex),
320 pthread_to_drd_mutex_type(mt), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000321 CALL_FN_W_WW(ret, fn, mutex, attr);
322 return ret;
323}
324
325// pthread_mutex_destroy
326PTH_FUNC(int, pthreadZumutexZudestroy,
327 pthread_mutex_t *mutex)
328{
329 int ret;
330 int res;
331 OrigFn fn;
332 VALGRIND_GET_ORIG_FN(fn);
333 CALL_FN_W_W(ret, fn, mutex);
334 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
bart5357fcb2008-02-27 15:46:00 +0000335 mutex, mutex_type(mutex), 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000336 return ret;
337}
338
339// pthread_mutex_lock
340PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock
341 pthread_mutex_t *mutex)
342{
343 int ret;
344 int res;
345 OrigFn fn;
346 VALGRIND_GET_ORIG_FN(fn);
347 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK,
bart5357fcb2008-02-27 15:46:00 +0000348 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000349#if 1
350 // The only purpose of the system call below is to make drd work on AMD64
351 // systems. Without this system call, clients crash (SIGSEGV) in
352 // std::locale::locale().
353 write(1, "", 0);
354#endif
355 CALL_FN_W_W(ret, fn, mutex);
356 if (ret == 0)
357 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
bart5357fcb2008-02-27 15:46:00 +0000358 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000359 return ret;
360}
361
362// pthread_mutex_trylock
363PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock
364 pthread_mutex_t *mutex)
365{
366 int ret;
367 int res;
368 OrigFn fn;
369 VALGRIND_GET_ORIG_FN(fn);
370 CALL_FN_W_W(ret, fn, mutex);
371 if (ret == 0)
372 {
373 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
bart5357fcb2008-02-27 15:46:00 +0000374 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000375 }
376 return ret;
377}
378
sewardj85642922008-01-14 11:54:56 +0000379// pthread_mutex_timedlock
380PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock
381 pthread_mutex_t *mutex,
382 const struct timespec *abs_timeout)
383{
384 int ret;
385 int res;
386 OrigFn fn;
387 VALGRIND_GET_ORIG_FN(fn);
388 CALL_FN_W_WW(ret, fn, mutex, abs_timeout);
389 if (ret == 0)
390 {
391 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
bart5357fcb2008-02-27 15:46:00 +0000392 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardj85642922008-01-14 11:54:56 +0000393 }
394 return ret;
395}
396
sewardjaf44c822007-11-25 14:01:38 +0000397// pthread_mutex_unlock
398PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock
399 pthread_mutex_t *mutex)
400{
401 int ret;
402 int res;
403 OrigFn fn;
404 VALGRIND_GET_ORIG_FN(fn);
405 VALGRIND_DO_CLIENT_REQUEST(res, -1,
406 VG_USERREQ__PRE_PTHREAD_MUTEX_UNLOCK,
bart5357fcb2008-02-27 15:46:00 +0000407 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000408 CALL_FN_W_W(ret, fn, mutex);
409 return ret;
410}
411
412// pthread_cond_init
sewardj347eeba2008-01-21 14:19:07 +0000413PTH_FUNC(int, pthreadZucondZuinitZa, // pthread_cond_init*
sewardjaf44c822007-11-25 14:01:38 +0000414 pthread_cond_t* cond,
415 const pthread_condattr_t* attr)
416{
417 int ret;
418 int res;
419 OrigFn fn;
420 VALGRIND_GET_ORIG_FN(fn);
421 CALL_FN_W_WW(ret, fn, cond, attr);
422 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_INIT,
423 cond, sizeof(*cond), 0, 0, 0);
424 return ret;
425}
426
427// pthread_cond_destroy
sewardj347eeba2008-01-21 14:19:07 +0000428PTH_FUNC(int, pthreadZucondZudestroyZa, // pthread_cond_destroy*
sewardjaf44c822007-11-25 14:01:38 +0000429 pthread_cond_t* cond)
430{
431 int ret;
432 int res;
433 OrigFn fn;
434 VALGRIND_GET_ORIG_FN(fn);
435 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_DESTROY,
sewardj721ad7b2007-11-30 08:30:29 +0000436 cond, 0, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000437 CALL_FN_W_W(ret, fn, cond);
438 return ret;
439}
440
441// pthread_cond_wait
sewardj347eeba2008-01-21 14:19:07 +0000442PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait*
sewardjaf44c822007-11-25 14:01:38 +0000443 pthread_cond_t *cond,
444 pthread_mutex_t *mutex)
445{
446 int ret;
447 int res;
448 OrigFn fn;
449 VALGRIND_GET_ORIG_FN(fn);
450 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_WAIT,
bart5357fcb2008-02-27 15:46:00 +0000451 cond, sizeof(*cond), mutex, mutex_type(mutex), 0);
sewardjaf44c822007-11-25 14:01:38 +0000452 CALL_FN_W_WW(ret, fn, cond, mutex);
453 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_WAIT,
bart5357fcb2008-02-27 15:46:00 +0000454 cond, mutex, sizeof(*mutex), mutex_type(mutex), 0);
sewardjaf44c822007-11-25 14:01:38 +0000455 return ret;
456}
457
458// pthread_cond_timedwait
sewardj347eeba2008-01-21 14:19:07 +0000459PTH_FUNC(int, pthreadZucondZutimedwaitZa, // pthread_cond_timedwait*
sewardjaf44c822007-11-25 14:01:38 +0000460 pthread_cond_t *cond,
461 pthread_mutex_t *mutex,
462 const struct timespec* abstime)
463{
464 int ret;
465 int res;
466 OrigFn fn;
467 VALGRIND_GET_ORIG_FN(fn);
468 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_WAIT,
bart5357fcb2008-02-27 15:46:00 +0000469 cond, sizeof(*cond), mutex, mutex_type(mutex), 0);
sewardjaf44c822007-11-25 14:01:38 +0000470 CALL_FN_W_WWW(ret, fn, cond, mutex, abstime);
471 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_WAIT,
bart5357fcb2008-02-27 15:46:00 +0000472 cond, mutex, sizeof(*mutex), mutex_type(mutex), 0);
sewardjaf44c822007-11-25 14:01:38 +0000473 return ret;
474}
475
476// pthread_cond_signal
sewardj347eeba2008-01-21 14:19:07 +0000477PTH_FUNC(int, pthreadZucondZusignalZa, // pthread_cond_signal*
sewardjaf44c822007-11-25 14:01:38 +0000478 pthread_cond_t* cond)
479{
480 int ret;
481 int res;
482 OrigFn fn;
483 VALGRIND_GET_ORIG_FN(fn);
484 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_SIGNAL,
485 cond, 0, 0, 0, 0);
486 CALL_FN_W_W(ret, fn, cond);
487 return ret;
488}
489
490// pthread_cond_broadcast
sewardj347eeba2008-01-21 14:19:07 +0000491PTH_FUNC(int, pthreadZucondZubroadcastZa, // pthread_cond_broadcast*
sewardjaf44c822007-11-25 14:01:38 +0000492 pthread_cond_t* cond)
493{
494 int ret;
495 int res;
496 OrigFn fn;
497 VALGRIND_GET_ORIG_FN(fn);
498 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_BROADCAST,
499 cond, 0, 0, 0, 0);
500 CALL_FN_W_W(ret, fn, cond);
501 return ret;
502}
503
504
505// pthread_spin_init
506PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init
507 pthread_spinlock_t *spinlock,
508 int pshared)
509{
510 int ret;
511 int res;
512 OrigFn fn;
513 VALGRIND_GET_ORIG_FN(fn);
514 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SPIN_INIT_OR_UNLOCK,
sewardj721ad7b2007-11-30 08:30:29 +0000515 spinlock, sizeof(*spinlock),
516 mutex_type_spinlock, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000517 CALL_FN_W_WW(ret, fn, spinlock, pshared);
518 return ret;
519}
520
521// pthread_spin_destroy
522PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy
523 pthread_spinlock_t *spinlock)
524{
525 int ret;
526 int res;
527 OrigFn fn;
528 VALGRIND_GET_ORIG_FN(fn);
529 CALL_FN_W_W(ret, fn, spinlock);
530 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
sewardj721ad7b2007-11-30 08:30:29 +0000531 spinlock, mutex_type_spinlock, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000532 return ret;
533}
534
535// pthread_spin_lock
536PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock
537 pthread_spinlock_t *spinlock)
538{
539 int ret;
540 int res;
541 OrigFn fn;
542 VALGRIND_GET_ORIG_FN(fn);
543 CALL_FN_W_W(ret, fn, spinlock);
544 if (ret == 0)
545 {
546 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
sewardj721ad7b2007-11-30 08:30:29 +0000547 spinlock, sizeof(*spinlock),
548 mutex_type_spinlock, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000549 }
550 return ret;
551}
552
553// pthread_spin_trylock
554PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock
555 pthread_spinlock_t *spinlock)
556{
557 int ret;
558 int res;
559 OrigFn fn;
560 VALGRIND_GET_ORIG_FN(fn);
561 CALL_FN_W_W(ret, fn, spinlock);
562 if (ret == 0)
563 {
564 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
sewardj721ad7b2007-11-30 08:30:29 +0000565 spinlock, sizeof(*spinlock),
566 mutex_type_spinlock, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000567 }
568 return ret;
569}
570
571// pthread_spin_unlock
572PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock
573 pthread_spinlock_t *spinlock)
574{
575 int ret;
576 int res;
577 OrigFn fn;
578 VALGRIND_GET_ORIG_FN(fn);
579 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SPIN_INIT_OR_UNLOCK,
sewardj721ad7b2007-11-30 08:30:29 +0000580 spinlock, sizeof(*spinlock),
581 mutex_type_spinlock, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000582 CALL_FN_W_W(ret, fn, spinlock);
583 return ret;
584}
585
sewardj85642922008-01-14 11:54:56 +0000586// pthread_barrier_init
587PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init
588 pthread_barrier_t* barrier,
589 const pthread_barrierattr_t* attr,
590 unsigned count)
591{
592 int ret;
593 int res;
594 OrigFn fn;
595 VALGRIND_GET_ORIG_FN(fn);
596 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__BARRIER_INIT,
597 barrier, sizeof(*barrier),
598 count, 0, 0);
599 CALL_FN_W_WWW(ret, fn, barrier, attr, count);
600 return ret;
601}
602
603// pthread_barrier_destroy
604PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy
605 pthread_barrier_t* barrier)
606{
607 int ret;
608 int res;
609 OrigFn fn;
610 VALGRIND_GET_ORIG_FN(fn);
611 CALL_FN_W_W(ret, fn, barrier);
612 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__BARRIER_DESTROY,
613 barrier, 0, 0, 0, 0);
614 return ret;
615}
616
617// pthread_barrier_wait
618PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait
619 pthread_barrier_t* barrier)
620{
621 int ret;
622 int res;
623 OrigFn fn;
624 VALGRIND_GET_ORIG_FN(fn);
625 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT,
626 barrier, 0, 0, 0, 0);
627 CALL_FN_W_W(ret, fn, barrier);
628 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT,
629 barrier,
630 ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD,
631 0, 0, 0);
632 return ret;
633}
634
635
636// From glibc 2.0 linuxthreads/sysdeps/pthread/cmpxchg/semaphorebits.h
637typedef struct { long int sem_status; } sem_t_glibc_2_0;
638
639// sem_init
640PTH_FUNC(int, sem_initZAGLIBCZu2Zd0, // sem_init@GLIBC_2.0
641 sem_t_glibc_2_0 *sem,
642 int pshared,
643 unsigned int value)
644{
645 int ret;
646 int res;
647 OrigFn fn;
648 VALGRIND_GET_ORIG_FN(fn);
649 CALL_FN_W_WWW(ret, fn, sem, pshared, value);
650 if (ret == 0)
651 {
652 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_INIT,
653 sem, sizeof(*sem),
654 pshared, value, 0);
655 }
656 return ret;
657}
658
659PTH_FUNC(int, sem_initZa, // sem_init*
660 sem_t *sem,
661 int pshared,
662 unsigned int value)
663{
664 int ret;
665 int res;
666 OrigFn fn;
667 VALGRIND_GET_ORIG_FN(fn);
668 CALL_FN_W_WWW(ret, fn, sem, pshared, value);
669 if (ret == 0)
670 {
671 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_INIT,
672 sem, sizeof(*sem),
673 pshared, value, 0);
674 }
675 return ret;
676}
677
678// sem_destroy
679PTH_FUNC(int, sem_destroyZAGLIBCZu2Zd0, // sem_destroy@GLIBC_2.0
680 sem_t_glibc_2_0 *sem)
681{
682 int ret;
683 int res;
684 OrigFn fn;
685 VALGRIND_GET_ORIG_FN(fn);
686 CALL_FN_W_W(ret, fn, sem);
687 if (ret == 0)
688 {
689 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_DESTROY,
690 sem, 0, 0, 0, 0);
691 }
692 return ret;
693}
694
695PTH_FUNC(int, sem_destroyZa, // sem_destroy*
696 sem_t *sem)
697{
698 int ret;
699 int res;
700 OrigFn fn;
701 VALGRIND_GET_ORIG_FN(fn);
702 CALL_FN_W_W(ret, fn, sem);
703 if (ret == 0)
704 {
705 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_DESTROY,
706 sem, 0, 0, 0, 0);
707 }
708 return ret;
709}
710
711// sem_wait
712PTH_FUNC(int, sem_waitZAGLIBCZu2Zd0, // sem_wait@GLIBC_2.0
713 sem_t_glibc_2_0 *sem)
714{
715 int ret;
716 int res;
717 OrigFn fn;
718 VALGRIND_GET_ORIG_FN(fn);
719 CALL_FN_W_W(ret, fn, sem);
720 if (ret == 0)
721 {
722 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
723 sem, sizeof(*sem), 0, 0, 0);
724 }
725 return ret;
726}
727
728PTH_FUNC(int, sem_waitZa, // sem_wait*
729 sem_t *sem)
730{
731 int ret;
732 int res;
733 OrigFn fn;
734 VALGRIND_GET_ORIG_FN(fn);
735 CALL_FN_W_W(ret, fn, sem);
736 if (ret == 0)
737 {
738 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
739 sem, sizeof(*sem), 0, 0, 0);
740 }
741 return ret;
742}
743
744// sem_trywait
745PTH_FUNC(int, sem_trywaitZAGLIBCZu2Zd0, // sem_trywait@GLIBC_2.0
746 sem_t_glibc_2_0 *sem)
747{
748 int ret;
749 int res;
750 OrigFn fn;
751 VALGRIND_GET_ORIG_FN(fn);
752 CALL_FN_W_W(ret, fn, sem);
753 if (ret == 0)
754 {
755 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
756 sem, sizeof(*sem), 0, 0, 0);
757 }
758 return ret;
759}
760
761PTH_FUNC(int, sem_trywaitZa, // sem_trywait*
762 sem_t *sem)
763{
764 int ret;
765 int res;
766 OrigFn fn;
767 VALGRIND_GET_ORIG_FN(fn);
768 CALL_FN_W_W(ret, fn, sem);
769 if (ret == 0)
770 {
771 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
772 sem, sizeof(*sem), 0, 0, 0);
773 }
774 return ret;
775}
776
777// sem_timedwait
778PTH_FUNC(int, sem_timedwait, // sem_timedwait
779 sem_t *sem, const struct timespec *abs_timeout)
780{
781 int ret;
782 int res;
783 OrigFn fn;
784 VALGRIND_GET_ORIG_FN(fn);
785 CALL_FN_W_WW(ret, fn, sem, abs_timeout);
786 if (ret == 0)
787 {
788 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
789 sem, sizeof(*sem), 0, 0, 0);
790 }
791 return ret;
792}
793
794// sem_post
795PTH_FUNC(int, sem_postZAGLIBCZu2Zd0, // sem_post@GLIBC_2.0
796 sem_t_glibc_2_0 *sem)
797{
798 int ret;
799 int res;
800 OrigFn fn;
801 VALGRIND_GET_ORIG_FN(fn);
802 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST,
803 sem, sizeof(*sem), 0, 0, 0);
804 CALL_FN_W_W(ret, fn, sem);
sewardjc0be9252008-02-11 11:00:51 +0000805 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST,
806 sem, sizeof(*sem), ret == 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000807 return ret;
808}
809
810PTH_FUNC(int, sem_postZa, // sem_post*
811 sem_t *sem)
812{
813 int ret;
814 int res;
815 OrigFn fn;
816 VALGRIND_GET_ORIG_FN(fn);
817 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST,
818 sem, sizeof(*sem), 0, 0, 0);
819 CALL_FN_W_W(ret, fn, sem);
sewardje3b57aa2008-01-18 07:42:01 +0000820 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST,
821 sem, sizeof(*sem), ret == 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000822 return ret;
823}
824
825/*
826pthread_rwlock_destroy
827pthread_rwlock_init
828pthread_rwlock_rdlock
829pthread_rwlock_timedrdlock
830pthread_rwlock_timedwrlock
831pthread_rwlock_tryrdlock
832pthread_rwlock_trywrlock
833pthread_rwlock_unlock
834pthread_rwlock_wrlock
835pthread_rwlockattr_destroy
836pthread_rwlockattr_getkind_np
837pthread_rwlockattr_getpshared
838pthread_rwlockattr_init
839pthread_rwlockattr_setkind_np
840pthread_rwlockattr_setpshared
841 */
842
sewardjaf44c822007-11-25 14:01:38 +0000843/*
844 * Local variables:
845 * c-basic-offset: 3
846 * End:
847 */