drd_pthread_intercepts.c revision ccf17de11cac09dc387e6cb115fdee0ae6e29e70
1
2/*--------------------------------------------------------------------*/
3/*--- Client-space code for drd.                  drd_intercepts.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7  This file is part of drd, a data race detector.
8
9  Copyright (C) 2006-2008 Bart Van Assche
10  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 when compiling with older glibc
44// versions (2.3 or before).
45#ifndef _GNU_SOURCE
46#define _GNU_SOURCE
47#endif
48
49#include <assert.h>
50#include <inttypes.h>       // uintptr_t
51#include <pthread.h>
52#include <semaphore.h>
53#include <stdio.h>
54#include <stdlib.h>
55#include <unistd.h>         // confstr()
56#include "config.h"
57#include "drd_clientreq.h"
58#include "pub_tool_redir.h"
59
60
61// Defines.
62
63#define PTH_FUNC(ret_ty, f, args...)                            \
64  ret_ty VG_WRAP_FUNCTION_ZZ(libpthreadZdsoZd0,f)(args);        \
65  ret_ty VG_WRAP_FUNCTION_ZZ(libpthreadZdsoZd0,f)(args)
66
67
68/* Local data structures. */
69
70typedef struct
71{
72  void* (*start)(void*);
73  void* arg;
74  int   detachstate;
75#if 0
76  pthread_mutex_t mutex;
77  pthread_cond_t  cond;
78#else
79  int wrapper_started;
80#endif
81} VgPosixThreadArgs;
82
83
84/* Function declarations. */
85
86static void init(void) __attribute__((constructor));
87static void check_threading_library(void);
88static void vg_set_main_thread_state(void);
89
90
91/* Function definitions. */
92
93/** Shared library initialization function: the _init() function is called
94 *  after dlopen() has loaded the shared library. This function must not
95 *  be declared static.
96 */
97static void init(void)
98{
99  check_threading_library();
100  vg_set_main_thread_state();
101  /* glibc up to and including version 2.7 triggers conflicting accesses   */
102  /* on stdout and stderr when sending output to one of these streams from */
103  /* more than one thread. Suppress data race reports on these objects.    */
104  DRD_IGNORE_VAR(*stdout);
105  DRD_IGNORE_VAR(*stderr);
106}
107
108static MutexT pthread_to_drd_mutex_type(const int kind)
109{
110  switch (kind)
111  {
112    /* PTHREAD_MUTEX_RECURSIVE_NP */
113  case PTHREAD_MUTEX_RECURSIVE:
114    return mutex_type_recursive_mutex;
115    /* PTHREAD_MUTEX_ERRORCHECK_NP */
116  case PTHREAD_MUTEX_ERRORCHECK:
117    return mutex_type_errorcheck_mutex;
118    /* PTHREAD_MUTEX_TIMED_NP */
119    /* PTHREAD_MUTEX_NORMAL */
120  case PTHREAD_MUTEX_DEFAULT:
121#if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP)
122  case PTHREAD_MUTEX_ADAPTIVE_NP:
123#endif
124    return mutex_type_default_mutex;
125  }
126  return mutex_type_invalid_mutex;
127}
128
129static MutexT mutex_type(pthread_mutex_t* mutex)
130{
131#if defined(HAVE_PTHREAD_MUTEX_T__M_KIND)
132  /* LinuxThreads. */
133  const int kind = mutex->__m_kind;
134#elif defined(HAVE_PTHREAD_MUTEX_T__DATA__KIND)
135  /* NPTL. */
136  const int kind = mutex->__data.__kind;
137#else
138  /* Another POSIX threads implementation. Regression tests will fail. */
139  const int kind = PTHREAD_MUTEX_DEFAULT;
140  fprintf(stderr,
141          "Did not recognize your POSIX threads implementation. Giving up.\n");
142  assert(0);
143#endif
144  return pthread_to_drd_mutex_type(kind);
145}
146
147static void vg_start_suppression(const void* const p, size_t const size)
148{
149  int res;
150  VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_START_SUPPRESSION,
151                             p, size, 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);
158  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;
165
166  VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK,
167                             0, 0, 0, 0, 0);
168
169  {
170    VgPosixThreadArgs* const arg_ptr = (VgPosixThreadArgs*)arg;
171    VgPosixThreadArgs const arg_copy = *arg_ptr;
172    void* result;
173
174#if 0
175    pthread_mutex_lock(arg_ptr->mutex);
176    pthread_cond_signal(arg_ptr->cond);
177    pthread_mutex_unlock(arg_ptr->mutex);
178#else
179    arg_ptr->wrapper_started = 1;
180#endif
181
182    VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
183                               pthread_self(), 0, 0, 0, 0);
184    vg_set_joinable(pthread_self(),
185                    arg_copy.detachstate == PTHREAD_CREATE_JOINABLE);
186    result = (arg_copy.start)(arg_copy.arg);
187    return result;
188  }
189}
190
191/** Return 1 if LinuxThread has been detected, and 0 otherwise. */
192static int detected_linuxthreads(void)
193{
194#if defined(linux)
195#if defined(_CS_GNU_LIBPTHREAD_VERSION)
196  /* Linux with a recent glibc. */
197  char buffer[256];
198  unsigned len;
199  len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
200  assert(len <= sizeof(buffer));
201  return len > 0 && buffer[0] == 'l';
202#else
203  /* Linux without _CS_GNU_LIBPTHREAD_VERSION: most likely LinuxThreads. */
204  return 1;
205#endif
206#else
207  /* Another OS than Linux, hence no LinuxThreads. */
208  return 0;
209#endif
210}
211
212/** Stop and print an error message in case a non-supported threading
213 *  library (LinuxThreads) has been detected.
214 */
215static void check_threading_library(void)
216{
217  if (detected_linuxthreads())
218  {
219    if (getenv("LD_ASSUME_KERNEL"))
220    {
221      fprintf(stderr,
222              "Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
223              "the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
224              "after having unset the environment variable LD_ASSUME_KERNEL. Giving up.\n"
225              );
226    }
227    else
228    {
229      fprintf(stderr,
230              "Detected the LinuxThreads threading library. Sorry, but DRD only supports\n"
231              "the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n"
232              "after having upgraded to a newer version of your Linux distribution.\n"
233              "Giving up.\n"
234              );
235    }
236    abort();
237  }
238}
239
240static void vg_set_main_thread_state(void)
241{
242  int res;
243
244  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK,
245                             0, 0, 0, 0, 0);
246
247  // Make sure that DRD knows about the main thread's POSIX thread ID.
248  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID,
249                             pthread_self(), 0, 0, 0, 0);
250
251}
252
253// pthread_create
254PTH_FUNC(int, pthreadZucreateZa, // pthread_create*
255         pthread_t *thread, const pthread_attr_t *attr,
256         void *(*start) (void *), void *arg)
257{
258  int    res;
259  int    ret;
260  OrigFn fn;
261  VgPosixThreadArgs vgargs;
262
263  VALGRIND_GET_ORIG_FN(fn);
264
265  vg_start_suppression(&vgargs.wrapper_started,
266                       sizeof(vgargs.wrapper_started));
267  vgargs.start = start;
268  vgargs.arg   = arg;
269  vgargs.wrapper_started = 0;
270  vgargs.detachstate = PTHREAD_CREATE_JOINABLE;
271  if (attr)
272  {
273    if (pthread_attr_getdetachstate(attr, &vgargs.detachstate) != 0)
274    {
275      assert(0);
276    }
277  }
278  assert(vgargs.detachstate == PTHREAD_CREATE_JOINABLE
279         || vgargs.detachstate == PTHREAD_CREATE_DETACHED);
280#if 0
281  pthread_mutex_init(&vgargs.mutex, 0);
282  pthread_cond_init(&vgargs.cond, 0);
283  pthread_mutex_lock(&vgargs.mutex);
284#endif
285  /* Suppress NPTL-specific conflicts between creator and created thread. */
286  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_STOP_RECORDING,
287                             0, 0, 0, 0, 0);
288  CALL_FN_W_WWWW(ret, fn, thread, attr, vg_thread_wrapper, &vgargs);
289  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_START_RECORDING,
290                             0, 0, 0, 0, 0);
291#if 0
292  pthread_cond_wait(&vgargs.cond, &vgargs.mutex);
293  pthread_mutex_unlock(&vgargs.mutex);
294  pthread_cond_destroy(&vgargs.cond);
295  pthread_mutex_destroy(&vgargs.mutex);
296#else
297  // Yes, you see it correctly, busy waiting ... The problem is that
298  // POSIX threads functions cannot be called here -- the functions defined
299  // in this file (drd_intercepts.c) would be called instead of those in
300  // libpthread.so. This loop is necessary because vgargs is allocated on the
301  // stack, and the created thread reads it.
302  if (ret == 0)
303  {
304    while (! vgargs.wrapper_started)
305    {
306      sched_yield();
307    }
308  }
309#endif
310  return ret;
311}
312
313// pthread_join
314PTH_FUNC(int, pthreadZujoin, // pthread_join
315         pthread_t pt_joinee, void **thread_return)
316{
317  int      ret;
318  int      res;
319  OrigFn   fn;
320
321  VALGRIND_GET_ORIG_FN(fn);
322  CALL_FN_W_WW(ret, fn, pt_joinee, thread_return);
323  if (ret == 0)
324  {
325    VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_JOIN,
326                               pt_joinee, 0, 0, 0, 0);
327  }
328  return ret;
329}
330
331// pthread_detach
332PTH_FUNC(int, pthreadZudetach, pthread_t pt_thread)
333{
334  int ret;
335  OrigFn fn;
336  VALGRIND_GET_ORIG_FN(fn);
337  {
338    CALL_FN_W_W(ret, fn, pt_thread);
339    if (ret == 0)
340    {
341      vg_set_joinable(pt_thread, 0);
342    }
343  }
344  return ret;
345}
346
347// pthread_mutex_init
348PTH_FUNC(int, pthreadZumutexZuinit,
349         pthread_mutex_t *mutex,
350         const pthread_mutexattr_t* attr)
351{
352  int ret;
353  int res;
354  OrigFn fn;
355  int mt;
356  VALGRIND_GET_ORIG_FN(fn);
357  mt = PTHREAD_MUTEX_DEFAULT;
358  if (attr)
359    pthread_mutexattr_gettype(attr, &mt);
360  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT,
361                             mutex, pthread_to_drd_mutex_type(mt), 0, 0, 0);
362  CALL_FN_W_WW(ret, fn, mutex, attr);
363  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT,
364                             mutex, 0, 0, 0, 0);
365  return ret;
366}
367
368// pthread_mutex_destroy
369PTH_FUNC(int, pthreadZumutexZudestroy,
370         pthread_mutex_t *mutex)
371{
372  int ret;
373  int res;
374  OrigFn fn;
375  VALGRIND_GET_ORIG_FN(fn);
376  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY,
377                             mutex, 0, 0, 0, 0);
378  CALL_FN_W_W(ret, fn, mutex);
379  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
380                             mutex, mutex_type(mutex), 0, 0, 0);
381  return ret;
382}
383
384// pthread_mutex_lock
385PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock
386         pthread_mutex_t *mutex)
387{
388  int   ret;
389  int   res;
390  OrigFn fn;
391  VALGRIND_GET_ORIG_FN(fn);
392  VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
393                             mutex, mutex_type(mutex), 0, 0, 0);
394  CALL_FN_W_W(ret, fn, mutex);
395  VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_MUTEX_LOCK,
396                             mutex, ret == 0, 0, 0, 0);
397  return ret;
398}
399
400// pthread_mutex_trylock
401PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock
402         pthread_mutex_t *mutex)
403{
404  int   ret;
405  int   res;
406  OrigFn fn;
407  VALGRIND_GET_ORIG_FN(fn);
408  VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
409                             mutex, mutex_type(mutex), 1, 0, 0);
410  CALL_FN_W_W(ret, fn, mutex);
411  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK,
412                             mutex, ret == 0, 0, 0, 0);
413  return ret;
414}
415
416// pthread_mutex_timedlock
417PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock
418         pthread_mutex_t *mutex,
419         const struct timespec *abs_timeout)
420{
421  int   ret;
422  int   res;
423  OrigFn fn;
424  VALGRIND_GET_ORIG_FN(fn);
425  VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
426                             mutex, mutex_type(mutex), 0, 0, 0);
427  CALL_FN_W_WW(ret, fn, mutex, abs_timeout);
428  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK,
429                             mutex, ret == 0, 0, 0, 0);
430  return ret;
431}
432
433// pthread_mutex_unlock
434PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock
435         pthread_mutex_t *mutex)
436{
437  int ret;
438  int   res;
439  OrigFn fn;
440  VALGRIND_GET_ORIG_FN(fn);
441  VALGRIND_DO_CLIENT_REQUEST(res, -1,
442                             VG_USERREQ__PRE_MUTEX_UNLOCK,
443                             mutex, mutex_type(mutex), 0, 0, 0);
444  CALL_FN_W_W(ret, fn, mutex);
445  VALGRIND_DO_CLIENT_REQUEST(res, -1,
446                             VG_USERREQ__POST_MUTEX_UNLOCK,
447                             mutex, 0, 0, 0, 0);
448  return ret;
449}
450
451// pthread_cond_init
452PTH_FUNC(int, pthreadZucondZuinitZa, // pthread_cond_init*
453         pthread_cond_t* cond,
454         const pthread_condattr_t* attr)
455{
456  int ret;
457  int res;
458  OrigFn fn;
459  VALGRIND_GET_ORIG_FN(fn);
460  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_INIT,
461                             cond, 0, 0, 0, 0);
462  CALL_FN_W_WW(ret, fn, cond, attr);
463  return ret;
464}
465
466// pthread_cond_destroy
467PTH_FUNC(int, pthreadZucondZudestroyZa, // pthread_cond_destroy*
468         pthread_cond_t* cond)
469{
470  int ret;
471  int res;
472  OrigFn fn;
473  VALGRIND_GET_ORIG_FN(fn);
474  CALL_FN_W_W(ret, fn, cond);
475  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_DESTROY,
476                             cond, 0, 0, 0, 0);
477  return ret;
478}
479
480// pthread_cond_wait
481PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait*
482         pthread_cond_t *cond,
483         pthread_mutex_t *mutex)
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_COND_WAIT,
490                             cond, mutex, mutex_type(mutex), 0, 0);
491  CALL_FN_W_WW(ret, fn, cond, mutex);
492  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT,
493                             cond, mutex, 1, 0, 0);
494  return ret;
495}
496
497// pthread_cond_timedwait
498PTH_FUNC(int, pthreadZucondZutimedwaitZa, // pthread_cond_timedwait*
499         pthread_cond_t *cond,
500         pthread_mutex_t *mutex,
501         const struct timespec* abstime)
502{
503  int   ret;
504  int   res;
505  OrigFn fn;
506  VALGRIND_GET_ORIG_FN(fn);
507  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_WAIT,
508                             cond, mutex, mutex_type(mutex), 0, 0);
509  CALL_FN_W_WWW(ret, fn, cond, mutex, abstime);
510  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT,
511                             cond, mutex, 1, 0, 0);
512  return ret;
513}
514
515// pthread_cond_signal
516PTH_FUNC(int, pthreadZucondZusignalZa, // pthread_cond_signal*
517         pthread_cond_t* cond)
518{
519  int   ret;
520  int   res;
521  OrigFn fn;
522  VALGRIND_GET_ORIG_FN(fn);
523  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_SIGNAL,
524                             cond, 0, 0, 0, 0);
525  CALL_FN_W_W(ret, fn, cond);
526  return ret;
527}
528
529// pthread_cond_broadcast
530PTH_FUNC(int, pthreadZucondZubroadcastZa, // pthread_cond_broadcast*
531         pthread_cond_t* cond)
532{
533  int   ret;
534  int   res;
535  OrigFn fn;
536  VALGRIND_GET_ORIG_FN(fn);
537  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_BROADCAST,
538                             cond, 0, 0, 0, 0);
539  CALL_FN_W_W(ret, fn, cond);
540  return ret;
541}
542
543
544// pthread_spin_init
545PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init
546         pthread_spinlock_t *spinlock,
547         int pshared)
548{
549  int ret;
550  int res;
551  OrigFn fn;
552  VALGRIND_GET_ORIG_FN(fn);
553  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SPIN_INIT_OR_UNLOCK,
554                             spinlock, mutex_type_spinlock, 0, 0, 0);
555  CALL_FN_W_WW(ret, fn, spinlock, pshared);
556  return ret;
557}
558
559// pthread_spin_destroy
560PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy
561         pthread_spinlock_t *spinlock)
562{
563  int ret;
564  int res;
565  OrigFn fn;
566  VALGRIND_GET_ORIG_FN(fn);
567  CALL_FN_W_W(ret, fn, spinlock);
568  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY,
569                             spinlock, mutex_type_spinlock, 0, 0, 0);
570  return ret;
571}
572
573// pthread_spin_lock
574PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock
575         pthread_spinlock_t *spinlock)
576{
577  int   ret;
578  int   res;
579  OrigFn fn;
580  VALGRIND_GET_ORIG_FN(fn);
581  VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
582                             spinlock, mutex_type_spinlock, 0, 0, 0);
583  CALL_FN_W_W(ret, fn, spinlock);
584  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK,
585                             spinlock, ret == 0, 0, 0, 0);
586  return ret;
587}
588
589// pthread_spin_trylock
590PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock
591         pthread_spinlock_t *spinlock)
592{
593  int   ret;
594  int   res;
595  OrigFn fn;
596  VALGRIND_GET_ORIG_FN(fn);
597  VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK,
598                             spinlock, mutex_type_spinlock, 0, 0, 0);
599  CALL_FN_W_W(ret, fn, spinlock);
600  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK,
601                             spinlock, ret == 0, 0, 0, 0);
602  return ret;
603}
604
605// pthread_spin_unlock
606PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock
607         pthread_spinlock_t *spinlock)
608{
609  int   ret;
610  int   res;
611  OrigFn fn;
612  VALGRIND_GET_ORIG_FN(fn);
613  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SPIN_INIT_OR_UNLOCK,
614                             spinlock, mutex_type_spinlock, 0, 0, 0);
615  CALL_FN_W_W(ret, fn, spinlock);
616  return ret;
617}
618
619// pthread_barrier_init
620PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init
621         pthread_barrier_t* barrier,
622         const pthread_barrierattr_t* attr,
623         unsigned count)
624{
625  int   ret;
626  int   res;
627  OrigFn fn;
628  VALGRIND_GET_ORIG_FN(fn);
629  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_INIT,
630                             barrier, pthread_barrier, count, 0, 0);
631  CALL_FN_W_WWW(ret, fn, barrier, attr, count);
632  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_INIT,
633                             barrier, pthread_barrier, 0, 0, 0);
634  return ret;
635}
636
637// pthread_barrier_destroy
638PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy
639         pthread_barrier_t* barrier)
640{
641  int   ret;
642  int   res;
643  OrigFn fn;
644  VALGRIND_GET_ORIG_FN(fn);
645  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_DESTROY,
646                             barrier, pthread_barrier, 0, 0, 0);
647  CALL_FN_W_W(ret, fn, barrier);
648  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_DESTROY,
649                             barrier, pthread_barrier, 0, 0, 0);
650  return ret;
651}
652
653// pthread_barrier_wait
654PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait
655         pthread_barrier_t* barrier)
656{
657  int   ret;
658  int   res;
659  OrigFn fn;
660  VALGRIND_GET_ORIG_FN(fn);
661  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT,
662                             barrier, pthread_barrier, 0, 0, 0);
663  CALL_FN_W_W(ret, fn, barrier);
664  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT,
665                             barrier, pthread_barrier,
666                             ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD,
667                             0, 0);
668  return ret;
669}
670
671
672// sem_init
673PTH_FUNC(int, semZuinitZa, // sem_init*
674         sem_t *sem,
675         int pshared,
676         unsigned int value)
677{
678  int   ret;
679  int   res;
680  OrigFn fn;
681  VALGRIND_GET_ORIG_FN(fn);
682  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_INIT,
683                             sem, pshared, value, 0, 0);
684  CALL_FN_W_WWW(ret, fn, sem, pshared, value);
685  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_INIT,
686                             sem, 0, 0, 0, 0);
687  return ret;
688}
689
690// sem_destroy
691PTH_FUNC(int, semZudestroyZa, // sem_destroy*
692         sem_t *sem)
693{
694  int   ret;
695  int   res;
696  OrigFn fn;
697  VALGRIND_GET_ORIG_FN(fn);
698  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_DESTROY,
699                             sem, 0, 0, 0, 0);
700  CALL_FN_W_W(ret, fn, sem);
701  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_DESTROY,
702                             sem, 0, 0, 0, 0);
703  return ret;
704}
705
706// sem_wait
707PTH_FUNC(int, semZuwaitZa, // sem_wait*
708         sem_t *sem)
709{
710  int   ret;
711  int   res;
712  OrigFn fn;
713  VALGRIND_GET_ORIG_FN(fn);
714  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
715                             sem, 0, 0, 0, 0);
716  CALL_FN_W_W(ret, fn, sem);
717  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
718                             sem, ret == 0, 0, 0, 0);
719  return ret;
720}
721
722// sem_trywait
723PTH_FUNC(int, semZutrywaitZa, // sem_trywait*
724         sem_t *sem)
725{
726  int   ret;
727  int   res;
728  OrigFn fn;
729  VALGRIND_GET_ORIG_FN(fn);
730  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
731                             sem, 0, 0, 0, 0);
732  CALL_FN_W_W(ret, fn, sem);
733  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
734                             sem, ret == 0, 0, 0, 0);
735  return ret;
736}
737
738// sem_timedwait
739PTH_FUNC(int, semZutimedwait, // sem_timedwait
740         sem_t *sem, const struct timespec *abs_timeout)
741{
742  int   ret;
743  int   res;
744  OrigFn fn;
745  VALGRIND_GET_ORIG_FN(fn);
746  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT,
747                             sem, 0, 0, 0, 0);
748  CALL_FN_W_WW(ret, fn, sem, abs_timeout);
749  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT,
750                             sem, ret == 0, 0, 0, 0);
751  return ret;
752}
753
754// sem_post
755PTH_FUNC(int, semZupostZa, // sem_post*
756         sem_t *sem)
757{
758  int   ret;
759  int   res;
760  OrigFn fn;
761  VALGRIND_GET_ORIG_FN(fn);
762  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST,
763                             sem, 0, 0, 0, 0);
764  CALL_FN_W_W(ret, fn, sem);
765  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST,
766                             sem, ret == 0, 0, 0, 0);
767  return ret;
768}
769
770// pthread_rwlock_init
771PTH_FUNC(int,
772         pthreadZurwlockZuinitZa, // pthread_rwlock_init*
773         pthread_rwlock_t* rwlock,
774         const pthread_rwlockattr_t* attr)
775{
776  int   ret;
777  int   res;
778  OrigFn fn;
779  VALGRIND_GET_ORIG_FN(fn);
780  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_INIT,
781                             rwlock, 0, 0, 0, 0);
782  CALL_FN_W_WW(ret, fn, rwlock, attr);
783  return ret;
784}
785
786// pthread_rwlock_destroy
787PTH_FUNC(int,
788         pthreadZurwlockZudestroyZa, // pthread_rwlock_destroy*
789         pthread_rwlock_t* rwlock)
790{
791  int   ret;
792  int   res;
793  OrigFn fn;
794  VALGRIND_GET_ORIG_FN(fn);
795  CALL_FN_W_W(ret, fn, rwlock);
796  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_DESTROY,
797                             rwlock, 0, 0, 0, 0);
798  return ret;
799}
800
801// pthread_rwlock_rdlock
802PTH_FUNC(int,
803         pthreadZurwlockZurdlockZa, // pthread_rwlock_rdlock*
804         pthread_rwlock_t* rwlock)
805{
806  int   ret;
807  int   res;
808  OrigFn fn;
809  VALGRIND_GET_ORIG_FN(fn);
810  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
811                             rwlock, 0, 0, 0, 0);
812  CALL_FN_W_W(ret, fn, rwlock);
813  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK,
814                             rwlock, ret == 0, 0, 0, 0);
815  return ret;
816}
817
818// pthread_rwlock_wrlock
819PTH_FUNC(int,
820         pthreadZurwlockZuwrlockZa, // pthread_rwlock_wrlock*
821         pthread_rwlock_t* rwlock)
822{
823  int   ret;
824  int   res;
825  OrigFn fn;
826  VALGRIND_GET_ORIG_FN(fn);
827  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
828                             rwlock, 0, 0, 0, 0);
829  CALL_FN_W_W(ret, fn, rwlock);
830  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK,
831                             rwlock, ret == 0, 0, 0, 0);
832  return ret;
833}
834
835// pthread_rwlock_timedrdlock
836PTH_FUNC(int,
837         pthreadZurwlockZutimedrdlockZa, // pthread_rwlock_timedrdlock*
838         pthread_rwlock_t* rwlock)
839{
840  int   ret;
841  int   res;
842  OrigFn fn;
843  VALGRIND_GET_ORIG_FN(fn);
844  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
845                             rwlock, 0, 0, 0, 0);
846  CALL_FN_W_W(ret, fn, rwlock);
847  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK,
848                             rwlock, ret == 0, 0, 0, 0);
849  return ret;
850}
851
852// pthread_rwlock_timedwrlock
853PTH_FUNC(int,
854         pthreadZurwlockZutimedwrlockZa, // pthread_rwlock_timedwrlock*
855         pthread_rwlock_t* rwlock)
856{
857  int   ret;
858  int   res;
859  OrigFn fn;
860  VALGRIND_GET_ORIG_FN(fn);
861  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
862                             rwlock, 0, 0, 0, 0);
863  CALL_FN_W_W(ret, fn, rwlock);
864  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK,
865                             rwlock, ret == 0, 0, 0, 0);
866  return ret;
867}
868
869// pthread_rwlock_tryrdlock
870PTH_FUNC(int,
871         pthreadZurwlockZutryrdlockZa, // pthread_rwlock_tryrdlock*
872         pthread_rwlock_t* rwlock)
873{
874  int   ret;
875  int   res;
876  OrigFn fn;
877  VALGRIND_GET_ORIG_FN(fn);
878  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK,
879                             rwlock, 0, 0, 0, 0);
880  CALL_FN_W_W(ret, fn, rwlock);
881  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK,
882                             rwlock, ret == 0, 0, 0, 0);
883  return ret;
884}
885
886// pthread_rwlock_trywrlock
887PTH_FUNC(int,
888         pthreadZurwlockZutrywrlockZa, // pthread_rwlock_trywrlock*
889         pthread_rwlock_t* rwlock)
890{
891  int   ret;
892  int   res;
893  OrigFn fn;
894  VALGRIND_GET_ORIG_FN(fn);
895  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK,
896                             rwlock, 0, 0, 0, 0);
897  CALL_FN_W_W(ret, fn, rwlock);
898  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK,
899                             rwlock, ret == 0, 0, 0, 0);
900  return ret;
901}
902
903// pthread_rwlock_unlock
904PTH_FUNC(int,
905         pthreadZurwlockZuunlockZa, // pthread_rwlock_unlock*
906         pthread_rwlock_t* rwlock)
907{
908  int   ret;
909  int   res;
910  OrigFn fn;
911  VALGRIND_GET_ORIG_FN(fn);
912  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_UNLOCK,
913                             rwlock, 0, 0, 0, 0);
914  CALL_FN_W_W(ret, fn, rwlock);
915  VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_UNLOCK,
916                             rwlock, ret == 0, 0, 0, 0);
917  return ret;
918}
919