blob: fd2ee2b3fa8ae5e9cb05e211d53f8df3da7076d1 [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>
bart0d063002008-03-01 07:25:13 +000053#include <stdlib.h>
sewardjaf44c822007-11-25 14:01:38 +000054#include <unistd.h>
sewardjaf44c822007-11-25 14:01:38 +000055#include "drd_clientreq.h"
sewardj85642922008-01-14 11:54:56 +000056#include "pub_tool_redir.h"
sewardjaf44c822007-11-25 14:01:38 +000057
58
59// Defines.
60
61#define PTH_FUNC(ret_ty, f, args...) \
62 ret_ty VG_WRAP_FUNCTION_ZZ(libpthreadZdsoZd0,f)(args); \
63 ret_ty VG_WRAP_FUNCTION_ZZ(libpthreadZdsoZd0,f)(args)
64
65
66// Local data structures.
67
68typedef struct
69{
70 void* (*start)(void*);
71 void* arg;
72 int detachstate;
73#if 0
74 pthread_mutex_t mutex;
75 pthread_cond_t cond;
76#else
77 int wrapper_started;
78#endif
79} VgPosixThreadArgs;
80
81
82// Local variables.
83
84static int vg_main_thread_state_is_set = 0;
bart0d063002008-03-01 07:25:13 +000085static pid_t vg_main_thread_pid;
sewardjaf44c822007-11-25 14:01:38 +000086
87
88// Function definitions.
89
bart5357fcb2008-02-27 15:46:00 +000090static MutexT pthread_to_drd_mutex_type(const int kind)
91{
92 switch (kind)
93 {
94 /* PTHREAD_MUTEX_RECURSIVE_NP */
95 case PTHREAD_MUTEX_RECURSIVE:
96 return mutex_type_recursive_mutex;
97 /* PTHREAD_MUTEX_ERRORCHECK_NP */
98 case PTHREAD_MUTEX_ERRORCHECK:
99 return mutex_type_errorcheck_mutex;
100 /* PTHREAD_MUTEX_TIMED_NP */
101 /* PTHREAD_MUTEX_NORMAL */
102 case PTHREAD_MUTEX_DEFAULT:
103 case PTHREAD_MUTEX_ADAPTIVE_NP:
104 return mutex_type_default_mutex;
bart5357fcb2008-02-27 15:46:00 +0000105 }
bart635cb162008-02-28 08:30:43 +0000106 return mutex_type_invalid_mutex;
bart5357fcb2008-02-27 15:46:00 +0000107}
108
109static MutexT mutex_type(pthread_mutex_t* mutex)
110{
bartc9463c42008-02-28 07:36:04 +0000111#if defined(_PTHREAD_DESCR_DEFINED)
112 // Linuxthreads.
113 const int kind = mutex->__m_kind;
114#elif defined(__SIZEOF_PTHREAD_MUTEX_T)
115 // NPTL.
116 const int kind = mutex->__data.__kind;
117#else
118 // Another POSIX threads implementation. Regression tests will fail.
119 const int kind = PTHREAD_MUTEX_DEFAULT;
120#endif
121 return pthread_to_drd_mutex_type(kind);
bart5357fcb2008-02-27 15:46:00 +0000122}
123
sewardjaf44c822007-11-25 14:01:38 +0000124static void vg_start_suppression(const void* const p, size_t const size)
125{
126 int res;
127 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_SUPPRESSION,
128 p, size, 0, 0, 0);
129}
130
131#if 0
132static void vg_finish_suppression(const void* const p, size_t const size)
133{
134 int res;
135 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_FINISH_SUPPRESSION,
136 p, size, 0, 0, 0);
137}
138#endif
139
140static void vg_start_recording(void)
141{
142 int res;
143 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_RECORDING,
144 pthread_self(), 0, 0, 0, 0);
145}
146
147static void vg_stop_recording(void)
148{
149 int res;
150 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_STOP_RECORDING,
151 pthread_self(), 0, 0, 0, 0);
152}
153
154static void vg_set_joinable(const pthread_t tid, const int joinable)
155{
156 int res;
157 assert(joinable == 0 || joinable == 1);
sewardjaf44c822007-11-25 14:01:38 +0000158 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__SET_JOINABLE,
159 tid, joinable, 0, 0, 0);
160}
161
162static void* vg_thread_wrapper(void* arg)
163{
164 int res;
bart0d063002008-03-01 07:25:13 +0000165
166 if (getpid() != vg_main_thread_pid)
167 {
168 fprintf(stderr,
169 "Detected the linuxthreads threading library.\n"
170 "Sorry, but DRD does not support linuxthreads.\n"
171 "Please try to run DRD on a system with NPTL instead.\n"
172 "Giving up.\n");
173 abort();
174 }
175
sewardjaf44c822007-11-25 14:01:38 +0000176 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK,
177 0, 0, 0, 0, 0);
178
179 {
180 VgPosixThreadArgs* const arg_ptr = (VgPosixThreadArgs*)arg;
181 VgPosixThreadArgs const arg_copy = *arg_ptr;
182 void* result;
183
184#if 0
185 pthread_mutex_lock(arg_ptr->mutex);
186 pthread_cond_signal(arg_ptr->cond);
187 pthread_mutex_unlock(arg_ptr->mutex);
188#else
189 arg_ptr->wrapper_started = 1;
190#endif
191
192 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
193 pthread_self(), 0, 0, 0, 0);
194 vg_set_joinable(pthread_self(),
195 arg_copy.detachstate == PTHREAD_CREATE_JOINABLE);
196 result = (arg_copy.start)(arg_copy.arg);
197 return result;
198 }
199}
200
201static void vg_set_main_thread_state(void)
202{
203 int res;
204
bart0d063002008-03-01 07:25:13 +0000205 vg_main_thread_pid = getpid();
206
sewardjaf44c822007-11-25 14:01:38 +0000207 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK,
208 0, 0, 0, 0, 0);
209
sewardjaf44c822007-11-25 14:01:38 +0000210 // Make sure that DRD knows about the main thread's POSIX thread ID.
211 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
212 pthread_self(), 0, 0, 0, 0);
213
214}
215
216// pthread_create
sewardj347eeba2008-01-21 14:19:07 +0000217PTH_FUNC(int, pthreadZucreateZa, // pthread_create*
sewardjaf44c822007-11-25 14:01:38 +0000218 pthread_t *thread, const pthread_attr_t *attr,
219 void *(*start) (void *), void *arg)
220{
221 int ret;
222 OrigFn fn;
223 VgPosixThreadArgs vgargs;
224
225 VALGRIND_GET_ORIG_FN(fn);
226
227 if (vg_main_thread_state_is_set == 0)
228 {
229 vg_set_main_thread_state();
230 vg_main_thread_state_is_set = 1;
231 }
232 vg_start_suppression(&vgargs.wrapper_started,
233 sizeof(vgargs.wrapper_started));
234 vgargs.start = start;
235 vgargs.arg = arg;
236 vgargs.wrapper_started = 0;
237 vgargs.detachstate = PTHREAD_CREATE_JOINABLE;
238 if (attr)
239 {
240 if (pthread_attr_getdetachstate(attr, &vgargs.detachstate) != 0)
241 {
242 assert(0);
243 }
sewardjaf44c822007-11-25 14:01:38 +0000244 }
245 assert(vgargs.detachstate == PTHREAD_CREATE_JOINABLE
246 || vgargs.detachstate == PTHREAD_CREATE_DETACHED);
247#if 0
248 pthread_mutex_init(&vgargs.mutex, 0);
249 pthread_cond_init(&vgargs.cond, 0);
250 pthread_mutex_lock(&vgargs.mutex);
251#endif
252 vg_stop_recording();
253 CALL_FN_W_WWWW(ret, fn, thread, attr, vg_thread_wrapper, &vgargs);
254 vg_start_recording();
255#if 0
256 pthread_cond_wait(&vgargs.cond, &vgargs.mutex);
257 pthread_mutex_unlock(&vgargs.mutex);
258 pthread_cond_destroy(&vgargs.cond);
259 pthread_mutex_destroy(&vgargs.mutex);
260#else
261 // Yes, you see it correctly, busy waiting ... The problem is that
262 // POSIX threads functions cannot be called here -- the functions defined
sewardj85642922008-01-14 11:54:56 +0000263 // in this file (drd_intercepts.c) would be called instead of those in
sewardjaf44c822007-11-25 14:01:38 +0000264 // libpthread.so. This loop is necessary because vgargs is allocated on the
265 // stack, and the created thread reads it.
sewardje0744f02007-12-01 02:09:50 +0000266 if (ret == 0)
sewardjaf44c822007-11-25 14:01:38 +0000267 {
sewardje0744f02007-12-01 02:09:50 +0000268 while (! vgargs.wrapper_started)
269 {
270 sched_yield();
271 }
sewardjaf44c822007-11-25 14:01:38 +0000272 }
273#endif
274 return ret;
275}
276
277// pthread_join
278PTH_FUNC(int, pthreadZujoin, // pthread_join
279 pthread_t pt_joinee, void **thread_return)
280{
281 int ret;
282 int res;
283 OrigFn fn;
284
285 VALGRIND_GET_ORIG_FN(fn);
286 CALL_FN_W_WW(ret, fn, pt_joinee, thread_return);
287 if (ret == 0)
288 {
289 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_JOIN,
290 pt_joinee, 0, 0, 0, 0);
291 }
292 return ret;
293}
294
295// pthread_detach
296PTH_FUNC(int, pthreadZudetach, pthread_t pt_thread)
297{
298 int ret;
299 OrigFn fn;
300 VALGRIND_GET_ORIG_FN(fn);
301 {
302 CALL_FN_W_W(ret, fn, pt_thread);
303 if (ret == 0)
304 {
305 vg_set_joinable(pt_thread, 0);
306 }
307 }
308 return ret;
309}
310
311// pthread_mutex_init
312PTH_FUNC(int, pthreadZumutexZuinit,
313 pthread_mutex_t *mutex,
314 const pthread_mutexattr_t* attr)
315{
316 int ret;
317 int res;
318 OrigFn fn;
bart5357fcb2008-02-27 15:46:00 +0000319 int mt = PTHREAD_MUTEX_DEFAULT;
sewardjaf44c822007-11-25 14:01:38 +0000320 VALGRIND_GET_ORIG_FN(fn);
bart5357fcb2008-02-27 15:46:00 +0000321 if (attr)
322 pthread_mutexattr_gettype(attr, &mt);
sewardjaf44c822007-11-25 14:01:38 +0000323 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT,
bart5357fcb2008-02-27 15:46:00 +0000324 mutex, sizeof(*mutex),
325 pthread_to_drd_mutex_type(mt), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000326 CALL_FN_W_WW(ret, fn, mutex, attr);
327 return ret;
328}
329
330// pthread_mutex_destroy
331PTH_FUNC(int, pthreadZumutexZudestroy,
332 pthread_mutex_t *mutex)
333{
334 int ret;
335 int res;
336 OrigFn fn;
337 VALGRIND_GET_ORIG_FN(fn);
338 CALL_FN_W_W(ret, fn, mutex);
339 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
bart5357fcb2008-02-27 15:46:00 +0000340 mutex, mutex_type(mutex), 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000341 return ret;
342}
343
344// pthread_mutex_lock
345PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock
346 pthread_mutex_t *mutex)
347{
348 int ret;
349 int res;
350 OrigFn fn;
351 VALGRIND_GET_ORIG_FN(fn);
352 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK,
bart5357fcb2008-02-27 15:46:00 +0000353 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000354#if 1
355 // The only purpose of the system call below is to make drd work on AMD64
356 // systems. Without this system call, clients crash (SIGSEGV) in
357 // std::locale::locale().
358 write(1, "", 0);
359#endif
360 CALL_FN_W_W(ret, fn, mutex);
bart3b1ee452008-02-29 19:28:15 +0000361 VALGRIND_DO_CLIENT_REQUEST(res, 0, 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
367// pthread_mutex_trylock
368PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock
369 pthread_mutex_t *mutex)
370{
371 int ret;
372 int res;
373 OrigFn fn;
374 VALGRIND_GET_ORIG_FN(fn);
375 CALL_FN_W_W(ret, fn, mutex);
bart3b1ee452008-02-29 19:28:15 +0000376 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
377 mutex, sizeof(*mutex), mutex_type(mutex),
378 ret == 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000379 return ret;
380}
381
sewardj85642922008-01-14 11:54:56 +0000382// pthread_mutex_timedlock
383PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock
384 pthread_mutex_t *mutex,
385 const struct timespec *abs_timeout)
386{
387 int ret;
388 int res;
389 OrigFn fn;
390 VALGRIND_GET_ORIG_FN(fn);
391 CALL_FN_W_WW(ret, fn, mutex, abs_timeout);
bart3b1ee452008-02-29 19:28:15 +0000392 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
393 mutex, sizeof(*mutex), mutex_type(mutex),
394 ret == 0, 0);
sewardj85642922008-01-14 11:54:56 +0000395 return ret;
396}
397
sewardjaf44c822007-11-25 14:01:38 +0000398// pthread_mutex_unlock
399PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock
400 pthread_mutex_t *mutex)
401{
402 int ret;
403 int res;
404 OrigFn fn;
405 VALGRIND_GET_ORIG_FN(fn);
406 VALGRIND_DO_CLIENT_REQUEST(res, -1,
407 VG_USERREQ__PRE_PTHREAD_MUTEX_UNLOCK,
bart5357fcb2008-02-27 15:46:00 +0000408 mutex, sizeof(*mutex), mutex_type(mutex), 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000409 CALL_FN_W_W(ret, fn, mutex);
410 return ret;
411}
412
413// pthread_cond_init
sewardj347eeba2008-01-21 14:19:07 +0000414PTH_FUNC(int, pthreadZucondZuinitZa, // pthread_cond_init*
sewardjaf44c822007-11-25 14:01:38 +0000415 pthread_cond_t* cond,
416 const pthread_condattr_t* attr)
417{
418 int ret;
419 int res;
420 OrigFn fn;
421 VALGRIND_GET_ORIG_FN(fn);
422 CALL_FN_W_WW(ret, fn, cond, attr);
423 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_INIT,
424 cond, sizeof(*cond), 0, 0, 0);
425 return ret;
426}
427
428// pthread_cond_destroy
sewardj347eeba2008-01-21 14:19:07 +0000429PTH_FUNC(int, pthreadZucondZudestroyZa, // pthread_cond_destroy*
sewardjaf44c822007-11-25 14:01:38 +0000430 pthread_cond_t* cond)
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_DESTROY,
sewardj721ad7b2007-11-30 08:30:29 +0000437 cond, 0, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000438 CALL_FN_W_W(ret, fn, cond);
439 return ret;
440}
441
442// pthread_cond_wait
sewardj347eeba2008-01-21 14:19:07 +0000443PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait*
sewardjaf44c822007-11-25 14:01:38 +0000444 pthread_cond_t *cond,
445 pthread_mutex_t *mutex)
446{
447 int ret;
448 int res;
449 OrigFn fn;
450 VALGRIND_GET_ORIG_FN(fn);
451 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_WAIT,
bart3b1ee452008-02-29 19:28:15 +0000452 cond, sizeof(*cond), mutex, mutex_type(mutex),
453 0);
sewardjaf44c822007-11-25 14:01:38 +0000454 CALL_FN_W_WW(ret, fn, cond, mutex);
455 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_WAIT,
bart3b1ee452008-02-29 19:28:15 +0000456 cond, mutex, sizeof(*mutex), mutex_type(mutex),
457 ret == 0);
sewardjaf44c822007-11-25 14:01:38 +0000458 return ret;
459}
460
461// pthread_cond_timedwait
sewardj347eeba2008-01-21 14:19:07 +0000462PTH_FUNC(int, pthreadZucondZutimedwaitZa, // pthread_cond_timedwait*
sewardjaf44c822007-11-25 14:01:38 +0000463 pthread_cond_t *cond,
464 pthread_mutex_t *mutex,
465 const struct timespec* abstime)
466{
467 int ret;
468 int res;
469 OrigFn fn;
470 VALGRIND_GET_ORIG_FN(fn);
471 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_WAIT,
bart3b1ee452008-02-29 19:28:15 +0000472 cond, sizeof(*cond), mutex, mutex_type(mutex),
473 0);
sewardjaf44c822007-11-25 14:01:38 +0000474 CALL_FN_W_WWW(ret, fn, cond, mutex, abstime);
475 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_WAIT,
bart3b1ee452008-02-29 19:28:15 +0000476 cond, mutex, sizeof(*mutex), mutex_type(mutex),
477 ret == 0);
sewardjaf44c822007-11-25 14:01:38 +0000478 return ret;
479}
480
481// pthread_cond_signal
sewardj347eeba2008-01-21 14:19:07 +0000482PTH_FUNC(int, pthreadZucondZusignalZa, // pthread_cond_signal*
sewardjaf44c822007-11-25 14:01:38 +0000483 pthread_cond_t* cond)
484{
485 int ret;
486 int res;
487 OrigFn fn;
488 VALGRIND_GET_ORIG_FN(fn);
489 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_SIGNAL,
490 cond, 0, 0, 0, 0);
491 CALL_FN_W_W(ret, fn, cond);
492 return ret;
493}
494
495// pthread_cond_broadcast
sewardj347eeba2008-01-21 14:19:07 +0000496PTH_FUNC(int, pthreadZucondZubroadcastZa, // pthread_cond_broadcast*
sewardjaf44c822007-11-25 14:01:38 +0000497 pthread_cond_t* cond)
498{
499 int ret;
500 int res;
501 OrigFn fn;
502 VALGRIND_GET_ORIG_FN(fn);
503 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_BROADCAST,
504 cond, 0, 0, 0, 0);
505 CALL_FN_W_W(ret, fn, cond);
506 return ret;
507}
508
509
510// pthread_spin_init
511PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init
512 pthread_spinlock_t *spinlock,
513 int pshared)
514{
515 int ret;
516 int res;
517 OrigFn fn;
518 VALGRIND_GET_ORIG_FN(fn);
519 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SPIN_INIT_OR_UNLOCK,
sewardj721ad7b2007-11-30 08:30:29 +0000520 spinlock, sizeof(*spinlock),
521 mutex_type_spinlock, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000522 CALL_FN_W_WW(ret, fn, spinlock, pshared);
523 return ret;
524}
525
526// pthread_spin_destroy
527PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy
528 pthread_spinlock_t *spinlock)
529{
530 int ret;
531 int res;
532 OrigFn fn;
533 VALGRIND_GET_ORIG_FN(fn);
534 CALL_FN_W_W(ret, fn, spinlock);
535 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
sewardj721ad7b2007-11-30 08:30:29 +0000536 spinlock, mutex_type_spinlock, 0, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000537 return ret;
538}
539
540// pthread_spin_lock
541PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock
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_trylock
556PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock
557 pthread_spinlock_t *spinlock)
558{
559 int ret;
560 int res;
561 OrigFn fn;
562 VALGRIND_GET_ORIG_FN(fn);
563 CALL_FN_W_W(ret, fn, spinlock);
bart3b1ee452008-02-29 19:28:15 +0000564 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK,
565 spinlock, sizeof(*spinlock),
566 mutex_type_spinlock, ret == 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000567 return ret;
568}
569
570// pthread_spin_unlock
571PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock
572 pthread_spinlock_t *spinlock)
573{
574 int ret;
575 int res;
576 OrigFn fn;
577 VALGRIND_GET_ORIG_FN(fn);
578 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SPIN_INIT_OR_UNLOCK,
sewardj721ad7b2007-11-30 08:30:29 +0000579 spinlock, sizeof(*spinlock),
580 mutex_type_spinlock, 0, 0);
sewardjaf44c822007-11-25 14:01:38 +0000581 CALL_FN_W_W(ret, fn, spinlock);
582 return ret;
583}
584
sewardj85642922008-01-14 11:54:56 +0000585// pthread_barrier_init
586PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init
587 pthread_barrier_t* barrier,
588 const pthread_barrierattr_t* attr,
589 unsigned count)
590{
591 int ret;
592 int res;
593 OrigFn fn;
594 VALGRIND_GET_ORIG_FN(fn);
595 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__BARRIER_INIT,
596 barrier, sizeof(*barrier),
597 count, 0, 0);
598 CALL_FN_W_WWW(ret, fn, barrier, attr, count);
599 return ret;
600}
601
602// pthread_barrier_destroy
603PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy
604 pthread_barrier_t* barrier)
605{
606 int ret;
607 int res;
608 OrigFn fn;
609 VALGRIND_GET_ORIG_FN(fn);
610 CALL_FN_W_W(ret, fn, barrier);
611 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__BARRIER_DESTROY,
612 barrier, 0, 0, 0, 0);
613 return ret;
614}
615
616// pthread_barrier_wait
617PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait
618 pthread_barrier_t* barrier)
619{
620 int ret;
621 int res;
622 OrigFn fn;
623 VALGRIND_GET_ORIG_FN(fn);
624 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT,
625 barrier, 0, 0, 0, 0);
626 CALL_FN_W_W(ret, fn, barrier);
627 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT,
628 barrier,
629 ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD,
630 0, 0, 0);
631 return ret;
632}
633
634
635// From glibc 2.0 linuxthreads/sysdeps/pthread/cmpxchg/semaphorebits.h
636typedef struct { long int sem_status; } sem_t_glibc_2_0;
637
638// sem_init
639PTH_FUNC(int, sem_initZAGLIBCZu2Zd0, // sem_init@GLIBC_2.0
640 sem_t_glibc_2_0 *sem,
641 int pshared,
642 unsigned int value)
643{
644 int ret;
645 int res;
646 OrigFn fn;
647 VALGRIND_GET_ORIG_FN(fn);
648 CALL_FN_W_WWW(ret, fn, sem, pshared, value);
649 if (ret == 0)
650 {
651 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_INIT,
652 sem, sizeof(*sem),
653 pshared, value, 0);
654 }
655 return ret;
656}
657
658PTH_FUNC(int, sem_initZa, // sem_init*
659 sem_t *sem,
660 int pshared,
661 unsigned int value)
662{
663 int ret;
664 int res;
665 OrigFn fn;
666 VALGRIND_GET_ORIG_FN(fn);
667 CALL_FN_W_WWW(ret, fn, sem, pshared, value);
668 if (ret == 0)
669 {
670 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_INIT,
671 sem, sizeof(*sem),
672 pshared, value, 0);
673 }
674 return ret;
675}
676
677// sem_destroy
678PTH_FUNC(int, sem_destroyZAGLIBCZu2Zd0, // sem_destroy@GLIBC_2.0
679 sem_t_glibc_2_0 *sem)
680{
681 int ret;
682 int res;
683 OrigFn fn;
684 VALGRIND_GET_ORIG_FN(fn);
685 CALL_FN_W_W(ret, fn, sem);
686 if (ret == 0)
687 {
688 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_DESTROY,
689 sem, 0, 0, 0, 0);
690 }
691 return ret;
692}
693
694PTH_FUNC(int, sem_destroyZa, // sem_destroy*
695 sem_t *sem)
696{
697 int ret;
698 int res;
699 OrigFn fn;
700 VALGRIND_GET_ORIG_FN(fn);
701 CALL_FN_W_W(ret, fn, sem);
702 if (ret == 0)
703 {
704 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SEM_DESTROY,
705 sem, 0, 0, 0, 0);
706 }
707 return ret;
708}
709
710// sem_wait
711PTH_FUNC(int, sem_waitZAGLIBCZu2Zd0, // sem_wait@GLIBC_2.0
712 sem_t_glibc_2_0 *sem)
713{
714 int ret;
715 int res;
716 OrigFn fn;
717 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000718 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
719 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000720 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000721 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
722 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000723 return ret;
724}
725
bart28230a32008-02-29 17:27:03 +0000726// sem_wait
sewardj85642922008-01-14 11:54:56 +0000727PTH_FUNC(int, sem_waitZa, // sem_wait*
728 sem_t *sem)
729{
730 int ret;
731 int res;
732 OrigFn fn;
733 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000734 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
735 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000736 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000737 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
738 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000739 return ret;
740}
741
742// sem_trywait
743PTH_FUNC(int, sem_trywaitZAGLIBCZu2Zd0, // sem_trywait@GLIBC_2.0
744 sem_t_glibc_2_0 *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
758PTH_FUNC(int, sem_trywaitZa, // sem_trywait*
759 sem_t *sem)
760{
761 int ret;
762 int res;
763 OrigFn fn;
764 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000765 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
766 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000767 CALL_FN_W_W(ret, fn, sem);
bart28230a32008-02-29 17:27:03 +0000768 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
769 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000770 return ret;
771}
772
773// sem_timedwait
774PTH_FUNC(int, sem_timedwait, // sem_timedwait
775 sem_t *sem, const struct timespec *abs_timeout)
776{
777 int ret;
778 int res;
779 OrigFn fn;
780 VALGRIND_GET_ORIG_FN(fn);
bart28230a32008-02-29 17:27:03 +0000781 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
782 sem, 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000783 CALL_FN_W_WW(ret, fn, sem, abs_timeout);
bart28230a32008-02-29 17:27:03 +0000784 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
785 sem, ret == 0, 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000786 return ret;
787}
788
789// sem_post
790PTH_FUNC(int, sem_postZAGLIBCZu2Zd0, // sem_post@GLIBC_2.0
791 sem_t_glibc_2_0 *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);
sewardjc0be9252008-02-11 11:00:51 +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
805PTH_FUNC(int, sem_postZa, // sem_post*
806 sem_t *sem)
807{
808 int ret;
809 int res;
810 OrigFn fn;
811 VALGRIND_GET_ORIG_FN(fn);
812 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST,
813 sem, sizeof(*sem), 0, 0, 0);
814 CALL_FN_W_W(ret, fn, sem);
sewardje3b57aa2008-01-18 07:42:01 +0000815 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST,
816 sem, sizeof(*sem), ret == 0, 0, 0);
sewardj85642922008-01-14 11:54:56 +0000817 return ret;
818}
819
820/*
821pthread_rwlock_destroy
822pthread_rwlock_init
823pthread_rwlock_rdlock
824pthread_rwlock_timedrdlock
825pthread_rwlock_timedwrlock
826pthread_rwlock_tryrdlock
827pthread_rwlock_trywrlock
828pthread_rwlock_unlock
829pthread_rwlock_wrlock
830pthread_rwlockattr_destroy
831pthread_rwlockattr_getkind_np
832pthread_rwlockattr_getpshared
833pthread_rwlockattr_init
834pthread_rwlockattr_setkind_np
835pthread_rwlockattr_setpshared
836 */
837
sewardjaf44c822007-11-25 14:01:38 +0000838/*
839 * Local variables:
840 * c-basic-offset: 3
841 * End:
842 */