blob: 4c54f5d25d82a473b186ea13924ccb16f0339c4a [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,
338 mutex, sizeof(*mutex), mutex_type(mutex),
339 ret == 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000340 return ret;
341}
342
343// pthread_mutex_trylock
344PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock
345 pthread_mutex_t *mutex)
346{
347 int ret;
348 int res;
349 OrigFn fn;
350 VALGRIND_GET_ORIG_FN(fn);
351 CALL_FN_W_W(ret, fn, mutex);
bart3b1ee452008-02-29 19:28:15 +0000352 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
353 mutex, sizeof(*mutex), mutex_type(mutex),
354 ret == 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);
367 CALL_FN_W_WW(ret, fn, mutex, abs_timeout);
bart3b1ee452008-02-29 19:28:15 +0000368 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
369 mutex, sizeof(*mutex), mutex_type(mutex),
370 ret == 0, 0);
sewardj85642922008-01-14 11:54:56 +0000371 return ret;
372}
373
sewardjaf44c822007-11-25 14:01:38 +0000374// pthread_mutex_unlock
375PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock
376 pthread_mutex_t *mutex)
377{
378 int ret;
379 int res;
380 OrigFn fn;
381 VALGRIND_GET_ORIG_FN(fn);
382 VALGRIND_DO_CLIENT_REQUEST(res, -1,
383 VG_USERREQ__PRE_PTHREAD_MUTEX_UNLOCK,
bart5357fcb2008-02-27 15:46:00 +0000384 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000385 CALL_FN_W_W(ret, fn, mutex);
386 return ret;
387}
388
389// pthread_cond_init
sewardj347eeba2008-01-21 14:19:07 +0000390PTH_FUNC(int, pthreadZucondZuinitZa, // pthread_cond_init*
sewardjaf44c822007-11-25 14:01:38 +0000391 pthread_cond_t* cond,
392 const pthread_condattr_t* attr)
393{
394 int ret;
395 int res;
396 OrigFn fn;
397 VALGRIND_GET_ORIG_FN(fn);
398 CALL_FN_W_WW(ret, fn, cond, attr);
399 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_INIT,
400 cond, sizeof(*cond), 0, 0, 0);
401 return ret;
402}
403
404// pthread_cond_destroy
sewardj347eeba2008-01-21 14:19:07 +0000405PTH_FUNC(int, pthreadZucondZudestroyZa, // pthread_cond_destroy*
sewardjaf44c822007-11-25 14:01:38 +0000406 pthread_cond_t* cond)
407{
408 int ret;
409 int res;
410 OrigFn fn;
411 VALGRIND_GET_ORIG_FN(fn);
412 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_DESTROY,
sewardj721ad7b2007-11-30 08:30:29 +0000413 cond, 0, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000414 CALL_FN_W_W(ret, fn, cond);
415 return ret;
416}
417
418// pthread_cond_wait
sewardj347eeba2008-01-21 14:19:07 +0000419PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait*
sewardjaf44c822007-11-25 14:01:38 +0000420 pthread_cond_t *cond,
421 pthread_mutex_t *mutex)
422{
423 int ret;
424 int res;
425 OrigFn fn;
426 VALGRIND_GET_ORIG_FN(fn);
427 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_WAIT,
bart3b1ee452008-02-29 19:28:15 +0000428 cond, sizeof(*cond), mutex, mutex_type(mutex),
429 0);
sewardjaf44c822007-11-25 14:01:38 +0000430 CALL_FN_W_WW(ret, fn, cond, mutex);
431 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_WAIT,
bart3b1ee452008-02-29 19:28:15 +0000432 cond, mutex, sizeof(*mutex), mutex_type(mutex),
433 ret == 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,
bart3b1ee452008-02-29 19:28:15 +0000452 cond, mutex, sizeof(*mutex), mutex_type(mutex),
453 ret == 0);
sewardjaf44c822007-11-25 14:01:38 +0000454 return ret;
455}
456
457// pthread_cond_signal
sewardj347eeba2008-01-21 14:19:07 +0000458PTH_FUNC(int, pthreadZucondZusignalZa, // pthread_cond_signal*
sewardjaf44c822007-11-25 14:01:38 +0000459 pthread_cond_t* cond)
460{
461 int ret;
462 int res;
463 OrigFn fn;
464 VALGRIND_GET_ORIG_FN(fn);
465 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_SIGNAL,
466 cond, 0, 0, 0, 0);
467 CALL_FN_W_W(ret, fn, cond);
468 return ret;
469}
470
471// pthread_cond_broadcast
sewardj347eeba2008-01-21 14:19:07 +0000472PTH_FUNC(int, pthreadZucondZubroadcastZa, // pthread_cond_broadcast*
sewardjaf44c822007-11-25 14:01:38 +0000473 pthread_cond_t* cond)
474{
475 int ret;
476 int res;
477 OrigFn fn;
478 VALGRIND_GET_ORIG_FN(fn);
479 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_BROADCAST,
480 cond, 0, 0, 0, 0);
481 CALL_FN_W_W(ret, fn, cond);
482 return ret;
483}
484
485
486// pthread_spin_init
487PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init
488 pthread_spinlock_t *spinlock,
489 int pshared)
490{
491 int ret;
492 int res;
493 OrigFn fn;
494 VALGRIND_GET_ORIG_FN(fn);
495 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SPIN_INIT_OR_UNLOCK,
sewardj721ad7b2007-11-30 08:30:29 +0000496 spinlock, sizeof(*spinlock),
497 mutex_type_spinlock, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000498 CALL_FN_W_WW(ret, fn, spinlock, pshared);
499 return ret;
500}
501
502// pthread_spin_destroy
503PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy
504 pthread_spinlock_t *spinlock)
505{
506 int ret;
507 int res;
508 OrigFn fn;
509 VALGRIND_GET_ORIG_FN(fn);
510 CALL_FN_W_W(ret, fn, spinlock);
511 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
sewardj721ad7b2007-11-30 08:30:29 +0000512 spinlock, mutex_type_spinlock, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000513 return ret;
514}
515
516// pthread_spin_lock
517PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock
518 pthread_spinlock_t *spinlock)
519{
520 int ret;
521 int res;
522 OrigFn fn;
523 VALGRIND_GET_ORIG_FN(fn);
524 CALL_FN_W_W(ret, fn, spinlock);
bart3b1ee452008-02-29 19:28:15 +0000525 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
526 spinlock, sizeof(*spinlock),
527 mutex_type_spinlock, ret == 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000528 return ret;
529}
530
531// pthread_spin_trylock
532PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock
533 pthread_spinlock_t *spinlock)
534{
535 int ret;
536 int res;
537 OrigFn fn;
538 VALGRIND_GET_ORIG_FN(fn);
539 CALL_FN_W_W(ret, fn, spinlock);
bart3b1ee452008-02-29 19:28:15 +0000540 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
541 spinlock, sizeof(*spinlock),
542 mutex_type_spinlock, ret == 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000543 return ret;
544}
545
546// pthread_spin_unlock
547PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock
548 pthread_spinlock_t *spinlock)
549{
550 int ret;
551 int res;
552 OrigFn fn;
553 VALGRIND_GET_ORIG_FN(fn);
554 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SPIN_INIT_OR_UNLOCK,
sewardj721ad7b2007-11-30 08:30:29 +0000555 spinlock, sizeof(*spinlock),
556 mutex_type_spinlock, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000557 CALL_FN_W_W(ret, fn, spinlock);
558 return ret;
559}
560
sewardj85642922008-01-14 11:54:56 +0000561// pthread_barrier_init
562PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init
563 pthread_barrier_t* barrier,
564 const pthread_barrierattr_t* attr,
565 unsigned count)
566{
567 int ret;
568 int res;
569 OrigFn fn;
570 VALGRIND_GET_ORIG_FN(fn);
571 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__BARRIER_INIT,
572 barrier, sizeof(*barrier),
573 count, 0, 0);
574 CALL_FN_W_WWW(ret, fn, barrier, attr, count);
575 return ret;
576}
577
578// pthread_barrier_destroy
579PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy
580 pthread_barrier_t* barrier)
581{
582 int ret;
583 int res;
584 OrigFn fn;
585 VALGRIND_GET_ORIG_FN(fn);
586 CALL_FN_W_W(ret, fn, barrier);
587 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__BARRIER_DESTROY,
588 barrier, 0, 0, 0, 0);
589 return ret;
590}
591
592// pthread_barrier_wait
593PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait
594 pthread_barrier_t* barrier)
595{
596 int ret;
597 int res;
598 OrigFn fn;
599 VALGRIND_GET_ORIG_FN(fn);
600 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT,
601 barrier, 0, 0, 0, 0);
602 CALL_FN_W_W(ret, fn, barrier);
603 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT,
604 barrier,
605 ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD,
606 0, 0, 0);
607 return ret;
608}
609
610
611// From glibc 2.0 linuxthreads/sysdeps/pthread/cmpxchg/semaphorebits.h
612typedef struct { long int sem_status; } sem_t_glibc_2_0;
613
614// sem_init
615PTH_FUNC(int, sem_initZAGLIBCZu2Zd0, // sem_init@GLIBC_2.0
616 sem_t_glibc_2_0 *sem,
617 int pshared,
618 unsigned int value)
619{
620 int ret;
621 int res;
622 OrigFn fn;
623 VALGRIND_GET_ORIG_FN(fn);
624 CALL_FN_W_WWW(ret, fn, sem, pshared, value);
625 if (ret == 0)
626 {
627 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_INIT,
628 sem, sizeof(*sem),
629 pshared, value, 0);
630 }
631 return ret;
632}
633
634PTH_FUNC(int, sem_initZa, // sem_init*
635 sem_t *sem,
636 int pshared,
637 unsigned int value)
638{
639 int ret;
640 int res;
641 OrigFn fn;
642 VALGRIND_GET_ORIG_FN(fn);
643 CALL_FN_W_WWW(ret, fn, sem, pshared, value);
644 if (ret == 0)
645 {
646 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_INIT,
647 sem, sizeof(*sem),
648 pshared, value, 0);
649 }
650 return ret;
651}
652
653// sem_destroy
654PTH_FUNC(int, sem_destroyZAGLIBCZu2Zd0, // sem_destroy@GLIBC_2.0
655 sem_t_glibc_2_0 *sem)
656{
657 int ret;
658 int res;
659 OrigFn fn;
660 VALGRIND_GET_ORIG_FN(fn);
661 CALL_FN_W_W(ret, fn, sem);
662 if (ret == 0)
663 {
664 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_DESTROY,
665 sem, 0, 0, 0, 0);
666 }
667 return ret;
668}
669
670PTH_FUNC(int, sem_destroyZa, // sem_destroy*
671 sem_t *sem)
672{
673 int ret;
674 int res;
675 OrigFn fn;
676 VALGRIND_GET_ORIG_FN(fn);
677 CALL_FN_W_W(ret, fn, sem);
678 if (ret == 0)
679 {
680 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_DESTROY,
681 sem, 0, 0, 0, 0);
682 }
683 return ret;
684}
685
686// sem_wait
687PTH_FUNC(int, sem_waitZAGLIBCZu2Zd0, // sem_wait@GLIBC_2.0
688 sem_t_glibc_2_0 *sem)
689{
690 int ret;
691 int res;
692 OrigFn fn;
693 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000694 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
695 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000696 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000697 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
698 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000699 return ret;
700}
701
bart28230a32008-02-29 17:27:03 +0000702// sem_wait
sewardj85642922008-01-14 11:54:56 +0000703PTH_FUNC(int, sem_waitZa, // sem_wait*
704 sem_t *sem)
705{
706 int ret;
707 int res;
708 OrigFn fn;
709 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000710 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
711 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000712 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000713 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
714 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000715 return ret;
716}
717
718// sem_trywait
719PTH_FUNC(int, sem_trywaitZAGLIBCZu2Zd0, // sem_trywait@GLIBC_2.0
720 sem_t_glibc_2_0 *sem)
721{
722 int ret;
723 int res;
724 OrigFn fn;
725 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000726 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
727 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000728 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000729 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
730 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000731 return ret;
732}
733
734PTH_FUNC(int, sem_trywaitZa, // sem_trywait*
735 sem_t *sem)
736{
737 int ret;
738 int res;
739 OrigFn fn;
740 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000741 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
742 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000743 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000744 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
745 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000746 return ret;
747}
748
749// sem_timedwait
750PTH_FUNC(int, sem_timedwait, // sem_timedwait
751 sem_t *sem, const struct timespec *abs_timeout)
752{
753 int ret;
754 int res;
755 OrigFn fn;
756 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000757 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
758 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000759 CALL_FN_W_WW(ret, fn, sem, abs_timeout);
bart28230a32008-02-29 17:27:03 +0000760 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
761 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000762 return ret;
763}
764
765// sem_post
766PTH_FUNC(int, sem_postZAGLIBCZu2Zd0, // sem_post@GLIBC_2.0
767 sem_t_glibc_2_0 *sem)
768{
769 int ret;
770 int res;
771 OrigFn fn;
772 VALGRIND_GET_ORIG_FN(fn);
773 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST,
774 sem, sizeof(*sem), 0, 0, 0);
775 CALL_FN_W_W(ret, fn, sem);
sewardjc0be9252008-02-11 11:00:51 +0000776 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST,
777 sem, sizeof(*sem), ret == 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000778 return ret;
779}
780
781PTH_FUNC(int, sem_postZa, // sem_post*
782 sem_t *sem)
783{
784 int ret;
785 int res;
786 OrigFn fn;
787 VALGRIND_GET_ORIG_FN(fn);
788 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST,
789 sem, sizeof(*sem), 0, 0, 0);
790 CALL_FN_W_W(ret, fn, sem);
sewardje3b57aa2008-01-18 07:42:01 +0000791 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST,
792 sem, sizeof(*sem), ret == 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000793 return ret;
794}
795
796/*
797pthread_rwlock_destroy
798pthread_rwlock_init
799pthread_rwlock_rdlock
800pthread_rwlock_timedrdlock
801pthread_rwlock_timedwrlock
802pthread_rwlock_tryrdlock
803pthread_rwlock_trywrlock
804pthread_rwlock_unlock
805pthread_rwlock_wrlock
806pthread_rwlockattr_destroy
807pthread_rwlockattr_getkind_np
808pthread_rwlockattr_getpshared
809pthread_rwlockattr_init
810pthread_rwlockattr_setkind_np
811pthread_rwlockattr_setpshared
812 */
813
sewardjaf44c822007-11-25 14:01:38 +0000814/*
815 * Local variables:
816 * c-basic-offset: 3
817 * End:
818 */