blob: 96a1f945c1f7403d87c9e5cae7675cc3864a8d70 [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
bart5e85d262008-03-01 10:49:37 +000043// Make sure pthread_spinlock_t is available when compiling with older glibc
44// versions (2.3 or before).
sewardjaf44c822007-11-25 14:01:38 +000045#ifndef _GNU_SOURCE
46#define _GNU_SOURCE
47#endif
48
49#include <assert.h>
50#include <inttypes.h> // uintptr_t
sewardj85642922008-01-14 11:54:56 +000051#include <pthread.h>
52#include <semaphore.h>
sewardjaf44c822007-11-25 14:01:38 +000053#include <stdio.h>
bart0d063002008-03-01 07:25:13 +000054#include <stdlib.h>
sewardjaf44c822007-11-25 14:01:38 +000055#include <unistd.h>
sewardjaf44c822007-11-25 14:01:38 +000056#include "drd_clientreq.h"
sewardj85642922008-01-14 11:54:56 +000057#include "pub_tool_redir.h"
sewardjaf44c822007-11-25 14:01:38 +000058
59
60// Defines.
61
62#define PTH_FUNC(ret_ty, f, args...) \
63 ret_ty VG_WRAP_FUNCTION_ZZ(libpthreadZdsoZd0,f)(args); \
64 ret_ty VG_WRAP_FUNCTION_ZZ(libpthreadZdsoZd0,f)(args)
65
66
67// Local data structures.
68
69typedef struct
70{
71 void* (*start)(void*);
72 void* arg;
73 int detachstate;
74#if 0
75 pthread_mutex_t mutex;
76 pthread_cond_t cond;
77#else
78 int wrapper_started;
79#endif
80} VgPosixThreadArgs;
81
82
83// Local variables.
84
85static int vg_main_thread_state_is_set = 0;
bart0d063002008-03-01 07:25:13 +000086static pid_t vg_main_thread_pid;
sewardjaf44c822007-11-25 14:01:38 +000087
88
89// Function definitions.
90
bart5357fcb2008-02-27 15:46:00 +000091static MutexT pthread_to_drd_mutex_type(const int kind)
92{
93 switch (kind)
94 {
95 /* PTHREAD_MUTEX_RECURSIVE_NP */
96 case PTHREAD_MUTEX_RECURSIVE:
97 return mutex_type_recursive_mutex;
98 /* PTHREAD_MUTEX_ERRORCHECK_NP */
99 case PTHREAD_MUTEX_ERRORCHECK:
100 return mutex_type_errorcheck_mutex;
101 /* PTHREAD_MUTEX_TIMED_NP */
102 /* PTHREAD_MUTEX_NORMAL */
103 case PTHREAD_MUTEX_DEFAULT:
104 case PTHREAD_MUTEX_ADAPTIVE_NP:
105 return mutex_type_default_mutex;
bart5357fcb2008-02-27 15:46:00 +0000106 }
bart635cb162008-02-28 08:30:43 +0000107 return mutex_type_invalid_mutex;
bart5357fcb2008-02-27 15:46:00 +0000108}
109
110static MutexT mutex_type(pthread_mutex_t* mutex)
111{
bartc9463c42008-02-28 07:36:04 +0000112#if defined(_PTHREAD_DESCR_DEFINED)
113 // Linuxthreads.
114 const int kind = mutex->__m_kind;
115#elif defined(__SIZEOF_PTHREAD_MUTEX_T)
116 // NPTL.
117 const int kind = mutex->__data.__kind;
118#else
119 // Another POSIX threads implementation. Regression tests will fail.
120 const int kind = PTHREAD_MUTEX_DEFAULT;
121#endif
122 return pthread_to_drd_mutex_type(kind);
bart5357fcb2008-02-27 15:46:00 +0000123}
124
sewardjaf44c822007-11-25 14:01:38 +0000125static void vg_start_suppression(const void* const p, size_t const size)
126{
127 int res;
128 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_SUPPRESSION,
bart5e85d262008-03-01 10:49:37 +0000129 p, (char*)p + size, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000130}
131
132static void vg_set_joinable(const pthread_t tid, const int joinable)
133{
134 int res;
135 assert(joinable == 0 || joinable == 1);
sewardjaf44c822007-11-25 14:01:38 +0000136 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__SET_JOINABLE,
137 tid, joinable, 0, 0, 0);
138}
139
140static void* vg_thread_wrapper(void* arg)
141{
142 int res;
bart0d063002008-03-01 07:25:13 +0000143
144 if (getpid() != vg_main_thread_pid)
145 {
bart777f7fe2008-03-02 17:43:18 +0000146 if (getenv("LD_ASSUME_KERNEL"))
147 {
148 fprintf(stderr,
149"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
150"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
151"after having unset the environment variable LD_ASSUME_KERNEL. Giving up.\n"
152 );
153 }
154 else
155 {
156 fprintf(stderr,
157"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
158"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
159"after having upgraded to a newer version of your Linux distribution.\n"
160"Giving up.\n"
161 );
162 }
bart0d063002008-03-01 07:25:13 +0000163 abort();
164 }
165
sewardjaf44c822007-11-25 14:01:38 +0000166 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK,
167 0, 0, 0, 0, 0);
168
169 {
170 VgPosixThreadArgs* const arg_ptr = (VgPosixThreadArgs*)arg;
171 VgPosixThreadArgs const arg_copy = *arg_ptr;
172 void* result;
173
174#if 0
175 pthread_mutex_lock(arg_ptr->mutex);
176 pthread_cond_signal(arg_ptr->cond);
177 pthread_mutex_unlock(arg_ptr->mutex);
178#else
179 arg_ptr->wrapper_started = 1;
180#endif
181
182 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
183 pthread_self(), 0, 0, 0, 0);
184 vg_set_joinable(pthread_self(),
185 arg_copy.detachstate == PTHREAD_CREATE_JOINABLE);
186 result = (arg_copy.start)(arg_copy.arg);
187 return result;
188 }
189}
190
191static void vg_set_main_thread_state(void)
192{
193 int res;
194
bart0d063002008-03-01 07:25:13 +0000195 vg_main_thread_pid = getpid();
196
sewardjaf44c822007-11-25 14:01:38 +0000197 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK,
198 0, 0, 0, 0, 0);
199
sewardjaf44c822007-11-25 14:01:38 +0000200 // Make sure that DRD knows about the main thread's POSIX thread ID.
201 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
202 pthread_self(), 0, 0, 0, 0);
203
204}
205
206// pthread_create
sewardj347eeba2008-01-21 14:19:07 +0000207PTH_FUNC(int, pthreadZucreateZa, // pthread_create*
sewardjaf44c822007-11-25 14:01:38 +0000208 pthread_t *thread, const pthread_attr_t *attr,
209 void *(*start) (void *), void *arg)
210{
211 int ret;
212 OrigFn fn;
213 VgPosixThreadArgs vgargs;
214
215 VALGRIND_GET_ORIG_FN(fn);
216
217 if (vg_main_thread_state_is_set == 0)
218 {
219 vg_set_main_thread_state();
220 vg_main_thread_state_is_set = 1;
221 }
222 vg_start_suppression(&vgargs.wrapper_started,
223 sizeof(vgargs.wrapper_started));
224 vgargs.start = start;
225 vgargs.arg = arg;
226 vgargs.wrapper_started = 0;
227 vgargs.detachstate = PTHREAD_CREATE_JOINABLE;
228 if (attr)
229 {
230 if (pthread_attr_getdetachstate(attr, &vgargs.detachstate) != 0)
231 {
232 assert(0);
233 }
sewardjaf44c822007-11-25 14:01:38 +0000234 }
235 assert(vgargs.detachstate == PTHREAD_CREATE_JOINABLE
236 || vgargs.detachstate == PTHREAD_CREATE_DETACHED);
237#if 0
238 pthread_mutex_init(&vgargs.mutex, 0);
239 pthread_cond_init(&vgargs.cond, 0);
240 pthread_mutex_lock(&vgargs.mutex);
241#endif
sewardjaf44c822007-11-25 14:01:38 +0000242 CALL_FN_W_WWWW(ret, fn, thread, attr, vg_thread_wrapper, &vgargs);
sewardjaf44c822007-11-25 14:01:38 +0000243#if 0
244 pthread_cond_wait(&vgargs.cond, &vgargs.mutex);
245 pthread_mutex_unlock(&vgargs.mutex);
246 pthread_cond_destroy(&vgargs.cond);
247 pthread_mutex_destroy(&vgargs.mutex);
248#else
249 // Yes, you see it correctly, busy waiting ... The problem is that
250 // POSIX threads functions cannot be called here -- the functions defined
sewardj85642922008-01-14 11:54:56 +0000251 // in this file (drd_intercepts.c) would be called instead of those in
sewardjaf44c822007-11-25 14:01:38 +0000252 // libpthread.so. This loop is necessary because vgargs is allocated on the
253 // stack, and the created thread reads it.
sewardje0744f02007-12-01 02:09:50 +0000254 if (ret == 0)
sewardjaf44c822007-11-25 14:01:38 +0000255 {
sewardje0744f02007-12-01 02:09:50 +0000256 while (! vgargs.wrapper_started)
257 {
258 sched_yield();
259 }
sewardjaf44c822007-11-25 14:01:38 +0000260 }
261#endif
262 return ret;
263}
264
265// pthread_join
266PTH_FUNC(int, pthreadZujoin, // pthread_join
267 pthread_t pt_joinee, void **thread_return)
268{
269 int ret;
270 int res;
271 OrigFn fn;
272
273 VALGRIND_GET_ORIG_FN(fn);
274 CALL_FN_W_WW(ret, fn, pt_joinee, thread_return);
275 if (ret == 0)
276 {
277 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_JOIN,
278 pt_joinee, 0, 0, 0, 0);
279 }
280 return ret;
281}
282
283// pthread_detach
284PTH_FUNC(int, pthreadZudetach, pthread_t pt_thread)
285{
286 int ret;
287 OrigFn fn;
288 VALGRIND_GET_ORIG_FN(fn);
289 {
290 CALL_FN_W_W(ret, fn, pt_thread);
291 if (ret == 0)
292 {
293 vg_set_joinable(pt_thread, 0);
294 }
295 }
296 return ret;
297}
298
299// pthread_mutex_init
300PTH_FUNC(int, pthreadZumutexZuinit,
301 pthread_mutex_t *mutex,
302 const pthread_mutexattr_t* attr)
303{
304 int ret;
305 int res;
306 OrigFn fn;
bart5357fcb2008-02-27 15:46:00 +0000307 int mt = PTHREAD_MUTEX_DEFAULT;
sewardjaf44c822007-11-25 14:01:38 +0000308 VALGRIND_GET_ORIG_FN(fn);
bart5357fcb2008-02-27 15:46:00 +0000309 if (attr)
310 pthread_mutexattr_gettype(attr, &mt);
sewardjaf44c822007-11-25 14:01:38 +0000311 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT,
bart5357fcb2008-02-27 15:46:00 +0000312 mutex, sizeof(*mutex),
313 pthread_to_drd_mutex_type(mt), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000314 CALL_FN_W_WW(ret, fn, mutex, attr);
315 return ret;
316}
317
318// pthread_mutex_destroy
319PTH_FUNC(int, pthreadZumutexZudestroy,
320 pthread_mutex_t *mutex)
321{
322 int ret;
323 int res;
324 OrigFn fn;
325 VALGRIND_GET_ORIG_FN(fn);
326 CALL_FN_W_W(ret, fn, mutex);
327 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
bart5357fcb2008-02-27 15:46:00 +0000328 mutex, mutex_type(mutex), 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000329 return ret;
330}
331
332// pthread_mutex_lock
333PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock
334 pthread_mutex_t *mutex)
335{
336 int ret;
337 int res;
338 OrigFn fn;
339 VALGRIND_GET_ORIG_FN(fn);
340 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK,
bart5357fcb2008-02-27 15:46:00 +0000341 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000342 CALL_FN_W_W(ret, fn, mutex);
bart3b1ee452008-02-29 19:28:15 +0000343 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
bart00344642008-03-01 15:27:41 +0000344 mutex, ret == 0, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000345 return ret;
346}
347
348// pthread_mutex_trylock
349PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock
350 pthread_mutex_t *mutex)
351{
352 int ret;
353 int res;
354 OrigFn fn;
355 VALGRIND_GET_ORIG_FN(fn);
bart00344642008-03-01 15:27:41 +0000356 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK,
357 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000358 CALL_FN_W_W(ret, fn, mutex);
bart3b1ee452008-02-29 19:28:15 +0000359 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
bart00344642008-03-01 15:27:41 +0000360 mutex, ret == 0, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000361 return ret;
362}
363
sewardj85642922008-01-14 11:54:56 +0000364// pthread_mutex_timedlock
365PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock
366 pthread_mutex_t *mutex,
367 const struct timespec *abs_timeout)
368{
369 int ret;
370 int res;
371 OrigFn fn;
372 VALGRIND_GET_ORIG_FN(fn);
bart00344642008-03-01 15:27:41 +0000373 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK,
374 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardj85642922008-01-14 11:54:56 +0000375 CALL_FN_W_WW(ret, fn, mutex, abs_timeout);
bart3b1ee452008-02-29 19:28:15 +0000376 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
bart00344642008-03-01 15:27:41 +0000377 mutex, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000378 return ret;
379}
380
sewardjaf44c822007-11-25 14:01:38 +0000381// pthread_mutex_unlock
382PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock
383 pthread_mutex_t *mutex)
384{
385 int ret;
386 int res;
387 OrigFn fn;
388 VALGRIND_GET_ORIG_FN(fn);
389 VALGRIND_DO_CLIENT_REQUEST(res, -1,
390 VG_USERREQ__PRE_PTHREAD_MUTEX_UNLOCK,
bart5357fcb2008-02-27 15:46:00 +0000391 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000392 CALL_FN_W_W(ret, fn, mutex);
393 return ret;
394}
395
396// pthread_cond_init
sewardj347eeba2008-01-21 14:19:07 +0000397PTH_FUNC(int, pthreadZucondZuinitZa, // pthread_cond_init*
sewardjaf44c822007-11-25 14:01:38 +0000398 pthread_cond_t* cond,
399 const pthread_condattr_t* attr)
400{
401 int ret;
402 int res;
403 OrigFn fn;
404 VALGRIND_GET_ORIG_FN(fn);
bart72b751c2008-03-01 13:44:24 +0000405 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_INIT,
sewardjaf44c822007-11-25 14:01:38 +0000406 cond, sizeof(*cond), 0, 0, 0);
bart72b751c2008-03-01 13:44:24 +0000407 CALL_FN_W_WW(ret, fn, cond, attr);
sewardjaf44c822007-11-25 14:01:38 +0000408 return ret;
409}
410
411// pthread_cond_destroy
sewardj347eeba2008-01-21 14:19:07 +0000412PTH_FUNC(int, pthreadZucondZudestroyZa, // pthread_cond_destroy*
sewardjaf44c822007-11-25 14:01:38 +0000413 pthread_cond_t* cond)
414{
415 int ret;
416 int res;
417 OrigFn fn;
418 VALGRIND_GET_ORIG_FN(fn);
sewardjaf44c822007-11-25 14:01:38 +0000419 CALL_FN_W_W(ret, fn, cond);
bart72b751c2008-03-01 13:44:24 +0000420 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_DESTROY,
421 cond, 0, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000422 return ret;
423}
424
425// pthread_cond_wait
sewardj347eeba2008-01-21 14:19:07 +0000426PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait*
sewardjaf44c822007-11-25 14:01:38 +0000427 pthread_cond_t *cond,
428 pthread_mutex_t *mutex)
429{
430 int ret;
431 int res;
432 OrigFn fn;
433 VALGRIND_GET_ORIG_FN(fn);
434 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_WAIT,
bart3b1ee452008-02-29 19:28:15 +0000435 cond, sizeof(*cond), mutex, mutex_type(mutex),
436 0);
sewardjaf44c822007-11-25 14:01:38 +0000437 CALL_FN_W_WW(ret, fn, cond, mutex);
438 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_WAIT,
bart00344642008-03-01 15:27:41 +0000439 cond, mutex, ret == 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000440 return ret;
441}
442
443// pthread_cond_timedwait
sewardj347eeba2008-01-21 14:19:07 +0000444PTH_FUNC(int, pthreadZucondZutimedwaitZa, // pthread_cond_timedwait*
sewardjaf44c822007-11-25 14:01:38 +0000445 pthread_cond_t *cond,
446 pthread_mutex_t *mutex,
447 const struct timespec* abstime)
448{
449 int ret;
450 int res;
451 OrigFn fn;
452 VALGRIND_GET_ORIG_FN(fn);
453 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_WAIT,
bart3b1ee452008-02-29 19:28:15 +0000454 cond, sizeof(*cond), mutex, mutex_type(mutex),
455 0);
sewardjaf44c822007-11-25 14:01:38 +0000456 CALL_FN_W_WWW(ret, fn, cond, mutex, abstime);
457 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_WAIT,
bart00344642008-03-01 15:27:41 +0000458 cond, mutex, ret == 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000459 return ret;
460}
461
462// pthread_cond_signal
sewardj347eeba2008-01-21 14:19:07 +0000463PTH_FUNC(int, pthreadZucondZusignalZa, // pthread_cond_signal*
sewardjaf44c822007-11-25 14:01:38 +0000464 pthread_cond_t* cond)
465{
466 int ret;
467 int res;
468 OrigFn fn;
469 VALGRIND_GET_ORIG_FN(fn);
470 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_SIGNAL,
471 cond, 0, 0, 0, 0);
472 CALL_FN_W_W(ret, fn, cond);
473 return ret;
474}
475
476// pthread_cond_broadcast
sewardj347eeba2008-01-21 14:19:07 +0000477PTH_FUNC(int, pthreadZucondZubroadcastZa, // pthread_cond_broadcast*
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_BROADCAST,
485 cond, 0, 0, 0, 0);
486 CALL_FN_W_W(ret, fn, cond);
487 return ret;
488}
489
490
491// pthread_spin_init
492PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init
493 pthread_spinlock_t *spinlock,
494 int pshared)
495{
496 int ret;
497 int res;
498 OrigFn fn;
499 VALGRIND_GET_ORIG_FN(fn);
500 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SPIN_INIT_OR_UNLOCK,
sewardj721ad7b2007-11-30 08:30:29 +0000501 spinlock, sizeof(*spinlock),
502 mutex_type_spinlock, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000503 CALL_FN_W_WW(ret, fn, spinlock, pshared);
504 return ret;
505}
506
507// pthread_spin_destroy
508PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy
509 pthread_spinlock_t *spinlock)
510{
511 int ret;
512 int res;
513 OrigFn fn;
514 VALGRIND_GET_ORIG_FN(fn);
515 CALL_FN_W_W(ret, fn, spinlock);
516 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
sewardj721ad7b2007-11-30 08:30:29 +0000517 spinlock, mutex_type_spinlock, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000518 return ret;
519}
520
521// pthread_spin_lock
522PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock
523 pthread_spinlock_t *spinlock)
524{
525 int ret;
526 int res;
527 OrigFn fn;
528 VALGRIND_GET_ORIG_FN(fn);
bart00344642008-03-01 15:27:41 +0000529 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK,
530 spinlock, sizeof(*spinlock), mutex_type_spinlock,
531 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000532 CALL_FN_W_W(ret, fn, spinlock);
bart3b1ee452008-02-29 19:28:15 +0000533 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
bart00344642008-03-01 15:27:41 +0000534 spinlock, ret == 0, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000535 return ret;
536}
537
538// pthread_spin_trylock
539PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock
540 pthread_spinlock_t *spinlock)
541{
542 int ret;
543 int res;
544 OrigFn fn;
545 VALGRIND_GET_ORIG_FN(fn);
bart00344642008-03-01 15:27:41 +0000546 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK,
547 spinlock, sizeof(*spinlock), mutex_type_spinlock,
548 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000549 CALL_FN_W_W(ret, fn, spinlock);
bart3b1ee452008-02-29 19:28:15 +0000550 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
bart00344642008-03-01 15:27:41 +0000551 spinlock, ret == 0, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000552 return ret;
553}
554
555// pthread_spin_unlock
556PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock
557 pthread_spinlock_t *spinlock)
558{
559 int ret;
560 int res;
561 OrigFn fn;
562 VALGRIND_GET_ORIG_FN(fn);
563 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SPIN_INIT_OR_UNLOCK,
sewardj721ad7b2007-11-30 08:30:29 +0000564 spinlock, sizeof(*spinlock),
565 mutex_type_spinlock, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000566 CALL_FN_W_W(ret, fn, spinlock);
567 return ret;
568}
569
sewardj85642922008-01-14 11:54:56 +0000570// pthread_barrier_init
571PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init
572 pthread_barrier_t* barrier,
573 const pthread_barrierattr_t* attr,
574 unsigned count)
575{
576 int ret;
577 int res;
578 OrigFn fn;
579 VALGRIND_GET_ORIG_FN(fn);
580 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__BARRIER_INIT,
581 barrier, sizeof(*barrier),
582 count, 0, 0);
583 CALL_FN_W_WWW(ret, fn, barrier, attr, count);
584 return ret;
585}
586
587// pthread_barrier_destroy
588PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy
589 pthread_barrier_t* barrier)
590{
591 int ret;
592 int res;
593 OrigFn fn;
594 VALGRIND_GET_ORIG_FN(fn);
595 CALL_FN_W_W(ret, fn, barrier);
596 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__BARRIER_DESTROY,
597 barrier, 0, 0, 0, 0);
598 return ret;
599}
600
601// pthread_barrier_wait
602PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait
603 pthread_barrier_t* barrier)
604{
605 int ret;
606 int res;
607 OrigFn fn;
608 VALGRIND_GET_ORIG_FN(fn);
609 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT,
610 barrier, 0, 0, 0, 0);
611 CALL_FN_W_W(ret, fn, barrier);
612 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT,
613 barrier,
614 ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD,
615 0, 0, 0);
616 return ret;
617}
618
619
620// From glibc 2.0 linuxthreads/sysdeps/pthread/cmpxchg/semaphorebits.h
621typedef struct { long int sem_status; } sem_t_glibc_2_0;
622
623// sem_init
bart00344642008-03-01 15:27:41 +0000624PTH_FUNC(int, semZuinitZAGLIBCZu2Zd0, // sem_init@GLIBC_2.0
sewardj85642922008-01-14 11:54:56 +0000625 sem_t_glibc_2_0 *sem,
626 int pshared,
627 unsigned int value)
628{
629 int ret;
630 int res;
631 OrigFn fn;
632 VALGRIND_GET_ORIG_FN(fn);
633 CALL_FN_W_WWW(ret, fn, sem, pshared, value);
634 if (ret == 0)
635 {
636 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_INIT,
637 sem, sizeof(*sem),
638 pshared, value, 0);
639 }
640 return ret;
641}
642
bart00344642008-03-01 15:27:41 +0000643PTH_FUNC(int, semZuinitZa, // sem_init*
sewardj85642922008-01-14 11:54:56 +0000644 sem_t *sem,
645 int pshared,
646 unsigned int value)
647{
648 int ret;
649 int res;
650 OrigFn fn;
651 VALGRIND_GET_ORIG_FN(fn);
652 CALL_FN_W_WWW(ret, fn, sem, pshared, value);
653 if (ret == 0)
654 {
655 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_INIT,
656 sem, sizeof(*sem),
657 pshared, value, 0);
658 }
659 return ret;
660}
661
662// sem_destroy
bart00344642008-03-01 15:27:41 +0000663PTH_FUNC(int, semZudestroyZAGLIBCZu2Zd0, // sem_destroy@GLIBC_2.0
sewardj85642922008-01-14 11:54:56 +0000664 sem_t_glibc_2_0 *sem)
665{
666 int ret;
667 int res;
668 OrigFn fn;
669 VALGRIND_GET_ORIG_FN(fn);
670 CALL_FN_W_W(ret, fn, sem);
671 if (ret == 0)
672 {
673 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_DESTROY,
674 sem, 0, 0, 0, 0);
675 }
676 return ret;
677}
678
bart00344642008-03-01 15:27:41 +0000679PTH_FUNC(int, semZudestroyZa, // sem_destroy*
sewardj85642922008-01-14 11:54:56 +0000680 sem_t *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
695// sem_wait
bart00344642008-03-01 15:27:41 +0000696PTH_FUNC(int, semZuwaitZAGLIBCZu2Zd0, // sem_wait@GLIBC_2.0
sewardj85642922008-01-14 11:54:56 +0000697 sem_t_glibc_2_0 *sem)
698{
699 int ret;
700 int res;
701 OrigFn fn;
702 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000703 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
704 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000705 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000706 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
707 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000708 return ret;
709}
710
bart28230a32008-02-29 17:27:03 +0000711// sem_wait
bart00344642008-03-01 15:27:41 +0000712PTH_FUNC(int, semZuwaitZa, // sem_wait*
sewardj85642922008-01-14 11:54:56 +0000713 sem_t *sem)
714{
715 int ret;
716 int res;
717 OrigFn fn;
718 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000719 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
720 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000721 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000722 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
723 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000724 return ret;
725}
726
727// sem_trywait
bart00344642008-03-01 15:27:41 +0000728PTH_FUNC(int, semZutrywaitZAGLIBCZu2Zd0, // sem_trywait@GLIBC_2.0
sewardj85642922008-01-14 11:54:56 +0000729 sem_t_glibc_2_0 *sem)
730{
731 int ret;
732 int res;
733 OrigFn fn;
734 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000735 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
736 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000737 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000738 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
739 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000740 return ret;
741}
742
bart00344642008-03-01 15:27:41 +0000743PTH_FUNC(int, semZutrywaitZa, // sem_trywait*
sewardj85642922008-01-14 11:54:56 +0000744 sem_t *sem)
745{
746 int ret;
747 int res;
748 OrigFn fn;
749 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000750 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
751 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000752 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000753 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
754 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000755 return ret;
756}
757
758// sem_timedwait
bart00344642008-03-01 15:27:41 +0000759PTH_FUNC(int, semZutimedwait, // sem_timedwait
sewardj85642922008-01-14 11:54:56 +0000760 sem_t *sem, const struct timespec *abs_timeout)
761{
762 int ret;
763 int res;
764 OrigFn fn;
765 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000766 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
767 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000768 CALL_FN_W_WW(ret, fn, sem, abs_timeout);
bart28230a32008-02-29 17:27:03 +0000769 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
770 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000771 return ret;
772}
773
774// sem_post
bart00344642008-03-01 15:27:41 +0000775PTH_FUNC(int, semZupostZAGLIBCZu2Zd0, // sem_post@GLIBC_2.0
sewardj85642922008-01-14 11:54:56 +0000776 sem_t_glibc_2_0 *sem)
777{
778 int ret;
779 int res;
780 OrigFn fn;
781 VALGRIND_GET_ORIG_FN(fn);
782 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST,
783 sem, sizeof(*sem), 0, 0, 0);
784 CALL_FN_W_W(ret, fn, sem);
sewardjc0be9252008-02-11 11:00:51 +0000785 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST,
786 sem, sizeof(*sem), ret == 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000787 return ret;
788}
789
bart00344642008-03-01 15:27:41 +0000790// sem_post
791PTH_FUNC(int, semZupostZa, // sem_post*
sewardj85642922008-01-14 11:54:56 +0000792 sem_t *sem)
793{
794 int ret;
795 int res;
796 OrigFn fn;
797 VALGRIND_GET_ORIG_FN(fn);
798 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST,
799 sem, sizeof(*sem), 0, 0, 0);
800 CALL_FN_W_W(ret, fn, sem);
sewardje3b57aa2008-01-18 07:42:01 +0000801 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST,
802 sem, sizeof(*sem), ret == 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000803 return ret;
804}
805
bart00344642008-03-01 15:27:41 +0000806// pthread_rwlock_init
807PTH_FUNC(int,
808 pthreadZurwlockZuinitZa, // pthread_rwlock_init*
809 pthread_rwlock_t* rwlock,
810 const pthread_rwlockattr_t* attr)
811{
812 int ret;
813 int res;
814 OrigFn fn;
815 VALGRIND_GET_ORIG_FN(fn);
816 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_INIT,
817 rwlock, sizeof(*rwlock), 0, 0, 0);
818 CALL_FN_W_WW(ret, fn, rwlock, attr);
819 return ret;
820}
821
822// pthread_rwlock_destroy
823PTH_FUNC(int,
824 pthreadZurwlockZudestroyZa, // pthread_rwlock_destroy*
825 pthread_rwlock_t* rwlock)
826{
827 int ret;
828 int res;
829 OrigFn fn;
830 VALGRIND_GET_ORIG_FN(fn);
831 CALL_FN_W_W(ret, fn, rwlock);
832 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_DESTROY,
833 rwlock, 0, 0, 0, 0);
834 return ret;
835}
836
837// pthread_rwlock_rdlock
838PTH_FUNC(int,
839 pthreadZurwlockZurdlockZa, // pthread_rwlock_rdlock*
840 pthread_rwlock_t* rwlock)
841{
842 int ret;
843 int res;
844 OrigFn fn;
845 VALGRIND_GET_ORIG_FN(fn);
846 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
847 rwlock, sizeof(*rwlock), 0, 0, 0);
848 CALL_FN_W_W(ret, fn, rwlock);
849 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK,
850 rwlock, ret == 0, 0, 0, 0);
851 return ret;
852}
853
854// pthread_rwlock_wrlock
855PTH_FUNC(int,
856 pthreadZurwlockZuwrlockZa, // pthread_rwlock_wrlock*
857 pthread_rwlock_t* rwlock)
858{
859 int ret;
860 int res;
861 OrigFn fn;
862 VALGRIND_GET_ORIG_FN(fn);
863 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
864 rwlock, sizeof(*rwlock), 0, 0, 0);
865 CALL_FN_W_W(ret, fn, rwlock);
866 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK,
867 rwlock, ret == 0, 0, 0, 0);
868 return ret;
869}
870
871// pthread_rwlock_timedrdlock
872PTH_FUNC(int,
873 pthreadZurwlockZutimedrdlockZa, // pthread_rwlock_timedrdlock*
874 pthread_rwlock_t* rwlock)
875{
876 int ret;
877 int res;
878 OrigFn fn;
879 VALGRIND_GET_ORIG_FN(fn);
880 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
881 rwlock, sizeof(*rwlock), 0, 0, 0);
882 CALL_FN_W_W(ret, fn, rwlock);
883 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK,
884 rwlock, ret == 0, 0, 0, 0);
885 return ret;
886}
887
888// pthread_rwlock_timedwrlock
889PTH_FUNC(int,
890 pthreadZurwlockZutimedwrlockZa, // pthread_rwlock_timedwrlock*
891 pthread_rwlock_t* rwlock)
892{
893 int ret;
894 int res;
895 OrigFn fn;
896 VALGRIND_GET_ORIG_FN(fn);
897 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
898 rwlock, sizeof(*rwlock), 0, 0, 0);
899 CALL_FN_W_W(ret, fn, rwlock);
900 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK,
901 rwlock, ret == 0, 0, 0, 0);
902 return ret;
903}
904
905// pthread_rwlock_tryrdlock
906PTH_FUNC(int,
907 pthreadZurwlockZutryrdlockZa, // pthread_rwlock_tryrdlock*
908 pthread_rwlock_t* rwlock)
909{
910 int ret;
911 int res;
912 OrigFn fn;
913 VALGRIND_GET_ORIG_FN(fn);
914 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
915 rwlock, sizeof(*rwlock), 0, 0, 0);
916 CALL_FN_W_W(ret, fn, rwlock);
917 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK,
918 rwlock, ret == 0, 0, 0, 0);
919 return ret;
920}
921
922// pthread_rwlock_trywrlock
923PTH_FUNC(int,
924 pthreadZurwlockZutrywrlockZa, // pthread_rwlock_trywrlock*
925 pthread_rwlock_t* rwlock)
926{
927 int ret;
928 int res;
929 OrigFn fn;
930 VALGRIND_GET_ORIG_FN(fn);
931 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
932 rwlock, sizeof(*rwlock), 0, 0, 0);
933 CALL_FN_W_W(ret, fn, rwlock);
934 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK,
935 rwlock, ret == 0, 0, 0, 0);
936 return ret;
937}
938
939// pthread_rwlock_unlock
940PTH_FUNC(int,
941 pthreadZurwlockZuunlockZa, // pthread_rwlock_unlock*
942 pthread_rwlock_t* rwlock)
943{
944 int ret;
945 int res;
946 OrigFn fn;
947 VALGRIND_GET_ORIG_FN(fn);
948 CALL_FN_W_W(ret, fn, rwlock);
bart777f7fe2008-03-02 17:43:18 +0000949 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_UNLOCK,
bart00344642008-03-01 15:27:41 +0000950 rwlock, ret == 0, 0, 0, 0);
951 return ret;
952}
953
sewardj85642922008-01-14 11:54:56 +0000954
sewardjaf44c822007-11-25 14:01:38 +0000955/*
956 * Local variables:
957 * c-basic-offset: 3
958 * End:
959 */