blob: 6e14d639234e4e0bd27d991ad0697b36934fc141 [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);
bart3b1ee452008-02-29 19:28:15 +0000346 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
347 mutex, sizeof(*mutex), mutex_type(mutex),
348 ret == 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);
bart3b1ee452008-02-29 19:28:15 +0000361 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
362 mutex, sizeof(*mutex), mutex_type(mutex),
363 ret == 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000364 return ret;
365}
366
sewardj85642922008-01-14 11:54:56 +0000367// pthread_mutex_timedlock
368PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock
369 pthread_mutex_t *mutex,
370 const struct timespec *abs_timeout)
371{
372 int ret;
373 int res;
374 OrigFn fn;
375 VALGRIND_GET_ORIG_FN(fn);
376 CALL_FN_W_WW(ret, fn, mutex, abs_timeout);
bart3b1ee452008-02-29 19:28:15 +0000377 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
378 mutex, sizeof(*mutex), mutex_type(mutex),
379 ret == 0, 0);
sewardj85642922008-01-14 11:54:56 +0000380 return ret;
381}
382
sewardjaf44c822007-11-25 14:01:38 +0000383// pthread_mutex_unlock
384PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock
385 pthread_mutex_t *mutex)
386{
387 int ret;
388 int res;
389 OrigFn fn;
390 VALGRIND_GET_ORIG_FN(fn);
391 VALGRIND_DO_CLIENT_REQUEST(res, -1,
392 VG_USERREQ__PRE_PTHREAD_MUTEX_UNLOCK,
bart5357fcb2008-02-27 15:46:00 +0000393 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000394 CALL_FN_W_W(ret, fn, mutex);
395 return ret;
396}
397
398// pthread_cond_init
sewardj347eeba2008-01-21 14:19:07 +0000399PTH_FUNC(int, pthreadZucondZuinitZa, // pthread_cond_init*
sewardjaf44c822007-11-25 14:01:38 +0000400 pthread_cond_t* cond,
401 const pthread_condattr_t* attr)
402{
403 int ret;
404 int res;
405 OrigFn fn;
406 VALGRIND_GET_ORIG_FN(fn);
407 CALL_FN_W_WW(ret, fn, cond, attr);
408 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_INIT,
409 cond, sizeof(*cond), 0, 0, 0);
410 return ret;
411}
412
413// pthread_cond_destroy
sewardj347eeba2008-01-21 14:19:07 +0000414PTH_FUNC(int, pthreadZucondZudestroyZa, // pthread_cond_destroy*
sewardjaf44c822007-11-25 14:01:38 +0000415 pthread_cond_t* cond)
416{
417 int ret;
418 int res;
419 OrigFn fn;
420 VALGRIND_GET_ORIG_FN(fn);
421 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_DESTROY,
sewardj721ad7b2007-11-30 08:30:29 +0000422 cond, 0, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000423 CALL_FN_W_W(ret, fn, cond);
424 return ret;
425}
426
427// pthread_cond_wait
sewardj347eeba2008-01-21 14:19:07 +0000428PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait*
sewardjaf44c822007-11-25 14:01:38 +0000429 pthread_cond_t *cond,
430 pthread_mutex_t *mutex)
431{
432 int ret;
433 int res;
434 OrigFn fn;
435 VALGRIND_GET_ORIG_FN(fn);
436 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_WAIT,
bart3b1ee452008-02-29 19:28:15 +0000437 cond, sizeof(*cond), mutex, mutex_type(mutex),
438 0);
sewardjaf44c822007-11-25 14:01:38 +0000439 CALL_FN_W_WW(ret, fn, cond, mutex);
440 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_WAIT,
bart3b1ee452008-02-29 19:28:15 +0000441 cond, mutex, sizeof(*mutex), mutex_type(mutex),
442 ret == 0);
sewardjaf44c822007-11-25 14:01:38 +0000443 return ret;
444}
445
446// pthread_cond_timedwait
sewardj347eeba2008-01-21 14:19:07 +0000447PTH_FUNC(int, pthreadZucondZutimedwaitZa, // pthread_cond_timedwait*
sewardjaf44c822007-11-25 14:01:38 +0000448 pthread_cond_t *cond,
449 pthread_mutex_t *mutex,
450 const struct timespec* abstime)
451{
452 int ret;
453 int res;
454 OrigFn fn;
455 VALGRIND_GET_ORIG_FN(fn);
456 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_WAIT,
bart3b1ee452008-02-29 19:28:15 +0000457 cond, sizeof(*cond), mutex, mutex_type(mutex),
458 0);
sewardjaf44c822007-11-25 14:01:38 +0000459 CALL_FN_W_WWW(ret, fn, cond, mutex, abstime);
460 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_WAIT,
bart3b1ee452008-02-29 19:28:15 +0000461 cond, mutex, sizeof(*mutex), mutex_type(mutex),
462 ret == 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);
bart3b1ee452008-02-29 19:28:15 +0000534 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
535 spinlock, sizeof(*spinlock),
536 mutex_type_spinlock, ret == 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000537 return ret;
538}
539
540// pthread_spin_trylock
541PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock
542 pthread_spinlock_t *spinlock)
543{
544 int ret;
545 int res;
546 OrigFn fn;
547 VALGRIND_GET_ORIG_FN(fn);
548 CALL_FN_W_W(ret, fn, spinlock);
bart3b1ee452008-02-29 19:28:15 +0000549 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
550 spinlock, sizeof(*spinlock),
551 mutex_type_spinlock, ret == 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
624PTH_FUNC(int, sem_initZAGLIBCZu2Zd0, // sem_init@GLIBC_2.0
625 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
643PTH_FUNC(int, sem_initZa, // sem_init*
644 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
663PTH_FUNC(int, sem_destroyZAGLIBCZu2Zd0, // sem_destroy@GLIBC_2.0
664 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
679PTH_FUNC(int, sem_destroyZa, // sem_destroy*
680 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
696PTH_FUNC(int, sem_waitZAGLIBCZu2Zd0, // sem_wait@GLIBC_2.0
697 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
sewardj85642922008-01-14 11:54:56 +0000712PTH_FUNC(int, sem_waitZa, // sem_wait*
713 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
728PTH_FUNC(int, sem_trywaitZAGLIBCZu2Zd0, // sem_trywait@GLIBC_2.0
729 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
743PTH_FUNC(int, sem_trywaitZa, // sem_trywait*
744 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
759PTH_FUNC(int, sem_timedwait, // sem_timedwait
760 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
775PTH_FUNC(int, sem_postZAGLIBCZu2Zd0, // sem_post@GLIBC_2.0
776 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
790PTH_FUNC(int, sem_postZa, // sem_post*
791 sem_t *sem)
792{
793 int ret;
794 int res;
795 OrigFn fn;
796 VALGRIND_GET_ORIG_FN(fn);
797 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST,
798 sem, sizeof(*sem), 0, 0, 0);
799 CALL_FN_W_W(ret, fn, sem);
sewardje3b57aa2008-01-18 07:42:01 +0000800 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST,
801 sem, sizeof(*sem), ret == 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000802 return ret;
803}
804
805/*
806pthread_rwlock_destroy
807pthread_rwlock_init
808pthread_rwlock_rdlock
809pthread_rwlock_timedrdlock
810pthread_rwlock_timedwrlock
811pthread_rwlock_tryrdlock
812pthread_rwlock_trywrlock
813pthread_rwlock_unlock
814pthread_rwlock_wrlock
815pthread_rwlockattr_destroy
816pthread_rwlockattr_getkind_np
817pthread_rwlockattr_getpshared
818pthread_rwlockattr_init
819pthread_rwlockattr_setkind_np
820pthread_rwlockattr_setpshared
821 */
822
sewardjaf44c822007-11-25 14:01:38 +0000823/*
824 * Local variables:
825 * c-basic-offset: 3
826 * End:
827 */