blob: 9c67416a0818238d4b3557f9efbda25f4643060b [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 {
146 fprintf(stderr,
147 "Detected the linuxthreads threading library.\n"
148 "Sorry, but DRD does not support linuxthreads.\n"
149 "Please try to run DRD on a system with NPTL instead.\n"
150 "Giving up.\n");
151 abort();
152 }
153
sewardjaf44c822007-11-25 14:01:38 +0000154 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK,
155 0, 0, 0, 0, 0);
156
157 {
158 VgPosixThreadArgs* const arg_ptr = (VgPosixThreadArgs*)arg;
159 VgPosixThreadArgs const arg_copy = *arg_ptr;
160 void* result;
161
162#if 0
163 pthread_mutex_lock(arg_ptr->mutex);
164 pthread_cond_signal(arg_ptr->cond);
165 pthread_mutex_unlock(arg_ptr->mutex);
166#else
167 arg_ptr->wrapper_started = 1;
168#endif
169
170 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
171 pthread_self(), 0, 0, 0, 0);
172 vg_set_joinable(pthread_self(),
173 arg_copy.detachstate == PTHREAD_CREATE_JOINABLE);
174 result = (arg_copy.start)(arg_copy.arg);
175 return result;
176 }
177}
178
179static void vg_set_main_thread_state(void)
180{
181 int res;
182
bart0d063002008-03-01 07:25:13 +0000183 vg_main_thread_pid = getpid();
184
sewardjaf44c822007-11-25 14:01:38 +0000185 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK,
186 0, 0, 0, 0, 0);
187
sewardjaf44c822007-11-25 14:01:38 +0000188 // Make sure that DRD knows about the main thread's POSIX thread ID.
189 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
190 pthread_self(), 0, 0, 0, 0);
191
192}
193
194// pthread_create
sewardj347eeba2008-01-21 14:19:07 +0000195PTH_FUNC(int, pthreadZucreateZa, // pthread_create*
sewardjaf44c822007-11-25 14:01:38 +0000196 pthread_t *thread, const pthread_attr_t *attr,
197 void *(*start) (void *), void *arg)
198{
199 int ret;
200 OrigFn fn;
201 VgPosixThreadArgs vgargs;
202
203 VALGRIND_GET_ORIG_FN(fn);
204
205 if (vg_main_thread_state_is_set == 0)
206 {
207 vg_set_main_thread_state();
208 vg_main_thread_state_is_set = 1;
209 }
210 vg_start_suppression(&vgargs.wrapper_started,
211 sizeof(vgargs.wrapper_started));
212 vgargs.start = start;
213 vgargs.arg = arg;
214 vgargs.wrapper_started = 0;
215 vgargs.detachstate = PTHREAD_CREATE_JOINABLE;
216 if (attr)
217 {
218 if (pthread_attr_getdetachstate(attr, &vgargs.detachstate) != 0)
219 {
220 assert(0);
221 }
sewardjaf44c822007-11-25 14:01:38 +0000222 }
223 assert(vgargs.detachstate == PTHREAD_CREATE_JOINABLE
224 || vgargs.detachstate == PTHREAD_CREATE_DETACHED);
225#if 0
226 pthread_mutex_init(&vgargs.mutex, 0);
227 pthread_cond_init(&vgargs.cond, 0);
228 pthread_mutex_lock(&vgargs.mutex);
229#endif
sewardjaf44c822007-11-25 14:01:38 +0000230 CALL_FN_W_WWWW(ret, fn, thread, attr, vg_thread_wrapper, &vgargs);
sewardjaf44c822007-11-25 14:01:38 +0000231#if 0
232 pthread_cond_wait(&vgargs.cond, &vgargs.mutex);
233 pthread_mutex_unlock(&vgargs.mutex);
234 pthread_cond_destroy(&vgargs.cond);
235 pthread_mutex_destroy(&vgargs.mutex);
236#else
237 // Yes, you see it correctly, busy waiting ... The problem is that
238 // POSIX threads functions cannot be called here -- the functions defined
sewardj85642922008-01-14 11:54:56 +0000239 // in this file (drd_intercepts.c) would be called instead of those in
sewardjaf44c822007-11-25 14:01:38 +0000240 // libpthread.so. This loop is necessary because vgargs is allocated on the
241 // stack, and the created thread reads it.
sewardje0744f02007-12-01 02:09:50 +0000242 if (ret == 0)
sewardjaf44c822007-11-25 14:01:38 +0000243 {
sewardje0744f02007-12-01 02:09:50 +0000244 while (! vgargs.wrapper_started)
245 {
246 sched_yield();
247 }
sewardjaf44c822007-11-25 14:01:38 +0000248 }
249#endif
250 return ret;
251}
252
253// pthread_join
254PTH_FUNC(int, pthreadZujoin, // pthread_join
255 pthread_t pt_joinee, void **thread_return)
256{
257 int ret;
258 int res;
259 OrigFn fn;
260
261 VALGRIND_GET_ORIG_FN(fn);
262 CALL_FN_W_WW(ret, fn, pt_joinee, thread_return);
263 if (ret == 0)
264 {
265 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_JOIN,
266 pt_joinee, 0, 0, 0, 0);
267 }
268 return ret;
269}
270
271// pthread_detach
272PTH_FUNC(int, pthreadZudetach, pthread_t pt_thread)
273{
274 int ret;
275 OrigFn fn;
276 VALGRIND_GET_ORIG_FN(fn);
277 {
278 CALL_FN_W_W(ret, fn, pt_thread);
279 if (ret == 0)
280 {
281 vg_set_joinable(pt_thread, 0);
282 }
283 }
284 return ret;
285}
286
287// pthread_mutex_init
288PTH_FUNC(int, pthreadZumutexZuinit,
289 pthread_mutex_t *mutex,
290 const pthread_mutexattr_t* attr)
291{
292 int ret;
293 int res;
294 OrigFn fn;
bart5357fcb2008-02-27 15:46:00 +0000295 int mt = PTHREAD_MUTEX_DEFAULT;
sewardjaf44c822007-11-25 14:01:38 +0000296 VALGRIND_GET_ORIG_FN(fn);
bart5357fcb2008-02-27 15:46:00 +0000297 if (attr)
298 pthread_mutexattr_gettype(attr, &mt);
sewardjaf44c822007-11-25 14:01:38 +0000299 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT,
bart5357fcb2008-02-27 15:46:00 +0000300 mutex, sizeof(*mutex),
301 pthread_to_drd_mutex_type(mt), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000302 CALL_FN_W_WW(ret, fn, mutex, attr);
303 return ret;
304}
305
306// pthread_mutex_destroy
307PTH_FUNC(int, pthreadZumutexZudestroy,
308 pthread_mutex_t *mutex)
309{
310 int ret;
311 int res;
312 OrigFn fn;
313 VALGRIND_GET_ORIG_FN(fn);
314 CALL_FN_W_W(ret, fn, mutex);
315 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
bart5357fcb2008-02-27 15:46:00 +0000316 mutex, mutex_type(mutex), 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000317 return ret;
318}
319
320// pthread_mutex_lock
321PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock
322 pthread_mutex_t *mutex)
323{
324 int ret;
325 int res;
326 OrigFn fn;
327 VALGRIND_GET_ORIG_FN(fn);
328 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK,
bart5357fcb2008-02-27 15:46:00 +0000329 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000330#if 1
331 // The only purpose of the system call below is to make drd work on AMD64
332 // systems. Without this system call, clients crash (SIGSEGV) in
333 // std::locale::locale().
334 write(1, "", 0);
335#endif
336 CALL_FN_W_W(ret, fn, mutex);
bart3b1ee452008-02-29 19:28:15 +0000337 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
bart00344642008-03-01 15:27:41 +0000338 mutex, ret == 0, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000339 return ret;
340}
341
342// pthread_mutex_trylock
343PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock
344 pthread_mutex_t *mutex)
345{
346 int ret;
347 int res;
348 OrigFn fn;
349 VALGRIND_GET_ORIG_FN(fn);
bart00344642008-03-01 15:27:41 +0000350 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK,
351 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000352 CALL_FN_W_W(ret, fn, mutex);
bart3b1ee452008-02-29 19:28:15 +0000353 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
bart00344642008-03-01 15:27:41 +0000354 mutex, ret == 0, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000355 return ret;
356}
357
sewardj85642922008-01-14 11:54:56 +0000358// pthread_mutex_timedlock
359PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock
360 pthread_mutex_t *mutex,
361 const struct timespec *abs_timeout)
362{
363 int ret;
364 int res;
365 OrigFn fn;
366 VALGRIND_GET_ORIG_FN(fn);
bart00344642008-03-01 15:27:41 +0000367 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK,
368 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardj85642922008-01-14 11:54:56 +0000369 CALL_FN_W_WW(ret, fn, mutex, abs_timeout);
bart3b1ee452008-02-29 19:28:15 +0000370 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
bart00344642008-03-01 15:27:41 +0000371 mutex, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000372 return ret;
373}
374
sewardjaf44c822007-11-25 14:01:38 +0000375// pthread_mutex_unlock
376PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock
377 pthread_mutex_t *mutex)
378{
379 int ret;
380 int res;
381 OrigFn fn;
382 VALGRIND_GET_ORIG_FN(fn);
383 VALGRIND_DO_CLIENT_REQUEST(res, -1,
384 VG_USERREQ__PRE_PTHREAD_MUTEX_UNLOCK,
bart5357fcb2008-02-27 15:46:00 +0000385 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000386 CALL_FN_W_W(ret, fn, mutex);
387 return ret;
388}
389
390// pthread_cond_init
sewardj347eeba2008-01-21 14:19:07 +0000391PTH_FUNC(int, pthreadZucondZuinitZa, // pthread_cond_init*
sewardjaf44c822007-11-25 14:01:38 +0000392 pthread_cond_t* cond,
393 const pthread_condattr_t* attr)
394{
395 int ret;
396 int res;
397 OrigFn fn;
398 VALGRIND_GET_ORIG_FN(fn);
bart72b751c2008-03-01 13:44:24 +0000399 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_INIT,
sewardjaf44c822007-11-25 14:01:38 +0000400 cond, sizeof(*cond), 0, 0, 0);
bart72b751c2008-03-01 13:44:24 +0000401 CALL_FN_W_WW(ret, fn, cond, attr);
sewardjaf44c822007-11-25 14:01:38 +0000402 return ret;
403}
404
405// pthread_cond_destroy
sewardj347eeba2008-01-21 14:19:07 +0000406PTH_FUNC(int, pthreadZucondZudestroyZa, // pthread_cond_destroy*
sewardjaf44c822007-11-25 14:01:38 +0000407 pthread_cond_t* cond)
408{
409 int ret;
410 int res;
411 OrigFn fn;
412 VALGRIND_GET_ORIG_FN(fn);
sewardjaf44c822007-11-25 14:01:38 +0000413 CALL_FN_W_W(ret, fn, cond);
bart72b751c2008-03-01 13:44:24 +0000414 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_DESTROY,
415 cond, 0, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000416 return ret;
417}
418
419// pthread_cond_wait
sewardj347eeba2008-01-21 14:19:07 +0000420PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait*
sewardjaf44c822007-11-25 14:01:38 +0000421 pthread_cond_t *cond,
422 pthread_mutex_t *mutex)
423{
424 int ret;
425 int res;
426 OrigFn fn;
427 VALGRIND_GET_ORIG_FN(fn);
428 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_WAIT,
bart3b1ee452008-02-29 19:28:15 +0000429 cond, sizeof(*cond), mutex, mutex_type(mutex),
430 0);
sewardjaf44c822007-11-25 14:01:38 +0000431 CALL_FN_W_WW(ret, fn, cond, mutex);
432 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_WAIT,
bart00344642008-03-01 15:27:41 +0000433 cond, mutex, ret == 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000434 return ret;
435}
436
437// pthread_cond_timedwait
sewardj347eeba2008-01-21 14:19:07 +0000438PTH_FUNC(int, pthreadZucondZutimedwaitZa, // pthread_cond_timedwait*
sewardjaf44c822007-11-25 14:01:38 +0000439 pthread_cond_t *cond,
440 pthread_mutex_t *mutex,
441 const struct timespec* abstime)
442{
443 int ret;
444 int res;
445 OrigFn fn;
446 VALGRIND_GET_ORIG_FN(fn);
447 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_WAIT,
bart3b1ee452008-02-29 19:28:15 +0000448 cond, sizeof(*cond), mutex, mutex_type(mutex),
449 0);
sewardjaf44c822007-11-25 14:01:38 +0000450 CALL_FN_W_WWW(ret, fn, cond, mutex, abstime);
451 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_WAIT,
bart00344642008-03-01 15:27:41 +0000452 cond, mutex, ret == 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000453 return ret;
454}
455
456// pthread_cond_signal
sewardj347eeba2008-01-21 14:19:07 +0000457PTH_FUNC(int, pthreadZucondZusignalZa, // pthread_cond_signal*
sewardjaf44c822007-11-25 14:01:38 +0000458 pthread_cond_t* cond)
459{
460 int ret;
461 int res;
462 OrigFn fn;
463 VALGRIND_GET_ORIG_FN(fn);
464 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_SIGNAL,
465 cond, 0, 0, 0, 0);
466 CALL_FN_W_W(ret, fn, cond);
467 return ret;
468}
469
470// pthread_cond_broadcast
sewardj347eeba2008-01-21 14:19:07 +0000471PTH_FUNC(int, pthreadZucondZubroadcastZa, // pthread_cond_broadcast*
sewardjaf44c822007-11-25 14:01:38 +0000472 pthread_cond_t* cond)
473{
474 int ret;
475 int res;
476 OrigFn fn;
477 VALGRIND_GET_ORIG_FN(fn);
478 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_BROADCAST,
479 cond, 0, 0, 0, 0);
480 CALL_FN_W_W(ret, fn, cond);
481 return ret;
482}
483
484
485// pthread_spin_init
486PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init
487 pthread_spinlock_t *spinlock,
488 int pshared)
489{
490 int ret;
491 int res;
492 OrigFn fn;
493 VALGRIND_GET_ORIG_FN(fn);
494 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SPIN_INIT_OR_UNLOCK,
sewardj721ad7b2007-11-30 08:30:29 +0000495 spinlock, sizeof(*spinlock),
496 mutex_type_spinlock, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000497 CALL_FN_W_WW(ret, fn, spinlock, pshared);
498 return ret;
499}
500
501// pthread_spin_destroy
502PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy
503 pthread_spinlock_t *spinlock)
504{
505 int ret;
506 int res;
507 OrigFn fn;
508 VALGRIND_GET_ORIG_FN(fn);
509 CALL_FN_W_W(ret, fn, spinlock);
510 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
sewardj721ad7b2007-11-30 08:30:29 +0000511 spinlock, mutex_type_spinlock, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000512 return ret;
513}
514
515// pthread_spin_lock
516PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock
517 pthread_spinlock_t *spinlock)
518{
519 int ret;
520 int res;
521 OrigFn fn;
522 VALGRIND_GET_ORIG_FN(fn);
bart00344642008-03-01 15:27:41 +0000523 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK,
524 spinlock, sizeof(*spinlock), mutex_type_spinlock,
525 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000526 CALL_FN_W_W(ret, fn, spinlock);
bart3b1ee452008-02-29 19:28:15 +0000527 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
bart00344642008-03-01 15:27:41 +0000528 spinlock, ret == 0, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000529 return ret;
530}
531
532// pthread_spin_trylock
533PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock
534 pthread_spinlock_t *spinlock)
535{
536 int ret;
537 int res;
538 OrigFn fn;
539 VALGRIND_GET_ORIG_FN(fn);
bart00344642008-03-01 15:27:41 +0000540 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK,
541 spinlock, sizeof(*spinlock), mutex_type_spinlock,
542 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000543 CALL_FN_W_W(ret, fn, spinlock);
bart3b1ee452008-02-29 19:28:15 +0000544 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
bart00344642008-03-01 15:27:41 +0000545 spinlock, ret == 0, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000546 return ret;
547}
548
549// pthread_spin_unlock
550PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock
551 pthread_spinlock_t *spinlock)
552{
553 int ret;
554 int res;
555 OrigFn fn;
556 VALGRIND_GET_ORIG_FN(fn);
557 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SPIN_INIT_OR_UNLOCK,
sewardj721ad7b2007-11-30 08:30:29 +0000558 spinlock, sizeof(*spinlock),
559 mutex_type_spinlock, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000560 CALL_FN_W_W(ret, fn, spinlock);
561 return ret;
562}
563
sewardj85642922008-01-14 11:54:56 +0000564// pthread_barrier_init
565PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init
566 pthread_barrier_t* barrier,
567 const pthread_barrierattr_t* attr,
568 unsigned count)
569{
570 int ret;
571 int res;
572 OrigFn fn;
573 VALGRIND_GET_ORIG_FN(fn);
574 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__BARRIER_INIT,
575 barrier, sizeof(*barrier),
576 count, 0, 0);
577 CALL_FN_W_WWW(ret, fn, barrier, attr, count);
578 return ret;
579}
580
581// pthread_barrier_destroy
582PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy
583 pthread_barrier_t* barrier)
584{
585 int ret;
586 int res;
587 OrigFn fn;
588 VALGRIND_GET_ORIG_FN(fn);
589 CALL_FN_W_W(ret, fn, barrier);
590 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__BARRIER_DESTROY,
591 barrier, 0, 0, 0, 0);
592 return ret;
593}
594
595// pthread_barrier_wait
596PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait
597 pthread_barrier_t* barrier)
598{
599 int ret;
600 int res;
601 OrigFn fn;
602 VALGRIND_GET_ORIG_FN(fn);
603 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT,
604 barrier, 0, 0, 0, 0);
605 CALL_FN_W_W(ret, fn, barrier);
606 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT,
607 barrier,
608 ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD,
609 0, 0, 0);
610 return ret;
611}
612
613
614// From glibc 2.0 linuxthreads/sysdeps/pthread/cmpxchg/semaphorebits.h
615typedef struct { long int sem_status; } sem_t_glibc_2_0;
616
617// sem_init
bart00344642008-03-01 15:27:41 +0000618PTH_FUNC(int, semZuinitZAGLIBCZu2Zd0, // sem_init@GLIBC_2.0
sewardj85642922008-01-14 11:54:56 +0000619 sem_t_glibc_2_0 *sem,
620 int pshared,
621 unsigned int value)
622{
623 int ret;
624 int res;
625 OrigFn fn;
626 VALGRIND_GET_ORIG_FN(fn);
627 CALL_FN_W_WWW(ret, fn, sem, pshared, value);
628 if (ret == 0)
629 {
630 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_INIT,
631 sem, sizeof(*sem),
632 pshared, value, 0);
633 }
634 return ret;
635}
636
bart00344642008-03-01 15:27:41 +0000637PTH_FUNC(int, semZuinitZa, // sem_init*
sewardj85642922008-01-14 11:54:56 +0000638 sem_t *sem,
639 int pshared,
640 unsigned int value)
641{
642 int ret;
643 int res;
644 OrigFn fn;
645 VALGRIND_GET_ORIG_FN(fn);
646 CALL_FN_W_WWW(ret, fn, sem, pshared, value);
647 if (ret == 0)
648 {
649 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_INIT,
650 sem, sizeof(*sem),
651 pshared, value, 0);
652 }
653 return ret;
654}
655
656// sem_destroy
bart00344642008-03-01 15:27:41 +0000657PTH_FUNC(int, semZudestroyZAGLIBCZu2Zd0, // sem_destroy@GLIBC_2.0
sewardj85642922008-01-14 11:54:56 +0000658 sem_t_glibc_2_0 *sem)
659{
660 int ret;
661 int res;
662 OrigFn fn;
663 VALGRIND_GET_ORIG_FN(fn);
664 CALL_FN_W_W(ret, fn, sem);
665 if (ret == 0)
666 {
667 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_DESTROY,
668 sem, 0, 0, 0, 0);
669 }
670 return ret;
671}
672
bart00344642008-03-01 15:27:41 +0000673PTH_FUNC(int, semZudestroyZa, // sem_destroy*
sewardj85642922008-01-14 11:54:56 +0000674 sem_t *sem)
675{
676 int ret;
677 int res;
678 OrigFn fn;
679 VALGRIND_GET_ORIG_FN(fn);
680 CALL_FN_W_W(ret, fn, sem);
681 if (ret == 0)
682 {
683 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_DESTROY,
684 sem, 0, 0, 0, 0);
685 }
686 return ret;
687}
688
689// sem_wait
bart00344642008-03-01 15:27:41 +0000690PTH_FUNC(int, semZuwaitZAGLIBCZu2Zd0, // sem_wait@GLIBC_2.0
sewardj85642922008-01-14 11:54:56 +0000691 sem_t_glibc_2_0 *sem)
692{
693 int ret;
694 int res;
695 OrigFn fn;
696 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000697 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
698 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000699 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000700 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
701 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000702 return ret;
703}
704
bart28230a32008-02-29 17:27:03 +0000705// sem_wait
bart00344642008-03-01 15:27:41 +0000706PTH_FUNC(int, semZuwaitZa, // sem_wait*
sewardj85642922008-01-14 11:54:56 +0000707 sem_t *sem)
708{
709 int ret;
710 int res;
711 OrigFn fn;
712 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000713 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
714 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000715 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000716 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
717 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000718 return ret;
719}
720
721// sem_trywait
bart00344642008-03-01 15:27:41 +0000722PTH_FUNC(int, semZutrywaitZAGLIBCZu2Zd0, // sem_trywait@GLIBC_2.0
sewardj85642922008-01-14 11:54:56 +0000723 sem_t_glibc_2_0 *sem)
724{
725 int ret;
726 int res;
727 OrigFn fn;
728 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000729 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
730 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000731 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000732 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
733 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000734 return ret;
735}
736
bart00344642008-03-01 15:27:41 +0000737PTH_FUNC(int, semZutrywaitZa, // sem_trywait*
sewardj85642922008-01-14 11:54:56 +0000738 sem_t *sem)
739{
740 int ret;
741 int res;
742 OrigFn fn;
743 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000744 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
745 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000746 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000747 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
748 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000749 return ret;
750}
751
752// sem_timedwait
bart00344642008-03-01 15:27:41 +0000753PTH_FUNC(int, semZutimedwait, // sem_timedwait
sewardj85642922008-01-14 11:54:56 +0000754 sem_t *sem, const struct timespec *abs_timeout)
755{
756 int ret;
757 int res;
758 OrigFn fn;
759 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000760 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
761 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000762 CALL_FN_W_WW(ret, fn, sem, abs_timeout);
bart28230a32008-02-29 17:27:03 +0000763 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
764 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000765 return ret;
766}
767
768// sem_post
bart00344642008-03-01 15:27:41 +0000769PTH_FUNC(int, semZupostZAGLIBCZu2Zd0, // sem_post@GLIBC_2.0
sewardj85642922008-01-14 11:54:56 +0000770 sem_t_glibc_2_0 *sem)
771{
772 int ret;
773 int res;
774 OrigFn fn;
775 VALGRIND_GET_ORIG_FN(fn);
776 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST,
777 sem, sizeof(*sem), 0, 0, 0);
778 CALL_FN_W_W(ret, fn, sem);
sewardjc0be9252008-02-11 11:00:51 +0000779 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST,
780 sem, sizeof(*sem), ret == 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000781 return ret;
782}
783
bart00344642008-03-01 15:27:41 +0000784// sem_post
785PTH_FUNC(int, semZupostZa, // sem_post*
sewardj85642922008-01-14 11:54:56 +0000786 sem_t *sem)
787{
788 int ret;
789 int res;
790 OrigFn fn;
791 VALGRIND_GET_ORIG_FN(fn);
792 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST,
793 sem, sizeof(*sem), 0, 0, 0);
794 CALL_FN_W_W(ret, fn, sem);
sewardje3b57aa2008-01-18 07:42:01 +0000795 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST,
796 sem, sizeof(*sem), ret == 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000797 return ret;
798}
799
bart00344642008-03-01 15:27:41 +0000800// pthread_rwlock_init
801PTH_FUNC(int,
802 pthreadZurwlockZuinitZa, // pthread_rwlock_init*
803 pthread_rwlock_t* rwlock,
804 const pthread_rwlockattr_t* attr)
805{
806 int ret;
807 int res;
808 OrigFn fn;
809 VALGRIND_GET_ORIG_FN(fn);
810 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_INIT,
811 rwlock, sizeof(*rwlock), 0, 0, 0);
812 CALL_FN_W_WW(ret, fn, rwlock, attr);
813 return ret;
814}
815
816// pthread_rwlock_destroy
817PTH_FUNC(int,
818 pthreadZurwlockZudestroyZa, // pthread_rwlock_destroy*
819 pthread_rwlock_t* rwlock)
820{
821 int ret;
822 int res;
823 OrigFn fn;
824 VALGRIND_GET_ORIG_FN(fn);
825 CALL_FN_W_W(ret, fn, rwlock);
826 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_DESTROY,
827 rwlock, 0, 0, 0, 0);
828 return ret;
829}
830
831// pthread_rwlock_rdlock
832PTH_FUNC(int,
833 pthreadZurwlockZurdlockZa, // pthread_rwlock_rdlock*
834 pthread_rwlock_t* rwlock)
835{
836 int ret;
837 int res;
838 OrigFn fn;
839 VALGRIND_GET_ORIG_FN(fn);
840 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
841 rwlock, sizeof(*rwlock), 0, 0, 0);
842 CALL_FN_W_W(ret, fn, rwlock);
843 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK,
844 rwlock, ret == 0, 0, 0, 0);
845 return ret;
846}
847
848// pthread_rwlock_wrlock
849PTH_FUNC(int,
850 pthreadZurwlockZuwrlockZa, // pthread_rwlock_wrlock*
851 pthread_rwlock_t* rwlock)
852{
853 int ret;
854 int res;
855 OrigFn fn;
856 VALGRIND_GET_ORIG_FN(fn);
857 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
858 rwlock, sizeof(*rwlock), 0, 0, 0);
859 CALL_FN_W_W(ret, fn, rwlock);
860 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK,
861 rwlock, ret == 0, 0, 0, 0);
862 return ret;
863}
864
865// pthread_rwlock_timedrdlock
866PTH_FUNC(int,
867 pthreadZurwlockZutimedrdlockZa, // pthread_rwlock_timedrdlock*
868 pthread_rwlock_t* rwlock)
869{
870 int ret;
871 int res;
872 OrigFn fn;
873 VALGRIND_GET_ORIG_FN(fn);
874 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
875 rwlock, sizeof(*rwlock), 0, 0, 0);
876 CALL_FN_W_W(ret, fn, rwlock);
877 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK,
878 rwlock, ret == 0, 0, 0, 0);
879 return ret;
880}
881
882// pthread_rwlock_timedwrlock
883PTH_FUNC(int,
884 pthreadZurwlockZutimedwrlockZa, // pthread_rwlock_timedwrlock*
885 pthread_rwlock_t* rwlock)
886{
887 int ret;
888 int res;
889 OrigFn fn;
890 VALGRIND_GET_ORIG_FN(fn);
891 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
892 rwlock, sizeof(*rwlock), 0, 0, 0);
893 CALL_FN_W_W(ret, fn, rwlock);
894 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK,
895 rwlock, ret == 0, 0, 0, 0);
896 return ret;
897}
898
899// pthread_rwlock_tryrdlock
900PTH_FUNC(int,
901 pthreadZurwlockZutryrdlockZa, // pthread_rwlock_tryrdlock*
902 pthread_rwlock_t* rwlock)
903{
904 int ret;
905 int res;
906 OrigFn fn;
907 VALGRIND_GET_ORIG_FN(fn);
908 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
909 rwlock, sizeof(*rwlock), 0, 0, 0);
910 CALL_FN_W_W(ret, fn, rwlock);
911 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK,
912 rwlock, ret == 0, 0, 0, 0);
913 return ret;
914}
915
916// pthread_rwlock_trywrlock
917PTH_FUNC(int,
918 pthreadZurwlockZutrywrlockZa, // pthread_rwlock_trywrlock*
919 pthread_rwlock_t* rwlock)
920{
921 int ret;
922 int res;
923 OrigFn fn;
924 VALGRIND_GET_ORIG_FN(fn);
925 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
926 rwlock, sizeof(*rwlock), 0, 0, 0);
927 CALL_FN_W_W(ret, fn, rwlock);
928 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK,
929 rwlock, ret == 0, 0, 0, 0);
930 return ret;
931}
932
933// pthread_rwlock_unlock
934PTH_FUNC(int,
935 pthreadZurwlockZuunlockZa, // pthread_rwlock_unlock*
936 pthread_rwlock_t* rwlock)
937{
938 int ret;
939 int res;
940 OrigFn fn;
941 VALGRIND_GET_ORIG_FN(fn);
942 CALL_FN_W_W(ret, fn, rwlock);
943 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_UNLOCK,
944 rwlock, ret == 0, 0, 0, 0);
945 return ret;
946}
947
sewardj85642922008-01-14 11:54:56 +0000948
sewardjaf44c822007-11-25 14:01:38 +0000949/*
950 * Local variables:
951 * c-basic-offset: 3
952 * End:
953 */