blob: 2a569785855fdcb65aebdec53d97add510e63c83 [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;
bart5357fcb2008-02-27 15:46:00 +0000103 }
bart635cb162008-02-28 08:30:43 +0000104 return mutex_type_invalid_mutex;
bart5357fcb2008-02-27 15:46:00 +0000105}
106
107static MutexT mutex_type(pthread_mutex_t* mutex)
108{
bartc9463c42008-02-28 07:36:04 +0000109#if defined(_PTHREAD_DESCR_DEFINED)
110 // Linuxthreads.
111 const int kind = mutex->__m_kind;
112#elif defined(__SIZEOF_PTHREAD_MUTEX_T)
113 // NPTL.
114 const int kind = mutex->__data.__kind;
115#else
116 // Another POSIX threads implementation. Regression tests will fail.
117 const int kind = PTHREAD_MUTEX_DEFAULT;
118#endif
119 return pthread_to_drd_mutex_type(kind);
bart5357fcb2008-02-27 15:46:00 +0000120}
121
sewardjaf44c822007-11-25 14:01:38 +0000122static void vg_start_suppression(const void* const p, size_t const size)
123{
124 int res;
125 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_SUPPRESSION,
126 p, size, 0, 0, 0);
127}
128
129#if 0
130static void vg_finish_suppression(const void* const p, size_t const size)
131{
132 int res;
133 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_FINISH_SUPPRESSION,
134 p, size, 0, 0, 0);
135}
136#endif
137
138static void vg_start_recording(void)
139{
140 int res;
141 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_RECORDING,
142 pthread_self(), 0, 0, 0, 0);
143}
144
145static void vg_stop_recording(void)
146{
147 int res;
148 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_STOP_RECORDING,
149 pthread_self(), 0, 0, 0, 0);
150}
151
152static void vg_set_joinable(const pthread_t tid, const int joinable)
153{
154 int res;
155 assert(joinable == 0 || joinable == 1);
sewardjaf44c822007-11-25 14:01:38 +0000156 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__SET_JOINABLE,
157 tid, joinable, 0, 0, 0);
158}
159
160static void* vg_thread_wrapper(void* arg)
161{
162 int res;
163 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK,
164 0, 0, 0, 0, 0);
165
166 {
167 VgPosixThreadArgs* const arg_ptr = (VgPosixThreadArgs*)arg;
168 VgPosixThreadArgs const arg_copy = *arg_ptr;
169 void* result;
170
171#if 0
172 pthread_mutex_lock(arg_ptr->mutex);
173 pthread_cond_signal(arg_ptr->cond);
174 pthread_mutex_unlock(arg_ptr->mutex);
175#else
176 arg_ptr->wrapper_started = 1;
177#endif
178
179 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
180 pthread_self(), 0, 0, 0, 0);
181 vg_set_joinable(pthread_self(),
182 arg_copy.detachstate == PTHREAD_CREATE_JOINABLE);
183 result = (arg_copy.start)(arg_copy.arg);
184 return result;
185 }
186}
187
188static void vg_set_main_thread_state(void)
189{
190 int res;
191
192 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK,
193 0, 0, 0, 0, 0);
194
sewardjaf44c822007-11-25 14:01:38 +0000195 // Make sure that DRD knows about the main thread's POSIX thread ID.
196 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
197 pthread_self(), 0, 0, 0, 0);
198
199}
200
201// pthread_create
sewardj347eeba2008-01-21 14:19:07 +0000202PTH_FUNC(int, pthreadZucreateZa, // pthread_create*
sewardjaf44c822007-11-25 14:01:38 +0000203 pthread_t *thread, const pthread_attr_t *attr,
204 void *(*start) (void *), void *arg)
205{
206 int ret;
207 OrigFn fn;
208 VgPosixThreadArgs vgargs;
209
210 VALGRIND_GET_ORIG_FN(fn);
211
212 if (vg_main_thread_state_is_set == 0)
213 {
214 vg_set_main_thread_state();
215 vg_main_thread_state_is_set = 1;
216 }
217 vg_start_suppression(&vgargs.wrapper_started,
218 sizeof(vgargs.wrapper_started));
219 vgargs.start = start;
220 vgargs.arg = arg;
221 vgargs.wrapper_started = 0;
222 vgargs.detachstate = PTHREAD_CREATE_JOINABLE;
223 if (attr)
224 {
225 if (pthread_attr_getdetachstate(attr, &vgargs.detachstate) != 0)
226 {
227 assert(0);
228 }
sewardjaf44c822007-11-25 14:01:38 +0000229 }
230 assert(vgargs.detachstate == PTHREAD_CREATE_JOINABLE
231 || vgargs.detachstate == PTHREAD_CREATE_DETACHED);
232#if 0
233 pthread_mutex_init(&vgargs.mutex, 0);
234 pthread_cond_init(&vgargs.cond, 0);
235 pthread_mutex_lock(&vgargs.mutex);
236#endif
237 vg_stop_recording();
238 CALL_FN_W_WWWW(ret, fn, thread, attr, vg_thread_wrapper, &vgargs);
239 vg_start_recording();
240#if 0
241 pthread_cond_wait(&vgargs.cond, &vgargs.mutex);
242 pthread_mutex_unlock(&vgargs.mutex);
243 pthread_cond_destroy(&vgargs.cond);
244 pthread_mutex_destroy(&vgargs.mutex);
245#else
246 // Yes, you see it correctly, busy waiting ... The problem is that
247 // POSIX threads functions cannot be called here -- the functions defined
sewardj85642922008-01-14 11:54:56 +0000248 // in this file (drd_intercepts.c) would be called instead of those in
sewardjaf44c822007-11-25 14:01:38 +0000249 // libpthread.so. This loop is necessary because vgargs is allocated on the
250 // stack, and the created thread reads it.
sewardje0744f02007-12-01 02:09:50 +0000251 if (ret == 0)
sewardjaf44c822007-11-25 14:01:38 +0000252 {
sewardje0744f02007-12-01 02:09:50 +0000253 while (! vgargs.wrapper_started)
254 {
255 sched_yield();
256 }
sewardjaf44c822007-11-25 14:01:38 +0000257 }
258#endif
259 return ret;
260}
261
262// pthread_join
263PTH_FUNC(int, pthreadZujoin, // pthread_join
264 pthread_t pt_joinee, void **thread_return)
265{
266 int ret;
267 int res;
268 OrigFn fn;
269
270 VALGRIND_GET_ORIG_FN(fn);
271 CALL_FN_W_WW(ret, fn, pt_joinee, thread_return);
272 if (ret == 0)
273 {
274 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_JOIN,
275 pt_joinee, 0, 0, 0, 0);
276 }
277 return ret;
278}
279
280// pthread_detach
281PTH_FUNC(int, pthreadZudetach, pthread_t pt_thread)
282{
283 int ret;
284 OrigFn fn;
285 VALGRIND_GET_ORIG_FN(fn);
286 {
287 CALL_FN_W_W(ret, fn, pt_thread);
288 if (ret == 0)
289 {
290 vg_set_joinable(pt_thread, 0);
291 }
292 }
293 return ret;
294}
295
296// pthread_mutex_init
297PTH_FUNC(int, pthreadZumutexZuinit,
298 pthread_mutex_t *mutex,
299 const pthread_mutexattr_t* attr)
300{
301 int ret;
302 int res;
303 OrigFn fn;
bart5357fcb2008-02-27 15:46:00 +0000304 int mt = PTHREAD_MUTEX_DEFAULT;
sewardjaf44c822007-11-25 14:01:38 +0000305 VALGRIND_GET_ORIG_FN(fn);
bart5357fcb2008-02-27 15:46:00 +0000306 if (attr)
307 pthread_mutexattr_gettype(attr, &mt);
sewardjaf44c822007-11-25 14:01:38 +0000308 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT,
bart5357fcb2008-02-27 15:46:00 +0000309 mutex, sizeof(*mutex),
310 pthread_to_drd_mutex_type(mt), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000311 CALL_FN_W_WW(ret, fn, mutex, attr);
312 return ret;
313}
314
315// pthread_mutex_destroy
316PTH_FUNC(int, pthreadZumutexZudestroy,
317 pthread_mutex_t *mutex)
318{
319 int ret;
320 int res;
321 OrigFn fn;
322 VALGRIND_GET_ORIG_FN(fn);
323 CALL_FN_W_W(ret, fn, mutex);
324 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
bart5357fcb2008-02-27 15:46:00 +0000325 mutex, mutex_type(mutex), 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000326 return ret;
327}
328
329// pthread_mutex_lock
330PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock
331 pthread_mutex_t *mutex)
332{
333 int ret;
334 int res;
335 OrigFn fn;
336 VALGRIND_GET_ORIG_FN(fn);
337 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK,
bart5357fcb2008-02-27 15:46:00 +0000338 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000339#if 1
340 // The only purpose of the system call below is to make drd work on AMD64
341 // systems. Without this system call, clients crash (SIGSEGV) in
342 // std::locale::locale().
343 write(1, "", 0);
344#endif
345 CALL_FN_W_W(ret, fn, mutex);
346 if (ret == 0)
347 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_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 return ret;
350}
351
352// pthread_mutex_trylock
353PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock
354 pthread_mutex_t *mutex)
355{
356 int ret;
357 int res;
358 OrigFn fn;
359 VALGRIND_GET_ORIG_FN(fn);
360 CALL_FN_W_W(ret, fn, mutex);
361 if (ret == 0)
362 {
363 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
bart5357fcb2008-02-27 15:46:00 +0000364 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000365 }
366 return ret;
367}
368
sewardj85642922008-01-14 11:54:56 +0000369// pthread_mutex_timedlock
370PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock
371 pthread_mutex_t *mutex,
372 const struct timespec *abs_timeout)
373{
374 int ret;
375 int res;
376 OrigFn fn;
377 VALGRIND_GET_ORIG_FN(fn);
378 CALL_FN_W_WW(ret, fn, mutex, abs_timeout);
379 if (ret == 0)
380 {
381 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
bart5357fcb2008-02-27 15:46:00 +0000382 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardj85642922008-01-14 11:54:56 +0000383 }
384 return ret;
385}
386
sewardjaf44c822007-11-25 14:01:38 +0000387// pthread_mutex_unlock
388PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock
389 pthread_mutex_t *mutex)
390{
391 int ret;
392 int res;
393 OrigFn fn;
394 VALGRIND_GET_ORIG_FN(fn);
395 VALGRIND_DO_CLIENT_REQUEST(res, -1,
396 VG_USERREQ__PRE_PTHREAD_MUTEX_UNLOCK,
bart5357fcb2008-02-27 15:46:00 +0000397 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000398 CALL_FN_W_W(ret, fn, mutex);
399 return ret;
400}
401
402// pthread_cond_init
sewardj347eeba2008-01-21 14:19:07 +0000403PTH_FUNC(int, pthreadZucondZuinitZa, // pthread_cond_init*
sewardjaf44c822007-11-25 14:01:38 +0000404 pthread_cond_t* cond,
405 const pthread_condattr_t* attr)
406{
407 int ret;
408 int res;
409 OrigFn fn;
410 VALGRIND_GET_ORIG_FN(fn);
411 CALL_FN_W_WW(ret, fn, cond, attr);
412 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_INIT,
413 cond, sizeof(*cond), 0, 0, 0);
414 return ret;
415}
416
417// pthread_cond_destroy
sewardj347eeba2008-01-21 14:19:07 +0000418PTH_FUNC(int, pthreadZucondZudestroyZa, // pthread_cond_destroy*
sewardjaf44c822007-11-25 14:01:38 +0000419 pthread_cond_t* cond)
420{
421 int ret;
422 int res;
423 OrigFn fn;
424 VALGRIND_GET_ORIG_FN(fn);
425 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_DESTROY,
sewardj721ad7b2007-11-30 08:30:29 +0000426 cond, 0, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000427 CALL_FN_W_W(ret, fn, cond);
428 return ret;
429}
430
431// pthread_cond_wait
sewardj347eeba2008-01-21 14:19:07 +0000432PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait*
sewardjaf44c822007-11-25 14:01:38 +0000433 pthread_cond_t *cond,
434 pthread_mutex_t *mutex)
435{
436 int ret;
437 int res;
438 OrigFn fn;
439 VALGRIND_GET_ORIG_FN(fn);
440 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_WAIT,
bart5357fcb2008-02-27 15:46:00 +0000441 cond, sizeof(*cond), mutex, mutex_type(mutex), 0);
sewardjaf44c822007-11-25 14:01:38 +0000442 CALL_FN_W_WW(ret, fn, cond, mutex);
443 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_WAIT,
bart5357fcb2008-02-27 15:46:00 +0000444 cond, mutex, sizeof(*mutex), mutex_type(mutex), 0);
sewardjaf44c822007-11-25 14:01:38 +0000445 return ret;
446}
447
448// pthread_cond_timedwait
sewardj347eeba2008-01-21 14:19:07 +0000449PTH_FUNC(int, pthreadZucondZutimedwaitZa, // pthread_cond_timedwait*
sewardjaf44c822007-11-25 14:01:38 +0000450 pthread_cond_t *cond,
451 pthread_mutex_t *mutex,
452 const struct timespec* abstime)
453{
454 int ret;
455 int res;
456 OrigFn fn;
457 VALGRIND_GET_ORIG_FN(fn);
458 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_WAIT,
bart5357fcb2008-02-27 15:46:00 +0000459 cond, sizeof(*cond), mutex, mutex_type(mutex), 0);
sewardjaf44c822007-11-25 14:01:38 +0000460 CALL_FN_W_WWW(ret, fn, cond, mutex, abstime);
461 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_WAIT,
bart5357fcb2008-02-27 15:46:00 +0000462 cond, mutex, sizeof(*mutex), mutex_type(mutex), 0);
sewardjaf44c822007-11-25 14:01:38 +0000463 return ret;
464}
465
466// pthread_cond_signal
sewardj347eeba2008-01-21 14:19:07 +0000467PTH_FUNC(int, pthreadZucondZusignalZa, // pthread_cond_signal*
sewardjaf44c822007-11-25 14:01:38 +0000468 pthread_cond_t* cond)
469{
470 int ret;
471 int res;
472 OrigFn fn;
473 VALGRIND_GET_ORIG_FN(fn);
474 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_SIGNAL,
475 cond, 0, 0, 0, 0);
476 CALL_FN_W_W(ret, fn, cond);
477 return ret;
478}
479
480// pthread_cond_broadcast
sewardj347eeba2008-01-21 14:19:07 +0000481PTH_FUNC(int, pthreadZucondZubroadcastZa, // pthread_cond_broadcast*
sewardjaf44c822007-11-25 14:01:38 +0000482 pthread_cond_t* cond)
483{
484 int ret;
485 int res;
486 OrigFn fn;
487 VALGRIND_GET_ORIG_FN(fn);
488 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_BROADCAST,
489 cond, 0, 0, 0, 0);
490 CALL_FN_W_W(ret, fn, cond);
491 return ret;
492}
493
494
495// pthread_spin_init
496PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init
497 pthread_spinlock_t *spinlock,
498 int pshared)
499{
500 int ret;
501 int res;
502 OrigFn fn;
503 VALGRIND_GET_ORIG_FN(fn);
504 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SPIN_INIT_OR_UNLOCK,
sewardj721ad7b2007-11-30 08:30:29 +0000505 spinlock, sizeof(*spinlock),
506 mutex_type_spinlock, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000507 CALL_FN_W_WW(ret, fn, spinlock, pshared);
508 return ret;
509}
510
511// pthread_spin_destroy
512PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy
513 pthread_spinlock_t *spinlock)
514{
515 int ret;
516 int res;
517 OrigFn fn;
518 VALGRIND_GET_ORIG_FN(fn);
519 CALL_FN_W_W(ret, fn, spinlock);
520 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
sewardj721ad7b2007-11-30 08:30:29 +0000521 spinlock, mutex_type_spinlock, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000522 return ret;
523}
524
525// pthread_spin_lock
526PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock
527 pthread_spinlock_t *spinlock)
528{
529 int ret;
530 int res;
531 OrigFn fn;
532 VALGRIND_GET_ORIG_FN(fn);
533 CALL_FN_W_W(ret, fn, spinlock);
534 if (ret == 0)
535 {
536 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
sewardj721ad7b2007-11-30 08:30:29 +0000537 spinlock, sizeof(*spinlock),
538 mutex_type_spinlock, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000539 }
540 return ret;
541}
542
543// pthread_spin_trylock
544PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock
545 pthread_spinlock_t *spinlock)
546{
547 int ret;
548 int res;
549 OrigFn fn;
550 VALGRIND_GET_ORIG_FN(fn);
551 CALL_FN_W_W(ret, fn, spinlock);
552 if (ret == 0)
553 {
554 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
sewardj721ad7b2007-11-30 08:30:29 +0000555 spinlock, sizeof(*spinlock),
556 mutex_type_spinlock, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000557 }
558 return ret;
559}
560
561// pthread_spin_unlock
562PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock
563 pthread_spinlock_t *spinlock)
564{
565 int ret;
566 int res;
567 OrigFn fn;
568 VALGRIND_GET_ORIG_FN(fn);
569 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SPIN_INIT_OR_UNLOCK,
sewardj721ad7b2007-11-30 08:30:29 +0000570 spinlock, sizeof(*spinlock),
571 mutex_type_spinlock, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000572 CALL_FN_W_W(ret, fn, spinlock);
573 return ret;
574}
575
sewardj85642922008-01-14 11:54:56 +0000576// pthread_barrier_init
577PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init
578 pthread_barrier_t* barrier,
579 const pthread_barrierattr_t* attr,
580 unsigned count)
581{
582 int ret;
583 int res;
584 OrigFn fn;
585 VALGRIND_GET_ORIG_FN(fn);
586 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__BARRIER_INIT,
587 barrier, sizeof(*barrier),
588 count, 0, 0);
589 CALL_FN_W_WWW(ret, fn, barrier, attr, count);
590 return ret;
591}
592
593// pthread_barrier_destroy
594PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy
595 pthread_barrier_t* barrier)
596{
597 int ret;
598 int res;
599 OrigFn fn;
600 VALGRIND_GET_ORIG_FN(fn);
601 CALL_FN_W_W(ret, fn, barrier);
602 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__BARRIER_DESTROY,
603 barrier, 0, 0, 0, 0);
604 return ret;
605}
606
607// pthread_barrier_wait
608PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait
609 pthread_barrier_t* barrier)
610{
611 int ret;
612 int res;
613 OrigFn fn;
614 VALGRIND_GET_ORIG_FN(fn);
615 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT,
616 barrier, 0, 0, 0, 0);
617 CALL_FN_W_W(ret, fn, barrier);
618 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT,
619 barrier,
620 ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD,
621 0, 0, 0);
622 return ret;
623}
624
625
626// From glibc 2.0 linuxthreads/sysdeps/pthread/cmpxchg/semaphorebits.h
627typedef struct { long int sem_status; } sem_t_glibc_2_0;
628
629// sem_init
630PTH_FUNC(int, sem_initZAGLIBCZu2Zd0, // sem_init@GLIBC_2.0
631 sem_t_glibc_2_0 *sem,
632 int pshared,
633 unsigned int value)
634{
635 int ret;
636 int res;
637 OrigFn fn;
638 VALGRIND_GET_ORIG_FN(fn);
639 CALL_FN_W_WWW(ret, fn, sem, pshared, value);
640 if (ret == 0)
641 {
642 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_INIT,
643 sem, sizeof(*sem),
644 pshared, value, 0);
645 }
646 return ret;
647}
648
649PTH_FUNC(int, sem_initZa, // sem_init*
650 sem_t *sem,
651 int pshared,
652 unsigned int value)
653{
654 int ret;
655 int res;
656 OrigFn fn;
657 VALGRIND_GET_ORIG_FN(fn);
658 CALL_FN_W_WWW(ret, fn, sem, pshared, value);
659 if (ret == 0)
660 {
661 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_INIT,
662 sem, sizeof(*sem),
663 pshared, value, 0);
664 }
665 return ret;
666}
667
668// sem_destroy
669PTH_FUNC(int, sem_destroyZAGLIBCZu2Zd0, // sem_destroy@GLIBC_2.0
670 sem_t_glibc_2_0 *sem)
671{
672 int ret;
673 int res;
674 OrigFn fn;
675 VALGRIND_GET_ORIG_FN(fn);
676 CALL_FN_W_W(ret, fn, sem);
677 if (ret == 0)
678 {
679 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_DESTROY,
680 sem, 0, 0, 0, 0);
681 }
682 return ret;
683}
684
685PTH_FUNC(int, sem_destroyZa, // sem_destroy*
686 sem_t *sem)
687{
688 int ret;
689 int res;
690 OrigFn fn;
691 VALGRIND_GET_ORIG_FN(fn);
692 CALL_FN_W_W(ret, fn, sem);
693 if (ret == 0)
694 {
695 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_DESTROY,
696 sem, 0, 0, 0, 0);
697 }
698 return ret;
699}
700
701// sem_wait
702PTH_FUNC(int, sem_waitZAGLIBCZu2Zd0, // sem_wait@GLIBC_2.0
703 sem_t_glibc_2_0 *sem)
704{
705 int ret;
706 int res;
707 OrigFn fn;
708 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000709 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
710 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000711 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000712 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
713 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000714 return ret;
715}
716
bart28230a32008-02-29 17:27:03 +0000717// sem_wait
sewardj85642922008-01-14 11:54:56 +0000718PTH_FUNC(int, sem_waitZa, // sem_wait*
719 sem_t *sem)
720{
721 int ret;
722 int res;
723 OrigFn fn;
724 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000725 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
726 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000727 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000728 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
729 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000730 return ret;
731}
732
733// sem_trywait
734PTH_FUNC(int, sem_trywaitZAGLIBCZu2Zd0, // sem_trywait@GLIBC_2.0
735 sem_t_glibc_2_0 *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
749PTH_FUNC(int, sem_trywaitZa, // sem_trywait*
750 sem_t *sem)
751{
752 int ret;
753 int res;
754 OrigFn fn;
755 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000756 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
757 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000758 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000759 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
760 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000761 return ret;
762}
763
764// sem_timedwait
765PTH_FUNC(int, sem_timedwait, // sem_timedwait
766 sem_t *sem, const struct timespec *abs_timeout)
767{
768 int ret;
769 int res;
770 OrigFn fn;
771 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000772 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
773 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000774 CALL_FN_W_WW(ret, fn, sem, abs_timeout);
bart28230a32008-02-29 17:27:03 +0000775 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
776 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000777 return ret;
778}
779
780// sem_post
781PTH_FUNC(int, sem_postZAGLIBCZu2Zd0, // sem_post@GLIBC_2.0
782 sem_t_glibc_2_0 *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);
sewardjc0be9252008-02-11 11:00:51 +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
796PTH_FUNC(int, sem_postZa, // sem_post*
797 sem_t *sem)
798{
799 int ret;
800 int res;
801 OrigFn fn;
802 VALGRIND_GET_ORIG_FN(fn);
803 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST,
804 sem, sizeof(*sem), 0, 0, 0);
805 CALL_FN_W_W(ret, fn, sem);
sewardje3b57aa2008-01-18 07:42:01 +0000806 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST,
807 sem, sizeof(*sem), ret == 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000808 return ret;
809}
810
811/*
812pthread_rwlock_destroy
813pthread_rwlock_init
814pthread_rwlock_rdlock
815pthread_rwlock_timedrdlock
816pthread_rwlock_timedwrlock
817pthread_rwlock_tryrdlock
818pthread_rwlock_trywrlock
819pthread_rwlock_unlock
820pthread_rwlock_wrlock
821pthread_rwlockattr_destroy
822pthread_rwlockattr_getkind_np
823pthread_rwlockattr_getpshared
824pthread_rwlockattr_init
825pthread_rwlockattr_setkind_np
826pthread_rwlockattr_setpshared
827 */
828
sewardjaf44c822007-11-25 14:01:38 +0000829/*
830 * Local variables:
831 * c-basic-offset: 3
832 * End:
833 */