Home | History | Annotate | Download | only in tsan
      1 /*
      2   This file is part of ThreadSanitizer, a dynamic data race detector
      3   based on Valgrind.
      4 
      5   Copyright (C) 2008-2009 Google Inc
      6      opensource (at) google.com
      7   Copyright (C) 2007-2008 OpenWorks LLP
      8       info (at) open-works.co.uk
      9 
     10   This program is free software; you can redistribute it and/or
     11   modify it under the terms of the GNU General Public License as
     12   published by the Free Software Foundation; either version 2 of the
     13   License, or (at your option) any later version.
     14 
     15   This program is distributed in the hope that it will be useful, but
     16   WITHOUT ANY WARRANTY; without even the implied warranty of
     17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     18   General Public License for more details.
     19 
     20   You should have received a copy of the GNU General Public License
     21   along with this program; if not, write to the Free Software
     22   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     23   02111-1307, USA.
     24 
     25   The GNU General Public License is contained in the file COPYING.
     26 */
     27 
     28 // Author: Konstantin Serebryany.
     29 // Parts of the code in this file are derived from Helgrind,
     30 // a data race detector written by Julian Seward.
     31 // Note that the rest of ThreadSanitizer code is not derived from Helgrind
     32 // and is published under the BSD license.
     33 
     34 #define _GNU_SOURCE 1
     35 #include <stdio.h>
     36 #include <stdlib.h>
     37 #include <assert.h>
     38 #include <errno.h>
     39 #include <pthread.h>
     40 #include <fcntl.h>  // O_CREAT
     41 #include <unistd.h> // F_LOCK
     42 
     43 #include "valgrind.h"
     44 #include "pub_tool_basics.h"
     45 #include "pub_tool_redir.h"
     46 #include "pub_tool_threadstate.h"
     47 
     48 #define NOINLINE __attribute__ ((noinline))
     49 
     50 #include "ts_valgrind_client_requests.h"
     51 
     52 // When replacing a function in valgrind, the replacement code
     53 // is instrumented, so we just don't touch reads/writes in replacement
     54 // functions.
     55 #define EXTRA_REPLACE_PARAMS
     56 #define EXTRA_REPLACE_ARGS
     57 #define REPORT_READ_RANGE(x, size)
     58 #define REPORT_WRITE_RANGE(x, size)
     59 #include "ts_replace.h"
     60 
     61 #define TRACE_PTH_FNS 0
     62 #define TRACE_ANN_FNS 0
     63 
     64 
     65 //----------- Basic stuff --------------------------- {{{1
     66 
     67 static inline int VALGRIND_TS_THREAD_ID(void) {
     68   unsigned int _qzz_res;
     69   VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 ,
     70                              TSREQ_GET_THREAD_ID,
     71                              0, 0, 0, 0, 0);
     72   return _qzz_res;
     73 }
     74 
     75 static inline int VALGRIND_VG_THREAD_ID(void) {
     76   unsigned int _qzz_res;
     77   VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 ,
     78                              TSREQ_GET_VG_THREAD_ID,
     79                              0, 0, 0, 0, 0);
     80   return _qzz_res;
     81 }
     82 
     83 static inline int  VALGRIND_TS_SEGMENT_ID(void) {
     84   unsigned int _qzz_res;
     85   VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 ,
     86                              TSREQ_GET_SEGMENT_ID,
     87                              0, 0, 0, 0, 0);
     88   return _qzz_res;
     89 }
     90 
     91 #define PTH_FUNC(ret_ty, f, args...) \
     92    ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args); \
     93    ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args)
     94 
     95 #define NONE_FUNC(ret_ty, f, args...) \
     96    ret_ty I_WRAP_SONAME_FNNAME_ZZ(NONE,f)(args); \
     97    ret_ty I_WRAP_SONAME_FNNAME_ZZ(NONE,f)(args)
     98 
     99 #define LIBC_FUNC(ret_ty, f, args...) \
    100    ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBC_SONAME,f)(args); \
    101    ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBC_SONAME,f)(args)
    102 
    103 // libstdcZpZpZa = libstdc++
    104 #define LIBSTDCXX_FUNC(ret_ty, f, args...) \
    105    ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBSTDCXX_SONAME,f)(args); \
    106    ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBSTDCXX_SONAME,f)(args)
    107 
    108 
    109 // Do a client request.  This is a macro rather than a function
    110 // so as to avoid having an extra function in the stack trace.
    111 
    112 #define DO_CREQ_v_v(_creqF)                              \
    113    do {                                                  \
    114       Word _unused_res;                                  \
    115       VALGRIND_DO_CLIENT_REQUEST(_unused_res, 0,         \
    116                                  (_creqF),               \
    117                                  0,0,0,0,0);             \
    118    } while (0)
    119 
    120 #define DO_CREQ_v_W(_creqF, _ty1F,_arg1F)                \
    121    do {                                                  \
    122       Word _unused_res, _arg1;                           \
    123       assert(sizeof(_ty1F) == sizeof(Word));             \
    124       _arg1 = (Word)(_arg1F);                            \
    125       VALGRIND_DO_CLIENT_REQUEST(_unused_res, 0,         \
    126                                  (_creqF),               \
    127                                  _arg1, 0,0,0,0);        \
    128    } while (0)
    129 
    130 #define DO_CREQ_v_WW(_creqF, _ty1F,_arg1F, _ty2F,_arg2F) \
    131    do {                                                  \
    132       Word _unused_res, _arg1, _arg2;                    \
    133       assert(sizeof(_ty1F) == sizeof(Word));             \
    134       assert(sizeof(_ty2F) == sizeof(Word));             \
    135       _arg1 = (Word)(_arg1F);                            \
    136       _arg2 = (Word)(_arg2F);                            \
    137       VALGRIND_DO_CLIENT_REQUEST(_unused_res, 0,         \
    138                                  (_creqF),               \
    139                                  _arg1,_arg2,0,0,0);     \
    140    } while (0)
    141 
    142 #define DO_CREQ_W_WW(_resF, _creqF, _ty1F,_arg1F, _ty2F,_arg2F) \
    143    do {                                                  \
    144       Word _res, _arg1, _arg2;                           \
    145       assert(sizeof(_ty1F) == sizeof(Word));             \
    146       assert(sizeof(_ty2F) == sizeof(Word));             \
    147       _arg1 = (Word)(_arg1F);                            \
    148       _arg2 = (Word)(_arg2F);                            \
    149       VALGRIND_DO_CLIENT_REQUEST(_res, 2,                \
    150                                  (_creqF),               \
    151                                  _arg1,_arg2,0,0,0);     \
    152       _resF = _res;                                      \
    153    } while (0)
    154 
    155 #define DO_CREQ_v_WWW(_creqF, _ty1F,_arg1F,              \
    156 		      _ty2F,_arg2F, _ty3F, _arg3F)       \
    157    do {                                                  \
    158       Word _unused_res, _arg1, _arg2, _arg3;             \
    159       assert(sizeof(_ty1F) == sizeof(Word));             \
    160       assert(sizeof(_ty2F) == sizeof(Word));             \
    161       assert(sizeof(_ty3F) == sizeof(Word));             \
    162       _arg1 = (Word)(_arg1F);                            \
    163       _arg2 = (Word)(_arg2F);                            \
    164       _arg3 = (Word)(_arg3F);                            \
    165       VALGRIND_DO_CLIENT_REQUEST(_unused_res, 0,         \
    166                                  (_creqF),               \
    167                                  _arg1,_arg2,_arg3,0,0); \
    168    } while (0)
    169 
    170 #define DO_CREQ_v_WWWW(_creqF, _ty1F,_arg1F, _ty2F,_arg2F,\
    171 		      _ty3F,_arg3F, _ty4F, _arg4F)       \
    172    do {                                                  \
    173       Word _unused_res, _arg1, _arg2, _arg3, _arg4;      \
    174       assert(sizeof(_ty1F) == sizeof(Word));             \
    175       assert(sizeof(_ty2F) == sizeof(Word));             \
    176       assert(sizeof(_ty3F) == sizeof(Word));             \
    177       assert(sizeof(_ty4F) == sizeof(Word));             \
    178       _arg1 = (Word)(_arg1F);                            \
    179       _arg2 = (Word)(_arg2F);                            \
    180       _arg3 = (Word)(_arg3F);                            \
    181       _arg4 = (Word)(_arg4F);                            \
    182       VALGRIND_DO_CLIENT_REQUEST(_unused_res, 0,         \
    183                               (_creqF),                  \
    184                              _arg1,_arg2,_arg3,_arg4,0); \
    185    } while (0)
    186 
    187 
    188 
    189 #define DO_PthAPIerror(_fnnameF, _errF)                  \
    190    do {                                                  \
    191       char* _fnname = (char*)(_fnnameF);                 \
    192       long  _err    = (long)(int)(_errF);                \
    193       char* _errstr = lame_strerror(_err);               \
    194       DO_CREQ_v_WWW(TSREQ_PTH_API_ERROR,                 \
    195                     char*,_fnname,                       \
    196                     long,_err, char*,_errstr);           \
    197    } while (0)
    198 
    199 static inline void IGNORE_ALL_ACCESSES_BEGIN(void) {
    200    DO_CREQ_v_W(TSREQ_IGNORE_ALL_ACCESSES_BEGIN,  void*, NULL);
    201 }
    202 
    203 static inline void IGNORE_ALL_ACCESSES_END(void) {
    204    DO_CREQ_v_W(TSREQ_IGNORE_ALL_ACCESSES_END,  void*, NULL);
    205 }
    206 
    207 static inline void IGNORE_ALL_SYNC_BEGIN(void) {
    208    DO_CREQ_v_W(TSREQ_IGNORE_ALL_SYNC_BEGIN,  void*, NULL);
    209 }
    210 
    211 static inline void IGNORE_ALL_SYNC_END(void) {
    212    DO_CREQ_v_W(TSREQ_IGNORE_ALL_SYNC_END,  void*, NULL);
    213 }
    214 
    215 static inline void IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(void) {
    216   IGNORE_ALL_ACCESSES_BEGIN();
    217   IGNORE_ALL_SYNC_BEGIN();
    218 }
    219 
    220 static inline void IGNORE_ALL_ACCESSES_AND_SYNC_END(void) {
    221   IGNORE_ALL_ACCESSES_END();
    222   IGNORE_ALL_SYNC_END();
    223 }
    224 
    225 //-------------- Wrapper for main() -------- {{{1
    226 #define MAIN_WRAPPER_DECL \
    227  int I_WRAP_SONAME_FNNAME_ZU(NONE,main) (long argc, char **argv, char **env)
    228 
    229 MAIN_WRAPPER_DECL;
    230 MAIN_WRAPPER_DECL {
    231   int ret;
    232   OrigFn fn;
    233   VALGRIND_GET_ORIG_FN(fn);
    234   DO_CREQ_v_WW(TSREQ_MAIN_IN,  long, argc, char **, argv);
    235   CALL_FN_W_WWW(ret, fn, argc, argv, env);
    236   DO_CREQ_v_W(TSREQ_MAIN_OUT,  void*, ret);
    237   return ret;
    238 }
    239 
    240 //-------------- MALLOC -------------------- {{{1
    241 
    242 // We ignore memory accesses and sync events inside malloc.
    243 // Accesses are ignored so that we don't spend time on them.
    244 // Sync events are ignored so that malloc does not create h-b arcs.
    245 // Currently, we ignore only Lock/Unlock events, not any other sync events.
    246 
    247 #define WRAP_MALLOC(soname, fnname) \
    248   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (SizeT n); \
    249   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (SizeT n) { \
    250     void* ret; \
    251     OrigFn fn;\
    252     VALGRIND_GET_ORIG_FN(fn);\
    253     IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \
    254       CALL_FN_W_W(ret, fn, n); \
    255     IGNORE_ALL_ACCESSES_AND_SYNC_END(); \
    256     DO_CREQ_v_WW(TSREQ_MALLOC,  void*, ret, long, n); \
    257     return ret; \
    258   }
    259 
    260 #define WRAP_CALLOC(soname, fnname) \
    261   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (SizeT n, SizeT c); \
    262   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (SizeT n, SizeT c) { \
    263     void* ret; \
    264     OrigFn fn;\
    265     VALGRIND_GET_ORIG_FN(fn);\
    266     IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \
    267       CALL_FN_W_WW(ret, fn, n, c); \
    268     IGNORE_ALL_ACCESSES_AND_SYNC_END(); \
    269     DO_CREQ_v_WW(TSREQ_MALLOC,  void*, ret, long, n * c); \
    270     return ret; \
    271   }
    272 
    273 #define WRAP_REALLOC(soname, fnname) \
    274   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *ptr, SizeT n); \
    275   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *ptr, SizeT n) { \
    276     void* ret; \
    277     OrigFn fn;\
    278     VALGRIND_GET_ORIG_FN(fn);\
    279     IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \
    280       CALL_FN_W_WW(ret, fn, ptr, n); \
    281     IGNORE_ALL_ACCESSES_AND_SYNC_END(); \
    282     DO_CREQ_v_WW(TSREQ_MALLOC,  void*, ret, long, n); \
    283     return ret; \
    284   }
    285 
    286 #define WRAP_POSIX_MEMALIGN(soname, fnname) \
    287   int I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void **ptr, long a, long size);\
    288   int I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void **ptr, long a, long size){\
    289     OrigFn fn;\
    290     int ret;\
    291     VALGRIND_GET_ORIG_FN(fn);\
    292     IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \
    293       CALL_FN_W_WWW(ret, fn, ptr, a, size); \
    294     IGNORE_ALL_ACCESSES_AND_SYNC_END(); \
    295     if (ret == 0) \
    296       DO_CREQ_v_WW(TSREQ_MALLOC,  void*, *ptr, long, size); \
    297     return ret; \
    298   }
    299 
    300 #define WRAP_WORKQ_OPS(soname, fnname) \
    301   int I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (int options, void* item, \
    302                                               int priority);\
    303   int I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (int options, void* item, \
    304                                               int priority){\
    305     OrigFn fn;\
    306     int ret;\
    307     VALGRIND_GET_ORIG_FN(fn);\
    308     CALL_FN_W_WWW(ret, fn, options, item, priority); \
    309     /* Trigger only on workq_ops(QUEUE_ADD) */ \
    310     if (options == 1) { \
    311       DO_CREQ_v_W(TSREQ_SIGNAL, void*,item); \
    312     } \
    313     return ret; \
    314   }
    315 
    316 WRAP_WORKQ_OPS(VG_Z_LIBC_SONAME, __workq_ops);
    317 
    318 #ifdef ANDROID
    319 #define OFF_T_SIZE 4
    320 #else
    321 // TODO: this is probably wrong for 32-bit code without -D_FILE_OFFSET_BITS=64
    322 #define OFF_T_SIZE 8
    323 #endif
    324 
    325 // Hacky workaround for https://bugs.kde.org/show_bug.cgi?id=228471
    326 // Used in mmap and lockf wrappers.
    327 #if VG_WORDSIZE < OFF_T_SIZE
    328 typedef unsigned long long OFF_T;
    329 #define CALL_FN_W_5WO_T(ret,fn,p1,p2,p3,p4,p5,off_t_p) CALL_FN_W_7W(ret,fn,\
    330                         p1,p2,p3,p4,p5,off_t_p & 0xffffffff, off_t_p >> 32)
    331 #define CALL_FN_W_2WO_T(ret,fn,p1,p2,off_t_p) CALL_FN_W_WWWW(ret,fn,\
    332                                  p1,p2,off_t_p & 0xffffffff, off_t_p >> 32)
    333 #else
    334 typedef long OFF_T;
    335 #define CALL_FN_W_5WO_T(ret,fn,p1,p2,p3,p4,p5,off_t_p) CALL_FN_W_6W(ret,fn,\
    336                                                     p1,p2,p3,p4,p5,off_t_p)
    337 #define CALL_FN_W_2WO_T(ret,fn,p1,p2,off_t_p) CALL_FN_W_WWW(ret,fn,\
    338                                                     p1,p2,off_t_p)
    339 #endif
    340 
    341 #define WRAP_MMAP(soname, fnname) \
    342   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *ptr, long size, long a, \
    343                                                 long b, long c, OFF_T d); \
    344   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *ptr, long size, long a, \
    345                                                 long b, long c, OFF_T d){ \
    346     void* ret;\
    347     OrigFn fn;\
    348     VALGRIND_GET_ORIG_FN(fn);\
    349     IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \
    350       CALL_FN_W_5WO_T(ret, fn, ptr, size, a, b, c, d); \
    351     IGNORE_ALL_ACCESSES_AND_SYNC_END(); \
    352     if (ret != (void*)-1) { \
    353       DO_CREQ_v_WW(TSREQ_MMAP,  void*, ret, long, size); \
    354     } \
    355     return ret; \
    356   }
    357 
    358 #define WRAP_MUNMAP(soname, fnname) \
    359   int I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *ptr, size_t size); \
    360   int I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *ptr, size_t size){ \
    361     int ret;\
    362     OrigFn fn;\
    363     VALGRIND_GET_ORIG_FN(fn);\
    364     IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \
    365       CALL_FN_W_WW(ret, fn, ptr, size); \
    366     IGNORE_ALL_ACCESSES_AND_SYNC_END(); \
    367     if (ret == 0) { \
    368       DO_CREQ_v_WW(TSREQ_MUNMAP, void*, ptr, size_t, size); \
    369     } \
    370     return ret; \
    371   }
    372 
    373 #define WRAP_ZONE_MALLOC(soname, fnname) \
    374   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void* zone, SizeT n); \
    375   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void* zone, SizeT n) { \
    376     void* ret; \
    377     OrigFn fn;\
    378     VALGRIND_GET_ORIG_FN(fn);\
    379     IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \
    380       CALL_FN_W_WW(ret, fn, zone, n); \
    381     IGNORE_ALL_ACCESSES_AND_SYNC_END(); \
    382     DO_CREQ_v_WW(TSREQ_MALLOC,  void*, ret, long, n); \
    383     return ret; \
    384   }
    385 
    386 #define WRAP_ZONE_CALLOC(soname, fnname) \
    387   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void* zone, SizeT n, SizeT c); \
    388   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void* zone, SizeT n, SizeT c) { \
    389     void* ret; \
    390     OrigFn fn;\
    391     VALGRIND_GET_ORIG_FN(fn);\
    392     IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \
    393       CALL_FN_W_WWW(ret, fn, zone, n, c); \
    394     IGNORE_ALL_ACCESSES_AND_SYNC_END(); \
    395     DO_CREQ_v_WW(TSREQ_MALLOC,  void*, ret, long, n * c); \
    396     return ret; \
    397   }
    398 
    399 #define WRAP_ZONE_REALLOC(soname, fnname) \
    400   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void* zone, void *ptr, SizeT n); \
    401   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void* zone, void *ptr, SizeT n) { \
    402     void* ret; \
    403     OrigFn fn;\
    404     VALGRIND_GET_ORIG_FN(fn);\
    405     IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \
    406       CALL_FN_W_WWW(ret, fn, zone, ptr, n); \
    407     IGNORE_ALL_ACCESSES_AND_SYNC_END(); \
    408     DO_CREQ_v_WW(TSREQ_MALLOC, void*, ret, long, n); \
    409     return ret; \
    410   }
    411 
    412 
    413 WRAP_ZONE_MALLOC(VG_Z_LIBC_SONAME, malloc_zone_malloc);
    414 WRAP_ZONE_CALLOC(VG_Z_LIBC_SONAME, malloc_zone_calloc);
    415 WRAP_ZONE_REALLOC(VG_Z_LIBC_SONAME, malloc_zone_realloc);
    416 
    417 WRAP_MALLOC(VG_Z_LIBC_SONAME, malloc);
    418 WRAP_MALLOC(NONE, malloc);
    419 
    420 WRAP_MALLOC(VG_Z_LIBC_SONAME, valloc);
    421 WRAP_MALLOC(NONE, valloc);
    422 WRAP_MALLOC(VG_Z_LIBC_SONAME, pvalloc);
    423 WRAP_MALLOC(NONE, pvalloc);
    424 
    425 WRAP_MALLOC(NONE, _Znam);
    426 WRAP_MALLOC(NONE, _Znwm);
    427 WRAP_MALLOC(NONE, _Znaj);
    428 WRAP_MALLOC(NONE, _Znwj);
    429 WRAP_MALLOC(NONE, _ZnamRKSt9nothrow_t);
    430 WRAP_MALLOC(NONE, _ZnwmRKSt9nothrow_t);
    431 WRAP_MALLOC(NONE, _ZnajRKSt9nothrow_t);
    432 WRAP_MALLOC(NONE, _ZnwjRKSt9nothrow_t);
    433 // same for libstdc++.
    434 WRAP_MALLOC(VG_Z_LIBSTDCXX_SONAME, _Znam);
    435 WRAP_MALLOC(VG_Z_LIBSTDCXX_SONAME, _Znwm);
    436 WRAP_MALLOC(VG_Z_LIBSTDCXX_SONAME, _Znaj);
    437 WRAP_MALLOC(VG_Z_LIBSTDCXX_SONAME, _Znwj);
    438 WRAP_MALLOC(VG_Z_LIBSTDCXX_SONAME, _ZnamRKSt9nothrow_t);
    439 WRAP_MALLOC(VG_Z_LIBSTDCXX_SONAME, _ZnwmRKSt9nothrow_t);
    440 WRAP_MALLOC(VG_Z_LIBSTDCXX_SONAME, _ZnajRKSt9nothrow_t);
    441 WRAP_MALLOC(VG_Z_LIBSTDCXX_SONAME, _ZnwjRKSt9nothrow_t);
    442 
    443 
    444 WRAP_CALLOC(VG_Z_LIBC_SONAME, calloc);
    445 WRAP_CALLOC(NONE, calloc);
    446 
    447 WRAP_REALLOC(VG_Z_LIBC_SONAME, realloc); // TODO: handle free inside realloc
    448 WRAP_REALLOC(NONE, realloc); // TODO: handle free inside realloc
    449 WRAP_REALLOC(VG_Z_LIBC_SONAME, memalign);
    450 WRAP_REALLOC(NONE, memalign);
    451 WRAP_POSIX_MEMALIGN(VG_Z_LIBC_SONAME, posix_memalign);
    452 WRAP_POSIX_MEMALIGN(NONE, posix_memalign);
    453 
    454 WRAP_MMAP(VG_Z_LIBC_SONAME, mmap);
    455 WRAP_MMAP(NONE, mmap);
    456 
    457 WRAP_MUNMAP(VG_Z_LIBC_SONAME, munmap);
    458 WRAP_MUNMAP(NONE, munmap);
    459 
    460 #define WRAP_FREE(soname, fnname) \
    461   void I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *ptr); \
    462   void I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *ptr) { \
    463     OrigFn fn;\
    464     VALGRIND_GET_ORIG_FN(fn);\
    465     DO_CREQ_v_W(TSREQ_FREE,  void*, ptr); \
    466     IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \
    467       CALL_FN_v_W(fn, ptr); \
    468     IGNORE_ALL_ACCESSES_AND_SYNC_END(); \
    469   }
    470 
    471 
    472 #define WRAP_FREE_ZZ(soname, fnname) \
    473   void I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) (void *ptr); \
    474   void I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) (void *ptr) { \
    475     OrigFn fn;\
    476     VALGRIND_GET_ORIG_FN(fn);\
    477     DO_CREQ_v_W(TSREQ_FREE,  void*, ptr); \
    478     IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \
    479       CALL_FN_v_W(fn, ptr); \
    480     IGNORE_ALL_ACCESSES_AND_SYNC_END(); \
    481   }
    482 
    483 
    484 #define WRAP_ZONE_FREE(soname, fnname) \
    485   void I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *zone, void *ptr); \
    486   void I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *zone, void *ptr) { \
    487     OrigFn fn;\
    488     VALGRIND_GET_ORIG_FN(fn);\
    489     DO_CREQ_v_W(TSREQ_FREE, void*, ptr); \
    490     IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(); \
    491       CALL_FN_v_WW(fn, zone, ptr); \
    492     IGNORE_ALL_ACCESSES_AND_SYNC_END(); \
    493   }
    494 
    495 WRAP_FREE(VG_Z_LIBC_SONAME, free);
    496 WRAP_ZONE_FREE(VG_Z_LIBC_SONAME, malloc_zone_free);
    497 
    498 WRAP_FREE(NONE, free);
    499 
    500 WRAP_FREE(NONE, _ZdlPv);
    501 WRAP_FREE(NONE, _ZdaPv);
    502 WRAP_FREE(NONE, _ZdlPvRKSt9nothrow_t);
    503 WRAP_FREE(NONE, _ZdaPvRKSt9nothrow_t);
    504 // same for libstdc++
    505 WRAP_FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPv);
    506 WRAP_FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPv);
    507 WRAP_FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPvRKSt9nothrow_t);
    508 WRAP_FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPvRKSt9nothrow_t);
    509 
    510 // operator delete
    511 WRAP_FREE_ZZ(NONE, operatorZsdeleteZa);
    512 
    513 
    514 /* Handle tcmalloc (http://code.google.com/p/google-perftools/) */
    515 
    516 /* tc_ functions (used when tcmalloc is running in release mode) */
    517 WRAP_MALLOC(NONE,tc_malloc);
    518 WRAP_MALLOC(NONE,tc_new);
    519 WRAP_MALLOC(NONE,tc_new_nothrow);
    520 WRAP_MALLOC(NONE,tc_newarray);
    521 WRAP_MALLOC(NONE,tc_newarray_nothrow);
    522 WRAP_FREE(NONE,tc_free);
    523 WRAP_FREE(NONE,tc_cfree);
    524 WRAP_FREE(NONE,tc_delete);
    525 WRAP_FREE(NONE,tc_delete_nothrow);
    526 WRAP_FREE(NONE,tc_deletearray);
    527 WRAP_FREE(NONE,tc_deletearray_nothrow);
    528 WRAP_CALLOC(NONE,tc_calloc);
    529 WRAP_REALLOC(NONE,tc_realloc);
    530 WRAP_MALLOC(NONE,tc_valloc);
    531 WRAP_POSIX_MEMALIGN(NONE,tc_memalign);
    532 WRAP_POSIX_MEMALIGN(NONE,tc_posix_memalign);
    533 
    534 
    535 
    536 //------------ Wrappers for stdio functions ---------
    537 /* These functions have internal synchronization that we don't handle and get
    538    lots of false positives. To fix this, we wrap these functions, touch their
    539    arguments, and pass them through to the original function, ignoring all
    540    memory accesses inside it. */
    541 
    542 size_t I_WRAP_SONAME_FNNAME_ZU(VG_Z_LIBC_SONAME, fwrite) (const void *ptr, size_t size, size_t nmemb, void* stream);
    543 size_t I_WRAP_SONAME_FNNAME_ZU(VG_Z_LIBC_SONAME, fwrite) (const void *ptr, size_t size, size_t nmemb, void* stream) {
    544   size_t ret;
    545   OrigFn fn;
    546   ReadMemory(ptr, size * nmemb);
    547   VALGRIND_GET_ORIG_FN(fn);
    548   IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN();
    549   CALL_FN_W_WWWW(ret, fn, ptr, size, nmemb, stream);
    550   IGNORE_ALL_ACCESSES_AND_SYNC_END();
    551   return ret;
    552 }
    553 
    554 int I_WRAP_SONAME_FNNAME_ZU(VG_Z_LIBC_SONAME, puts) (const char *s);
    555 int I_WRAP_SONAME_FNNAME_ZU(VG_Z_LIBC_SONAME, puts) (const char *s) {
    556   int ret;
    557   OrigFn fn;
    558   ReadString(s);
    559   VALGRIND_GET_ORIG_FN(fn);
    560   IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN();
    561   CALL_FN_W_W(ret, fn, s);
    562   IGNORE_ALL_ACCESSES_AND_SYNC_END();
    563   return ret;
    564 }
    565 
    566 
    567 //-------------- PTHREADS -------------------- {{{1
    568 /* A lame version of strerror which doesn't use the real libc
    569    strerror_r, since using the latter just generates endless more
    570    threading errors (glibc goes off and does tons of crap w.r.t.
    571    locales etc) */
    572 static char* lame_strerror ( long err )
    573 {   switch (err) {
    574       case EPERM:       return "EPERM: Operation not permitted";
    575       case ENOENT:      return "ENOENT: No such file or directory";
    576       case ESRCH:       return "ESRCH: No such process";
    577       case EINTR:       return "EINTR: Interrupted system call";
    578       case EBADF:       return "EBADF: Bad file number";
    579       case EAGAIN:      return "EAGAIN: Try again";
    580       case ENOMEM:      return "ENOMEM: Out of memory";
    581       case EACCES:      return "EACCES: Permission denied";
    582       case EFAULT:      return "EFAULT: Bad address";
    583       case EEXIST:      return "EEXIST: File exists";
    584       case EINVAL:      return "EINVAL: Invalid argument";
    585       case EMFILE:      return "EMFILE: Too many open files";
    586       case ENOSYS:      return "ENOSYS: Function not implemented";
    587       case EOVERFLOW:   return "EOVERFLOW: Value too large "
    588                                "for defined data type";
    589       case EBUSY:       return "EBUSY: Device or resource busy";
    590       case ETIMEDOUT:   return "ETIMEDOUT: Connection timed out";
    591       case EDEADLK:     return "EDEADLK: Resource deadlock would occur";
    592       case EOPNOTSUPP:  return "EOPNOTSUPP: Operation not supported on "
    593                                "transport endpoint"; /* honest, guv */
    594       default:          return "tc_intercepts.c: lame_strerror(): "
    595                                "unhandled case -- please fix me!";
    596    }
    597 }
    598 
    599 
    600 // libpthread sentry functions.
    601 // Darwin implementations of several libpthread functions call other functions
    602 // that are intercepted by ThreadSanitizer as well. To avoid reacting on those
    603 // functions twice the status of each Valgrind thread is stored in the
    604 // tid_inside_pthread_lib array and all the client requests from the inner
    605 // pthread functions are ignored.
    606 
    607 static int tid_inside_pthread_lib[VG_N_THREADS];
    608 
    609 // A pthread_*() function must call pthread_lib_enter() if its implementation
    610 // calls or is called by another pthread_*() function. The function that
    611 // called pthread_lib_enter() should perform client requests to ThreadSanitizer
    612 // iff the return value of pthread_lib_enter() is equal to 1.
    613 static int pthread_lib_enter(void) {
    614   int ret = 1, tid;
    615   IGNORE_ALL_ACCESSES_BEGIN();
    616   tid = VALGRIND_VG_THREAD_ID();
    617   if (tid_inside_pthread_lib[tid]++) {
    618     ret = 0;
    619   } else {
    620     ret = 1;
    621   }
    622   IGNORE_ALL_ACCESSES_END();
    623   return ret;
    624 }
    625 
    626 // A pthread_*() function must call pthread_lib_exit() iff it has called
    627 // pthread_lib_enter().
    628 static void pthread_lib_exit(void) {
    629   int tid;
    630   IGNORE_ALL_ACCESSES_BEGIN();
    631   tid = VALGRIND_VG_THREAD_ID();
    632   tid_inside_pthread_lib[tid]--;
    633   IGNORE_ALL_ACCESSES_END();
    634 }
    635 
    636 /*----------------------------------------------------------------*/
    637 /*--- pthread_create, pthread_join, pthread_exit               ---*/
    638 /*----------------------------------------------------------------*/
    639 
    640 static void* ThreadSanitizerStartThread ( void* xargsV )
    641 {
    642    volatile Word volatile* xargs = (volatile Word volatile*) xargsV;
    643    void*(*fn)(void*) = (void*(*)(void*))xargs[0];
    644    void* arg         = (void*)xargs[1];
    645    pthread_t me = pthread_self();
    646    size_t stacksize = 0;
    647    void *stackaddr = NULL;
    648    pthread_attr_t attr;
    649 
    650    /* Tell the tool what my pthread_t is. */
    651    DO_CREQ_v_W(TSREQ_SET_MY_PTHREAD_T, pthread_t,me);
    652 #ifdef VGO_darwin
    653    /* Tell the tool what my stack size and stack top are.
    654       This is Darwin-specific and works as long as ThreadSanitizerStartThread
    655       is used for pthreads only.
    656    */
    657    stacksize = pthread_get_stacksize_np(me);
    658    stackaddr = pthread_get_stackaddr_np(me);
    659    DO_CREQ_v_WW(TSREQ_SET_STACKTOP_STACKSIZE, void*, stackaddr,
    660                                               size_t, stacksize);
    661 #else
    662    if (pthread_getattr_np(pthread_self(), &attr) == 0) {
    663      pthread_attr_getstack(&attr, &stackaddr, &stacksize);
    664      pthread_attr_destroy(&attr);
    665      DO_CREQ_v_WW(TSREQ_SET_STACKTOP_STACKSIZE,
    666                   void*, (char*)stackaddr + stacksize,
    667                   size_t, stacksize);
    668    } else {
    669      /* Let the tool guess where the stack starts. */
    670      DO_CREQ_v_W(TSREQ_THR_STACK_TOP, void*, &stacksize);
    671    }
    672 #endif
    673    /* allow the parent to proceed.  We can't let it proceed until
    674       we're ready because (1) we need to make sure it doesn't exit and
    675       hence deallocate xargs[] while we still need it, and (2) we
    676       don't want either parent nor child to proceed until the tool has
    677       been notified of the child's pthread_t. */
    678    xargs[2] = 0;
    679    /* Now we can no longer safely use xargs[]. */
    680    return (void*) fn( (void*)arg );
    681 }
    682 
    683 static int pthread_create_WRK(pthread_t *thread, const pthread_attr_t *attr,
    684                               void *(*start) (void *), void *arg)
    685 {
    686    int    ret;
    687    OrigFn fn;
    688    volatile Word xargs[3];
    689 
    690    VALGRIND_GET_ORIG_FN(fn);
    691    if (TRACE_PTH_FNS) {
    692       fprintf(stderr, "<< pthread_create wrapper"); fflush(stderr);
    693    }
    694    xargs[0] = (Word)start;
    695    xargs[1] = (Word)arg;
    696    xargs[2] = 1; /* serves as a spinlock -- sigh */
    697 
    698    IGNORE_ALL_ACCESSES_BEGIN();
    699      CALL_FN_W_WWWW(ret, fn, thread,attr,ThreadSanitizerStartThread,&xargs[0]);
    700    IGNORE_ALL_ACCESSES_END();
    701 
    702    if (ret == 0) {
    703       /* we have to wait for the child to notify the tool of its
    704          pthread_t before continuing */
    705       while (xargs[2] != 0) {
    706          /* Do nothing.  We need to spin until the child writes to
    707             xargs[2].  However, that can lead to starvation in the
    708             child and very long delays (eg, tc19_shadowmem on
    709             ppc64-linux Fedora Core 6).  So yield the cpu if we can,
    710             to let the child run at the earliest available
    711             opportunity. */
    712          sched_yield();
    713       }
    714    } else {
    715       DO_PthAPIerror( "pthread_create", ret );
    716    }
    717 
    718    if (TRACE_PTH_FNS) {
    719       fprintf(stderr, " :: pth_create -> %d >>\n", ret);
    720    }
    721    return ret;
    722 }
    723 
    724 PTH_FUNC(int, pthreadZucreate, // pthread_create (Darwin)
    725               pthread_t *thread, const pthread_attr_t *attr,
    726               void *(*start) (void *), void *arg) {
    727    return pthread_create_WRK(thread, attr, start, arg);
    728 }
    729 PTH_FUNC(int, pthreadZucreateZAZa, // pthread_create@* (Linux)
    730               pthread_t *thread, const pthread_attr_t *attr,
    731               void *(*start) (void *), void *arg) {
    732    return pthread_create_WRK(thread, attr, start, arg);
    733 }
    734 
    735 // pthread_join
    736 static int pthread_join_WRK(pthread_t thread, void** value_pointer)
    737 {
    738    int ret;
    739    OrigFn fn;
    740    VALGRIND_GET_ORIG_FN(fn);
    741    if (TRACE_PTH_FNS) {
    742       fprintf(stderr, "<< pthread_join wrapper"); fflush(stderr);
    743    }
    744 
    745    CALL_FN_W_WW(ret, fn, thread,value_pointer);
    746 
    747    /* At least with NPTL as the thread library, this is safe because
    748       it is guaranteed (by NPTL) that the joiner will completely gone
    749       before pthread_join (the original) returns.  See email below.*/
    750    if (ret == 0 /*success*/) {
    751       DO_CREQ_v_W(TSREQ_PTHREAD_JOIN_POST, pthread_t,thread);
    752    } else {
    753       DO_PthAPIerror( "pthread_join", ret );
    754    }
    755 
    756    if (TRACE_PTH_FNS) {
    757       fprintf(stderr, " :: pth_join -> %d >>\n", ret);
    758    }
    759    return ret;
    760 }
    761 
    762 PTH_FUNC(int, pthreadZujoin, // pthread_join (Linux)
    763               pthread_t thread, void** value_pointer)
    764 {
    765   return pthread_join_WRK(thread, value_pointer);
    766 }
    767 
    768 PTH_FUNC(int, pthreadZujoin$Za, // pthread_join$* (Darwin)
    769               pthread_t thread, void** value_pointer)
    770 {
    771   return pthread_join_WRK(thread, value_pointer);
    772 }
    773 
    774 
    775 
    776 /* Behaviour of pthread_join on NPTL:
    777 
    778 Me:
    779 I have a question re the NPTL pthread_join implementation.
    780 
    781   Suppose I am the thread 'stayer'.
    782 
    783   If I call pthread_join(quitter), is it guaranteed that the
    784   thread 'quitter' has really exited before pthread_join returns?
    785 
    786   IOW, is it guaranteed that 'quitter' will not execute any further
    787   instructions after pthread_join returns?
    788 
    789 I believe this is true based on the following analysis of
    790 glibc-2.5 sources.  However am not 100% sure and would appreciate
    791 confirmation.
    792 
    793   'quitter' will be running start_thread() in nptl/pthread_create.c
    794 
    795   The last action of start_thread() is to exit via
    796   __exit_thread_inline(0), which simply does sys_exit
    797   (nptl/pthread_create.c:403)
    798 
    799   'stayer' meanwhile is waiting for lll_wait_tid (pd->tid)
    800   (call at nptl/pthread_join.c:89)
    801 
    802   As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536,
    803   lll_wait_tid will not return until kernel notifies via futex
    804   wakeup that 'quitter' has terminated.
    805 
    806   Hence pthread_join cannot return until 'quitter' really has
    807   completely disappeared.
    808 
    809 Drepper:
    810 >   As per comment at nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h:536,
    811 >   lll_wait_tid will not return until kernel notifies via futex
    812 >   wakeup that 'quitter' has terminated.
    813 That's the key.  The kernel resets the TID field after the thread is
    814 done.  No way the joiner can return before the thread is gone.
    815 */
    816 
    817 #ifdef ANDROID
    818 // Android-specific part. Ignore some internal synchronization in bionic.
    819 PTH_FUNC(int, pthreadZuexit, void* retval) // pthread_exit (Android)
    820 {
    821   int ret;
    822   OrigFn fn;
    823   VALGRIND_GET_ORIG_FN(fn);
    824   IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN();
    825   CALL_FN_W_W(ret, fn, retval);
    826   IGNORE_ALL_ACCESSES_AND_SYNC_END();
    827   return ret;
    828 }
    829 #endif
    830 
    831 
    832 /*----------------------------------------------------------------*/
    833 /*--- pthread_mutex_t functions                                ---*/
    834 /*----------------------------------------------------------------*/
    835 
    836 /* Handled:   pthread_mutex_init pthread_mutex_destroy
    837               pthread_mutex_lock
    838               pthread_mutex_trylock
    839               pthread_mutex_timedlock
    840               pthread_mutex_unlock
    841 
    842               pthread_spin_init pthread_spin_destroy
    843               pthread_spin_lock
    844               pthread_spin_trylock
    845               pthread_spin_unlock
    846 */
    847 
    848 // pthread_mutex_init
    849 PTH_FUNC(int, pthreadZumutexZuinit, // pthread_mutex_init
    850               pthread_mutex_t *mutex,
    851               pthread_mutexattr_t* attr)
    852 {
    853    int    ret;
    854    long   mbRec;
    855    OrigFn fn;
    856    VALGRIND_GET_ORIG_FN(fn);
    857    if (TRACE_PTH_FNS) {
    858       fprintf(stderr, "<< pthread_mxinit %p", mutex); fflush(stderr);
    859    }
    860 
    861    mbRec = 0;
    862    if (attr) {
    863       int ty, zzz;
    864       zzz = pthread_mutexattr_gettype(attr, &ty);
    865       if (zzz == 0 && ty == PTHREAD_MUTEX_RECURSIVE)
    866          mbRec = 1;
    867    }
    868 
    869    CALL_FN_W_WW(ret, fn, mutex,attr);
    870 
    871    if (ret == 0 /*success*/) {
    872       DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_CREATE_POST,
    873                    pthread_mutex_t*,mutex, long,mbRec);
    874    } else {
    875       DO_PthAPIerror( "pthread_mutex_init", ret );
    876    }
    877 
    878    if (TRACE_PTH_FNS) {
    879       fprintf(stderr, " :: mxinit -> %d >>\n", ret);
    880    }
    881    return ret;
    882 }
    883 
    884 
    885 // pthread_mutex_destroy
    886 PTH_FUNC(int, pthreadZumutexZudestroy, // pthread_mutex_destroy
    887               pthread_mutex_t *mutex)
    888 {
    889    int    ret;
    890    OrigFn fn;
    891    VALGRIND_GET_ORIG_FN(fn);
    892    if (TRACE_PTH_FNS) {
    893       fprintf(stderr, "<< pthread_mxdestroy %p", mutex); fflush(stderr);
    894    }
    895 
    896    DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_DESTROY_PRE,
    897                pthread_mutex_t*,mutex);
    898 
    899    CALL_FN_W_W(ret, fn, mutex);
    900 
    901    if (ret != 0) {
    902       DO_PthAPIerror( "pthread_mutex_destroy", ret );
    903    }
    904 
    905    if (TRACE_PTH_FNS) {
    906       fprintf(stderr, " :: mxdestroy -> %d >>\n", ret);
    907    }
    908    return ret;
    909 }
    910 
    911 
    912 // pthread_mutex_lock
    913 PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock
    914               pthread_mutex_t *mutex)
    915 {
    916    int    ret;
    917    OrigFn fn;
    918    int is_outermost;
    919    VALGRIND_GET_ORIG_FN(fn);
    920    if (TRACE_PTH_FNS) {
    921       fprintf(stderr, "<< pthread_mxlock %p", mutex); fflush(stderr);
    922    }
    923 
    924    is_outermost = pthread_lib_enter();
    925 
    926    CALL_FN_W_W(ret, fn, mutex);
    927 
    928    /* There's a hole here: libpthread now knows the lock is locked,
    929       but the tool doesn't, so some other thread could run and detect
    930       that the lock has been acquired by someone (this thread).  Does
    931       this matter?  Not sure, but I don't think so. */
    932 
    933    if (is_outermost) {
    934       if ((ret == 0 /*success*/)) {
    935          DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST,
    936                       pthread_mutex_t*,mutex, long, 1);
    937       } else {
    938          DO_PthAPIerror( "pthread_mutex_lock", ret );
    939       }
    940    }
    941 
    942    if (TRACE_PTH_FNS) {
    943       fprintf(stderr, " :: mxlock -> %d >>\n", ret);
    944    }
    945    pthread_lib_exit();
    946    return ret;
    947 }
    948 
    949 
    950 // pthread_mutex_trylock.  The handling needed here is very similar
    951 // to that for pthread_mutex_lock, except that we need to tell
    952 // the pre-lock creq that this is a trylock-style operation, and
    953 // therefore not to complain if the lock is nonrecursive and
    954 // already locked by this thread -- because then it'll just fail
    955 // immediately with EBUSY.
    956 static int pthread_mutex_trylock_WRK(pthread_mutex_t *mutex)
    957 {
    958    int    ret;
    959    OrigFn fn;
    960    VALGRIND_GET_ORIG_FN(fn);
    961    if (TRACE_PTH_FNS) {
    962       fprintf(stderr, "<< pthread_mxtrylock %p", mutex); fflush(stderr);
    963    }
    964 
    965    CALL_FN_W_W(ret, fn, mutex);
    966 
    967    /* There's a hole here: libpthread now knows the lock is locked,
    968       but the tool doesn't, so some other thread could run and detect
    969       that the lock has been acquired by someone (this thread).  Does
    970       this matter?  Not sure, but I don't think so. */
    971 
    972    if (ret == 0 /*success*/) {
    973       DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST,
    974                   pthread_mutex_t*,mutex, long, 1);
    975    } else {
    976       if (ret != EBUSY)
    977          DO_PthAPIerror( "pthread_mutex_trylock", ret );
    978    }
    979 
    980    if (TRACE_PTH_FNS) {
    981       fprintf(stderr, " :: mxtrylock -> %d >>\n", ret);
    982    }
    983    return ret;
    984 }
    985 
    986 PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock
    987               pthread_mutex_t *mutex)
    988 {
    989   return pthread_mutex_trylock_WRK(mutex);
    990 }
    991 
    992 
    993 // pthread_mutex_timedlock.  Identical logic to pthread_mutex_trylock.
    994 // Not implemented in Darwin pthreads.
    995 PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock
    996    pthread_mutex_t *mutex,
    997          void* timeout)
    998 {
    999    int    ret;
   1000    OrigFn fn;
   1001    VALGRIND_GET_ORIG_FN(fn);
   1002    if (TRACE_PTH_FNS) {
   1003       fprintf(stderr, "<< pthread_mxtimedlock %p %p", mutex, timeout);
   1004       fflush(stderr);
   1005    }
   1006 
   1007    CALL_FN_W_WW(ret, fn, mutex,timeout);
   1008 
   1009    /* There's a hole here: libpthread now knows the lock is locked,
   1010       but the tool doesn't, so some other thread could run and detect
   1011       that the lock has been acquired by someone (this thread).  Does
   1012       this matter?  Not sure, but I don't think so. */
   1013 
   1014    if (ret == 0 /*success*/) {
   1015       DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST,
   1016                   pthread_mutex_t*,mutex, long, 1);
   1017    } else {
   1018       if (ret != ETIMEDOUT)
   1019          DO_PthAPIerror( "pthread_mutex_timedlock", ret );
   1020    }
   1021 
   1022    if (TRACE_PTH_FNS) {
   1023       fprintf(stderr, " :: mxtimedlock -> %d >>\n", ret);
   1024    }
   1025    return ret;
   1026 }
   1027 
   1028 
   1029 // pthread_mutex_unlock
   1030 PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock
   1031               pthread_mutex_t *mutex)
   1032 {
   1033    int    ret;
   1034    OrigFn fn;
   1035    VALGRIND_GET_ORIG_FN(fn);
   1036 
   1037    if (TRACE_PTH_FNS) {
   1038       fprintf(stderr, "<< pthread_mxunlk %p", mutex); fflush(stderr);
   1039    }
   1040 
   1041    DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_UNLOCK_PRE,
   1042                pthread_mutex_t*,mutex);
   1043 
   1044    CALL_FN_W_W(ret, fn, mutex);
   1045 
   1046    if (ret != 0 /*error*/) {
   1047       DO_PthAPIerror( "pthread_mutex_unlock", ret );
   1048    }
   1049 
   1050    if (TRACE_PTH_FNS) {
   1051       fprintf(stderr, " mxunlk -> %d >>\n", ret);
   1052    }
   1053    return ret;
   1054 }
   1055 
   1056 // pthread_spin_init
   1057 PTH_FUNC(int, pthreadZuspinZuinit, void *lock, int pshared) {
   1058   int    ret;
   1059   OrigFn fn;
   1060   const char *func = "pthread_spin_init";
   1061   VALGRIND_GET_ORIG_FN(fn);
   1062   if (TRACE_PTH_FNS) {
   1063     fprintf(stderr, "<< %s %p", func, lock);
   1064   }
   1065   CALL_FN_W_WW(ret, fn, lock, pshared);
   1066   if (ret == 0)  {
   1067     DO_CREQ_v_W(TSREQ_PTHREAD_SPIN_LOCK_INIT_OR_UNLOCK, void *, lock);
   1068   }
   1069   if (TRACE_PTH_FNS) {
   1070     fprintf(stderr, " -- %p >>\n", lock);
   1071   }
   1072   return ret;
   1073 }
   1074 
   1075 // pthread_spin_destroy
   1076 PTH_FUNC(int, pthreadZuspinZudestroy, void *lock) {
   1077   int    ret;
   1078   OrigFn fn;
   1079   const char *func = "pthread_spin_destroy";
   1080   VALGRIND_GET_ORIG_FN(fn);
   1081   if (TRACE_PTH_FNS) {
   1082     fprintf(stderr, "<< %s %p", func, lock);
   1083   }
   1084   DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_DESTROY_PRE, void*, lock);
   1085   CALL_FN_W_W(ret, fn, lock);
   1086   if (TRACE_PTH_FNS) {
   1087     fprintf(stderr, " -- %p >>\n", lock);
   1088   }
   1089   return ret;
   1090 }
   1091 
   1092 // pthread_spin_lock
   1093 PTH_FUNC(int, pthreadZuspinZulock, void *lock) {
   1094   int    ret;
   1095   OrigFn fn;
   1096   const char *func = "pthread_spin_lock";
   1097   VALGRIND_GET_ORIG_FN(fn);
   1098   if (TRACE_PTH_FNS) {
   1099     fprintf(stderr, "<< %s %p", func, lock);
   1100   }
   1101   CALL_FN_W_W(ret, fn, lock);
   1102   if (ret == 0) {
   1103     DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, void *, lock,
   1104                  long, 1 /*is_w*/);
   1105   }
   1106   if (TRACE_PTH_FNS) {
   1107     fprintf(stderr, " -- %p >>\n", lock);
   1108   }
   1109   return ret;
   1110 }
   1111 
   1112 // pthread_spin_trylock
   1113 PTH_FUNC(int, pthreadZuspinZutrylock, void *lock) {
   1114   int    ret;
   1115   OrigFn fn;
   1116   const char *func = "pthread_spin_trylock";
   1117   VALGRIND_GET_ORIG_FN(fn);
   1118   if (TRACE_PTH_FNS) {
   1119     fprintf(stderr, "<< %s %p", func, lock);
   1120   }
   1121   CALL_FN_W_W(ret, fn, lock);
   1122   if (ret == 0) {
   1123     DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, void *, lock,
   1124                  long, 1 /*is_w*/);
   1125   }
   1126   if (TRACE_PTH_FNS) {
   1127     fprintf(stderr, " -- %p >>\n", lock);
   1128   }
   1129   return ret;
   1130 }
   1131 
   1132 // pthread_spin_unlock
   1133 PTH_FUNC(int, pthreadZuspinZuunlock, void *lock) {
   1134   int    ret;
   1135   OrigFn fn;
   1136   const char *func = "pthread_spin_unlock";
   1137   VALGRIND_GET_ORIG_FN(fn);
   1138   if (TRACE_PTH_FNS) {
   1139     fprintf(stderr, "<< %s %p", func, lock);
   1140   }
   1141   DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_UNLOCK_PRE, void*, lock);
   1142   CALL_FN_W_W(ret, fn, lock);
   1143   if (TRACE_PTH_FNS) {
   1144     fprintf(stderr, " -- %p >>\n", lock);
   1145   }
   1146   return ret;
   1147 }
   1148 
   1149 
   1150 /*----------------------------------------------------------------*/
   1151 /*--- pthread_cond_t functions                                 ---*/
   1152 /*----------------------------------------------------------------*/
   1153 
   1154 /* Handled:   pthread_cond_wait pthread_cond_timedwait
   1155               pthread_cond_signal pthread_cond_broadcast
   1156 
   1157    Unhandled: pthread_cond_init pthread_cond_destroy
   1158               -- are these important?
   1159 */
   1160 
   1161 // pthread_cond_wait
   1162 static int pthread_cond_wait_WRK(pthread_cond_t* cond, pthread_mutex_t* mutex)
   1163 {
   1164   int ret;
   1165   OrigFn fn;
   1166 
   1167   int is_outermost = pthread_lib_enter();
   1168   VALGRIND_GET_ORIG_FN(fn);
   1169 
   1170   if (TRACE_PTH_FNS) {
   1171     fprintf(stderr, "<< pthread_cond_wait %p %p", cond, mutex);
   1172     fflush(stderr);
   1173   }
   1174   if (is_outermost) {
   1175     DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_UNLOCK_PRE, pthread_mutex_t*,mutex);
   1176   }
   1177 
   1178   CALL_FN_W_WW(ret, fn, cond,mutex);
   1179 
   1180   if (is_outermost) {
   1181     DO_CREQ_v_W(TSREQ_WAIT, void *,cond);
   1182     DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, void *, mutex,
   1183                  long, 1 /*is_w*/);
   1184   }
   1185 
   1186   if (ret != 0) {
   1187     DO_PthAPIerror( "pthread_cond_wait", ret );
   1188   }
   1189 
   1190   if (TRACE_PTH_FNS) {
   1191     fprintf(stderr, " cowait -> %d >>\n", ret);
   1192   }
   1193 
   1194   pthread_lib_exit();
   1195 
   1196   return ret;
   1197 }
   1198 
   1199 PTH_FUNC(int, pthreadZucondZuwaitZAZa, // pthread_cond_wait@*
   1200               pthread_cond_t* cond, pthread_mutex_t* mutex)
   1201 {
   1202   return pthread_cond_wait_WRK(cond, mutex);
   1203 }
   1204 
   1205 PTH_FUNC(int, pthreadZucondZuwait$Za, // pthread_cond_wait$*
   1206               pthread_cond_t* cond, pthread_mutex_t* mutex)
   1207 {
   1208   return pthread_cond_wait_WRK(cond, mutex);
   1209 }
   1210 
   1211 
   1212 // pthread_cond_timedwait
   1213 static int pthread_cond_timedwait_WRK(pthread_cond_t* cond,
   1214                                       pthread_mutex_t* mutex,
   1215                                       struct timespec* abstime)
   1216 {
   1217    int ret;
   1218    OrigFn fn;
   1219    int is_outermost = pthread_lib_enter();
   1220    VALGRIND_GET_ORIG_FN(fn);
   1221 
   1222    if (TRACE_PTH_FNS) {
   1223       fprintf(stderr, "<< pthread_cond_timedwait %p %p %p",
   1224                       cond, mutex, abstime);
   1225       fflush(stderr);
   1226    }
   1227 
   1228    /* Tell the tool a cond-wait is about to happen, so it can check
   1229       for bogus argument values.  In return it tells us whether it
   1230       thinks the mutex is valid or not. */
   1231    if (is_outermost) {
   1232      DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_UNLOCK_PRE, void *,mutex);
   1233    }
   1234 
   1235 
   1236    CALL_FN_W_WWW(ret, fn, cond,mutex,abstime);
   1237 
   1238    if (is_outermost) {
   1239       if (ret == 0) {
   1240          DO_CREQ_v_W(TSREQ_WAIT, void *, cond);
   1241       }
   1242       DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST, void *,mutex,
   1243                   long, 1 /*is_w*/);
   1244    }
   1245 
   1246    if (ret != 0 && ret != ETIMEDOUT) {
   1247       DO_PthAPIerror( "pthread_cond_timedwait", ret );
   1248    }
   1249 
   1250    if (TRACE_PTH_FNS) {
   1251       fprintf(stderr, " cotimedwait -> %d >>\n", ret);
   1252    }
   1253 
   1254    pthread_lib_exit();
   1255    return ret;
   1256 }
   1257 
   1258 PTH_FUNC(int, pthreadZucondZutimedwaitZAZa, // pthread_cond_timedwait@*
   1259          pthread_cond_t* cond, pthread_mutex_t* mutex,
   1260          struct timespec* abstime)
   1261 {
   1262   return pthread_cond_timedwait_WRK(cond, mutex, abstime);
   1263 }
   1264 
   1265 PTH_FUNC(int, pthreadZucondZutimedwait$Za, // pthread_cond_timedwait$*
   1266          pthread_cond_t* cond, pthread_mutex_t* mutex,
   1267          struct timespec* abstime)
   1268 {
   1269   return pthread_cond_timedwait_WRK(cond, mutex, abstime);
   1270 }
   1271 
   1272 PTH_FUNC(int, pthreadZucondZutimedwaitZurelativeZunp, // pthread_cond_timedwait_relative_np
   1273          pthread_cond_t* cond, pthread_mutex_t* mutex,
   1274          struct timespec* abstime)
   1275 {
   1276   return pthread_cond_timedwait_WRK(cond, mutex, abstime);
   1277 }
   1278 
   1279 
   1280 // pthread_cond_signal
   1281 static int pthread_cond_signal_WRK(pthread_cond_t* cond)
   1282 {
   1283    int ret;
   1284    OrigFn fn;
   1285    VALGRIND_GET_ORIG_FN(fn);
   1286 
   1287    if (TRACE_PTH_FNS) {
   1288       fprintf(stderr, "<< pthread_cond_signal %p", cond);
   1289       fflush(stderr);
   1290    }
   1291 
   1292    DO_CREQ_v_W(TSREQ_SIGNAL,
   1293                pthread_cond_t*,cond);
   1294 
   1295    CALL_FN_W_W(ret, fn, cond);
   1296 
   1297    if (ret != 0) {
   1298       DO_PthAPIerror( "pthread_cond_signal", ret );
   1299    }
   1300 
   1301    if (TRACE_PTH_FNS) {
   1302       fprintf(stderr, " cosig -> %d >>\n", ret);
   1303    }
   1304 
   1305    return ret;
   1306 }
   1307 
   1308 PTH_FUNC(int, pthreadZucondZusignal, // pthread_cond_signal
   1309               pthread_cond_t* cond)
   1310 {
   1311   return pthread_cond_signal_WRK(cond);
   1312 }
   1313 
   1314 PTH_FUNC(int, pthreadZucondZusignalZAZa, // pthread_cond_signal@*
   1315               pthread_cond_t* cond)
   1316 {
   1317   return pthread_cond_signal_WRK(cond);
   1318 }
   1319 
   1320 // pthread_cond_broadcast
   1321 // Note, this is pretty much identical, from a dependency-graph
   1322 // point of view, with cond_signal, so the code is duplicated.
   1323 // Maybe it should be commoned up.
   1324 static int pthread_cond_broadcast_WRK(pthread_cond_t* cond)
   1325 {
   1326    int ret;
   1327    OrigFn fn;
   1328    pthread_lib_enter();
   1329    VALGRIND_GET_ORIG_FN(fn);
   1330 
   1331    if (TRACE_PTH_FNS) {
   1332       fprintf(stderr, "<< pthread_broadcast_signal %p", cond);
   1333       fflush(stderr);
   1334    }
   1335 
   1336    DO_CREQ_v_W(TSREQ_SIGNAL,
   1337                pthread_cond_t*,cond);
   1338 
   1339    CALL_FN_W_W(ret, fn, cond);
   1340 
   1341    if (ret != 0) {
   1342       DO_PthAPIerror( "pthread_cond_broadcast", ret );
   1343    }
   1344 
   1345    if (TRACE_PTH_FNS) {
   1346       fprintf(stderr, " cobro -> %d >>\n", ret);
   1347    }
   1348 
   1349    pthread_lib_exit();
   1350    return ret;
   1351 }
   1352 
   1353 PTH_FUNC(int, pthreadZucondZubroadcast, // pthread_cond_broadcast
   1354               pthread_cond_t* cond)
   1355 {
   1356   return pthread_cond_broadcast_WRK(cond);
   1357 }
   1358 
   1359 PTH_FUNC(int, pthreadZucondZubroadcastZAZa, // pthread_cond_broadcast@*
   1360               pthread_cond_t* cond)
   1361 {
   1362   return pthread_cond_broadcast_WRK(cond);
   1363 }
   1364 
   1365 static void do_wait(void *cv) {
   1366   DO_CREQ_v_W(TSREQ_WAIT, void *, cv);
   1367 }
   1368 
   1369 /*----------------------------------------------------------------*/
   1370 /*--- pthread_barrier_t functions                              ---*/
   1371 /*----------------------------------------------------------------*/
   1372 #if defined(VGO_darwin) || defined(ANDROID)
   1373 typedef void pthread_barrier_t;
   1374 #endif
   1375 // pthread_barrier_wait
   1376 static int pthread_barrier_wait_WRK(pthread_barrier_t* b)
   1377 {
   1378    int ret;
   1379    OrigFn fn;
   1380    VALGRIND_GET_ORIG_FN(fn);
   1381 
   1382    if (TRACE_PTH_FNS) {
   1383       fprintf(stderr, "<< pthread_barrier_wait %p", b);
   1384       fflush(stderr);
   1385    }
   1386 
   1387    DO_CREQ_v_W(TSREQ_CYCLIC_BARRIER_WAIT_BEFORE, void*,b);
   1388    CALL_FN_W_W(ret, fn, b);
   1389    DO_CREQ_v_W(TSREQ_CYCLIC_BARRIER_WAIT_AFTER, void*,b);
   1390 
   1391    // FIXME: handle ret
   1392    if (TRACE_PTH_FNS) {
   1393       fprintf(stderr, "  pthread_barrier_wait -> %d >>\n", ret);
   1394    }
   1395 
   1396    return ret;
   1397 }
   1398 
   1399 PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait
   1400               pthread_barrier_t* b)
   1401 {
   1402   return pthread_barrier_wait_WRK(b);
   1403 }
   1404 
   1405 // pthread_barrier_init
   1406 PTH_FUNC(int, pthreadZubarrierZuinit, void *b, void *a, unsigned n) {
   1407    int ret;
   1408    OrigFn fn;
   1409    VALGRIND_GET_ORIG_FN(fn);
   1410    DO_CREQ_v_WW(TSREQ_CYCLIC_BARRIER_INIT, void*,b, unsigned long, n);
   1411    CALL_FN_W_WWW(ret, fn, b, a, n);
   1412    return ret;
   1413 }
   1414 /*----------------------------------------------------------------*/
   1415 /*--- pthread_rwlock_t functions                               ---*/
   1416 /*----------------------------------------------------------------*/
   1417 
   1418 /* Handled:   pthread_rwlock_init pthread_rwlock_destroy
   1419               pthread_rwlock_rdlock
   1420               pthread_rwlock_wrlock
   1421               pthread_rwlock_unlock
   1422 
   1423    Unhandled: pthread_rwlock_timedrdlock
   1424               pthread_rwlock_tryrdlock
   1425 
   1426               pthread_rwlock_timedwrlock
   1427               pthread_rwlock_trywrlock
   1428 */
   1429 
   1430 // pthread_rwlock_init
   1431 static int pthread_rwlock_init_WRK(pthread_rwlock_t *rwl,
   1432                                    pthread_rwlockattr_t* attr)
   1433 {
   1434    int    ret;
   1435    OrigFn fn;
   1436    VALGRIND_GET_ORIG_FN(fn);
   1437    if (TRACE_PTH_FNS) {
   1438       fprintf(stderr, "<< pthread_rwl_init %p", rwl); fflush(stderr);
   1439    }
   1440 
   1441    CALL_FN_W_WW(ret, fn, rwl,attr);
   1442 
   1443    if (ret == 0 /*success*/) {
   1444       DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_CREATE_POST,
   1445                   pthread_rwlock_t*,rwl);
   1446    } else {
   1447       DO_PthAPIerror( "pthread_rwlock_init", ret );
   1448    }
   1449 
   1450    if (TRACE_PTH_FNS) {
   1451       fprintf(stderr, " :: rwl_init -> %d >>\n", ret);
   1452    }
   1453    return ret;
   1454 }
   1455 
   1456 PTH_FUNC(int, pthreadZurwlockZuinit, // pthread_rwlock_init
   1457               pthread_rwlock_t *rwl,
   1458               pthread_rwlockattr_t* attr)
   1459 {
   1460   return pthread_rwlock_init_WRK(rwl, attr);
   1461 }
   1462 
   1463 PTH_FUNC(int, pthreadZurwlockZuinit$Za, // pthread_rwlock_init$*
   1464               pthread_rwlock_t *rwl,
   1465               pthread_rwlockattr_t* attr)
   1466 {
   1467   return pthread_rwlock_init_WRK(rwl, attr);
   1468 }
   1469 
   1470 // pthread_rwlock_destroy
   1471 static int pthread_rwlock_destroy_WRK( pthread_rwlock_t *rwl)
   1472 {
   1473    int    ret;
   1474    OrigFn fn;
   1475    VALGRIND_GET_ORIG_FN(fn);
   1476    if (TRACE_PTH_FNS) {
   1477       fprintf(stderr, "<< pthread_rwl_destroy %p", rwl); fflush(stderr);
   1478    }
   1479 
   1480    DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_DESTROY_PRE,
   1481                pthread_rwlock_t*,rwl);
   1482 
   1483    CALL_FN_W_W(ret, fn, rwl);
   1484 
   1485    if (ret != 0) {
   1486       DO_PthAPIerror( "pthread_rwlock_destroy", ret );
   1487    }
   1488 
   1489    if (TRACE_PTH_FNS) {
   1490       fprintf(stderr, " :: rwl_destroy -> %d >>\n", ret);
   1491    }
   1492    return ret;
   1493 }
   1494 
   1495 PTH_FUNC(int, pthreadZurwlockZudestroy, // pthread_rwlock_destroy
   1496               pthread_rwlock_t *rwl)
   1497 {
   1498   return pthread_rwlock_destroy_WRK(rwl);
   1499 }
   1500 
   1501 PTH_FUNC(int, pthreadZurwlockZudestroy$Za, // pthread_rwlock_destroy$*
   1502               pthread_rwlock_t *rwl)
   1503 {
   1504   return pthread_rwlock_destroy_WRK(rwl);
   1505 }
   1506 
   1507 
   1508 // pthread_rwlock_wrlock
   1509 static int pthread_rwlock_wrlock_WRK(pthread_rwlock_t* rwlock)
   1510 {
   1511    int    ret;
   1512    OrigFn fn;
   1513    VALGRIND_GET_ORIG_FN(fn);
   1514    if (TRACE_PTH_FNS) {
   1515       fprintf(stderr, "<< pthread_rwl_wlk %p", rwlock); fflush(stderr);
   1516    }
   1517 
   1518 
   1519    IGNORE_ALL_SYNC_BEGIN();
   1520    CALL_FN_W_W(ret, fn, rwlock);
   1521    IGNORE_ALL_SYNC_END();
   1522 
   1523    if (ret == 0 /*success*/) {
   1524       DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST,
   1525                    pthread_rwlock_t*,rwlock, long,1/*isW*/);
   1526    } else {
   1527       DO_PthAPIerror( "pthread_rwlock_wrlock", ret );
   1528    }
   1529 
   1530    if (TRACE_PTH_FNS) {
   1531       fprintf(stderr, " :: rwl_wlk -> %d >>\n", ret);
   1532    }
   1533    return ret;
   1534 }
   1535 
   1536 PTH_FUNC(int, pthreadZurwlockZuwrlock, // pthread_rwlock_wrlock
   1537 	 pthread_rwlock_t* rwlock)
   1538 {
   1539   return pthread_rwlock_wrlock_WRK(rwlock);
   1540 }
   1541 
   1542 PTH_FUNC(int, pthreadZurwlockZuwrlock$Za, // pthread_rwlock_wrlock$*
   1543 	 pthread_rwlock_t* rwlock)
   1544 {
   1545   return pthread_rwlock_wrlock_WRK(rwlock);
   1546 }
   1547 
   1548 // pthread_rwlock_rdlock
   1549 static int pthread_rwlock_rdlock_WRK(pthread_rwlock_t* rwlock)
   1550 {
   1551    int    ret;
   1552    OrigFn fn;
   1553    VALGRIND_GET_ORIG_FN(fn);
   1554    if (TRACE_PTH_FNS) {
   1555       fprintf(stderr, "<< pthread_rwl_rlk %p", rwlock); fflush(stderr);
   1556    }
   1557 
   1558    IGNORE_ALL_SYNC_BEGIN();
   1559    CALL_FN_W_W(ret, fn, rwlock);
   1560    IGNORE_ALL_SYNC_END();
   1561 
   1562    if (ret == 0 /*success*/) {
   1563       DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST,
   1564                    pthread_rwlock_t*,rwlock, long,0/*!isW*/);
   1565    } else {
   1566       DO_PthAPIerror( "pthread_rwlock_rdlock", ret );
   1567    }
   1568 
   1569    if (TRACE_PTH_FNS) {
   1570       fprintf(stderr, " :: rwl_rlk -> %d >>\n", ret);
   1571    }
   1572    return ret;
   1573 }
   1574 
   1575 PTH_FUNC(int, pthreadZurwlockZurdlock, // pthread_rwlock_rdlock
   1576 	 pthread_rwlock_t* rwlock)
   1577 {
   1578   return pthread_rwlock_rdlock_WRK(rwlock);
   1579 }
   1580 
   1581 PTH_FUNC(int, pthreadZurwlockZurdlock$Za, // pthread_rwlock_rdlock$*
   1582 	 pthread_rwlock_t* rwlock)
   1583 {
   1584   return pthread_rwlock_rdlock_WRK(rwlock);
   1585 }
   1586 
   1587 // pthread_rwlock_trywrlock
   1588 static int pthread_rwlock_trywrlock_WRK(pthread_rwlock_t* rwlock)
   1589 {
   1590    int    ret;
   1591    OrigFn fn;
   1592    VALGRIND_GET_ORIG_FN(fn);
   1593    if (TRACE_PTH_FNS) {
   1594       fprintf(stderr, "<< pthread_rwl_trywlk %p", rwlock); fflush(stderr);
   1595    }
   1596 
   1597    IGNORE_ALL_SYNC_BEGIN();
   1598    CALL_FN_W_W(ret, fn, rwlock);
   1599    IGNORE_ALL_SYNC_END();
   1600 
   1601    /* There's a hole here: libpthread now knows the lock is locked,
   1602       but the tool doesn't, so some other thread could run and detect
   1603       that the lock has been acquired by someone (this thread).  Does
   1604       this matter?  Not sure, but I don't think so. */
   1605 
   1606    if (ret == 0 /*success*/) {
   1607       DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST,
   1608                    pthread_rwlock_t*,rwlock, long,1/*isW*/);
   1609    } else {
   1610       if (ret != EBUSY)
   1611          DO_PthAPIerror( "pthread_rwlock_trywrlock", ret );
   1612    }
   1613 
   1614    if (TRACE_PTH_FNS) {
   1615       fprintf(stderr, " :: rwl_trywlk -> %d >>\n", ret);
   1616    }
   1617    return ret;
   1618 }
   1619 
   1620 PTH_FUNC(int, pthreadZurwlockZutrywrlock, // pthread_rwlock_trywrlock
   1621 	 pthread_rwlock_t* rwlock)
   1622 {
   1623   return pthread_rwlock_trywrlock_WRK(rwlock);
   1624 }
   1625 
   1626 PTH_FUNC(int, pthreadZurwlockZutrywrlock$Za, // pthread_rwlock_trywrlock$*
   1627 	 pthread_rwlock_t* rwlock)
   1628 {
   1629   return pthread_rwlock_trywrlock_WRK(rwlock);
   1630 }
   1631 
   1632 // pthread_rwlock_tryrdlock
   1633 static int pthread_rwlock_tryrdlock_WRK(pthread_rwlock_t* rwlock)
   1634 {
   1635    int    ret;
   1636    OrigFn fn;
   1637    VALGRIND_GET_ORIG_FN(fn);
   1638    if (TRACE_PTH_FNS) {
   1639       fprintf(stderr, "<< pthread_rwl_tryrlk %p", rwlock); fflush(stderr);
   1640    }
   1641 
   1642    IGNORE_ALL_SYNC_BEGIN();
   1643    CALL_FN_W_W(ret, fn, rwlock);
   1644    IGNORE_ALL_SYNC_END();
   1645 
   1646    /* There's a hole here: libpthread now knows the lock is locked,
   1647       but the tool doesn't, so some other thread could run and detect
   1648       that the lock has been acquired by someone (this thread).  Does
   1649       this matter?  Not sure, but I don't think so. */
   1650 
   1651    if (ret == 0 /*success*/) {
   1652       DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST,
   1653                    pthread_rwlock_t*,rwlock, long,0/*!isW*/);
   1654    } else {
   1655       if (ret != EBUSY)
   1656          DO_PthAPIerror( "pthread_rwlock_tryrdlock", ret );
   1657    }
   1658 
   1659    if (TRACE_PTH_FNS) {
   1660       fprintf(stderr, " :: rwl_tryrlk -> %d >>\n", ret);
   1661    }
   1662    return ret;
   1663 }
   1664 
   1665 PTH_FUNC(int, pthreadZurwlockZutryrdlock, // pthread_rwlock_tryrdlock
   1666 	 pthread_rwlock_t* rwlock)
   1667 {
   1668   return pthread_rwlock_tryrdlock_WRK(rwlock);
   1669 }
   1670 
   1671 PTH_FUNC(int, pthreadZurwlockZutryrdlock$Za, // pthread_rwlock_tryrdlock$*
   1672 	 pthread_rwlock_t* rwlock)
   1673 {
   1674   return pthread_rwlock_tryrdlock_WRK(rwlock);
   1675 }
   1676 
   1677 
   1678 // pthread_rwlock_unlock
   1679 static int pthread_rwlock_unlock_WRK(pthread_rwlock_t* rwlock)
   1680 {
   1681    int    ret;
   1682    OrigFn fn;
   1683    VALGRIND_GET_ORIG_FN(fn);
   1684    if (TRACE_PTH_FNS) {
   1685       fprintf(stderr, "<< pthread_rwl_unlk %p", rwlock); fflush(stderr);
   1686    }
   1687 
   1688    DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_UNLOCK_PRE,
   1689                pthread_rwlock_t*,rwlock);
   1690 
   1691    IGNORE_ALL_SYNC_BEGIN();
   1692    CALL_FN_W_W(ret, fn, rwlock);
   1693    IGNORE_ALL_SYNC_END();
   1694 
   1695    if (ret != 0 /*error*/) {
   1696       DO_PthAPIerror( "pthread_rwlock_unlock", ret );
   1697    }
   1698 
   1699    if (TRACE_PTH_FNS) {
   1700       fprintf(stderr, " :: rwl_unlk -> %d >>\n", ret);
   1701    }
   1702    return ret;
   1703 }
   1704 
   1705 PTH_FUNC(int, pthreadZurwlockZuunlock, // pthread_rwlock_unlock
   1706 	 pthread_rwlock_t* rwlock)
   1707 {
   1708   return pthread_rwlock_unlock_WRK(rwlock);
   1709 }
   1710 
   1711 PTH_FUNC(int, pthreadZurwlockZuunlock$Za, // pthread_rwlock_unlock$*
   1712 	 pthread_rwlock_t* rwlock)
   1713 {
   1714   return pthread_rwlock_unlock_WRK(rwlock);
   1715 }
   1716 
   1717 /*----------------------------------------------------------------*/
   1718 /*--- POSIX semaphores                                         ---*/
   1719 /*----------------------------------------------------------------*/
   1720 
   1721 #include <semaphore.h>
   1722 
   1723 #define TRACE_SEM_FNS 0
   1724 
   1725 /* Handled:
   1726      int sem_init(sem_t *sem, int pshared, unsigned value);
   1727      int sem_destroy(sem_t *sem);
   1728      int sem_wait(sem_t *sem);
   1729      int sem_post(sem_t *sem);
   1730      int sem_trywait(sem_t *sem);
   1731 
   1732    Unhandled:
   1733      int sem_timedwait(sem_t *restrict sem,
   1734                        const struct timespec *restrict abs_timeout);
   1735 */
   1736 
   1737 /* glibc-2.5 has sem_init@@GLIBC_2.2.5 (amd64-linux)
   1738              and sem_init@@GLIBC_2.1 (x86-linux): match sem_init@*
   1739    sem_init is not implemented for Darwin. */
   1740 PTH_FUNC(int, semZuinitZAZa, sem_t* sem, int pshared, unsigned long value)
   1741 {
   1742    OrigFn fn;
   1743    int    ret;
   1744    VALGRIND_GET_ORIG_FN(fn);
   1745 
   1746    if (TRACE_SEM_FNS) {
   1747       fprintf(stderr, "<< sem_init(%p,%d,%lu) ", sem,pshared,value);
   1748       fflush(stderr);
   1749    }
   1750 
   1751    CALL_FN_W_WWW(ret, fn, sem,pshared,value);
   1752 
   1753    if (ret == 0) {
   1754       DO_CREQ_v_WW(TSREQ_POSIX_SEM_INIT_POST,
   1755                    sem_t*, sem, unsigned long, value);
   1756    } else {
   1757       DO_PthAPIerror( "sem_init", errno );
   1758    }
   1759 
   1760    if (TRACE_SEM_FNS) {
   1761       fprintf(stderr, " sem_init -> %d >>\n", ret);
   1762       fflush(stderr);
   1763    }
   1764 
   1765    return ret;
   1766 }
   1767 
   1768 
   1769 static int sem_destroy_WRK(sem_t* sem)
   1770 {
   1771    OrigFn fn;
   1772    int    ret;
   1773    VALGRIND_GET_ORIG_FN(fn);
   1774 
   1775    if (TRACE_SEM_FNS) {
   1776       fprintf(stderr, "<< sem_destroy(%p) ", sem);
   1777       fflush(stderr);
   1778    }
   1779 
   1780    DO_CREQ_v_W(TSREQ_POSIX_SEM_DESTROY_PRE, sem_t*, sem);
   1781 
   1782    CALL_FN_W_W(ret, fn, sem);
   1783 
   1784    if (ret != 0) {
   1785       DO_PthAPIerror( "sem_destroy", errno );
   1786    }
   1787 
   1788    if (TRACE_SEM_FNS) {
   1789       fprintf(stderr, " sem_destroy -> %d >>\n", ret);
   1790       fflush(stderr);
   1791    }
   1792 
   1793    return ret;
   1794 }
   1795 
   1796 /* glibc-2.5 has sem_destroy@@GLIBC_2.2.5 (amd64-linux)
   1797              and sem_destroy@@GLIBC_2.1 (x86-linux); match sem_destroy@* */
   1798 PTH_FUNC(int, semZudestroyZAZa, sem_t* sem)
   1799 {
   1800   return sem_destroy_WRK(sem);
   1801 }
   1802 
   1803 // Darwin has sem_destroy.
   1804 PTH_FUNC(int, semZudestroy, sem_t* sem)
   1805 {
   1806   return sem_destroy_WRK(sem);
   1807 }
   1808 
   1809 /* glibc-2.5 has sem_wait (amd64-linux); match sem_wait
   1810              and sem_wait@@GLIBC_2.1 (x86-linux); match sem_wait@* */
   1811 /* wait: decrement semaphore - acquire lockage */
   1812 static int sem_wait_WRK(sem_t* sem, const char *name, int is_try)
   1813 {
   1814    OrigFn fn;
   1815    int    ret;
   1816    VALGRIND_GET_ORIG_FN(fn);
   1817 
   1818    if (TRACE_SEM_FNS) {
   1819       fprintf(stderr, "<< %s(%p) ", name, sem);
   1820       fflush(stderr);
   1821    }
   1822 
   1823    CALL_FN_W_W(ret, fn, sem);
   1824 
   1825    if (ret == 0) {
   1826       DO_CREQ_v_W(TSREQ_WAIT, sem_t*,sem);
   1827    } else {
   1828       if (!is_try) {
   1829          DO_PthAPIerror( name, errno );
   1830       }
   1831    }
   1832 
   1833    if (TRACE_SEM_FNS) {
   1834       fprintf(stderr, " %s -> %d >>\n", name, ret);
   1835       fflush(stderr);
   1836    }
   1837 
   1838    return ret;
   1839 }
   1840 PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */
   1841    return sem_wait_WRK(sem, "sem_wait", 0);
   1842 }
   1843 PTH_FUNC(int, semZuwaitZAZa, sem_t* sem) { /* sem_wait@* */
   1844    return sem_wait_WRK(sem, "sem_wait", 0);
   1845 }
   1846 PTH_FUNC(int, semZuwait$Za, sem_t* sem) { /* sem_wait$* */
   1847    return sem_wait_WRK(sem, "sem_wait", 0);
   1848 }
   1849 PTH_FUNC(int, semZutrywait, sem_t* sem) { /* sem_trywait */
   1850    return sem_wait_WRK(sem, "sem_trywait", 1);
   1851 }
   1852 PTH_FUNC(int, semZutrywaitZAZa, sem_t* sem) { /* sem_trywait@* */
   1853    return sem_wait_WRK(sem, "sem_trywait", 1);
   1854 }
   1855 PTH_FUNC(int, semZutrywait$Za, sem_t* sem) { /* sem_trywait$* */
   1856    return sem_wait_WRK(sem, "sem_trywait", 1);
   1857 }
   1858 
   1859 
   1860 
   1861 
   1862 /* glibc-2.5 has sem_post (amd64-linux); match sem_post
   1863              and sem_post@@GLIBC_2.1 (x86-linux); match sem_post@* */
   1864 /* post: increment semaphore - release lockage */
   1865 static int sem_post_WRK(OrigFn fn, sem_t* sem)
   1866 {
   1867    int    ret;
   1868 
   1869 
   1870    if (TRACE_SEM_FNS) {
   1871       fprintf(stderr, "<< sem_post(%p) ", sem);
   1872       fflush(stderr);
   1873    }
   1874 
   1875    DO_CREQ_v_W(TSREQ_SIGNAL, sem_t*,sem);
   1876 
   1877    CALL_FN_W_W(ret, fn, sem);
   1878 
   1879    if (ret != 0) {
   1880       DO_PthAPIerror( "sem_post", errno );
   1881    }
   1882 
   1883    if (TRACE_SEM_FNS) {
   1884       fprintf(stderr, " sem_post -> %d >>\n", ret);
   1885       fflush(stderr);
   1886    }
   1887 
   1888    return ret;
   1889 }
   1890 PTH_FUNC(int, semZupost, sem_t* sem) { /* sem_post */
   1891    OrigFn fn;
   1892    VALGRIND_GET_ORIG_FN(fn);
   1893    return sem_post_WRK(fn, sem);
   1894 }
   1895 PTH_FUNC(int, semZupostZAZa, sem_t* sem) { /* sem_post@* */
   1896    OrigFn fn;
   1897    VALGRIND_GET_ORIG_FN(fn);
   1898    return sem_post_WRK(fn, sem);
   1899 }
   1900 PTH_FUNC(int, semZupost$Za, sem_t* sem) { /* sem_post$* */
   1901    OrigFn fn;
   1902    VALGRIND_GET_ORIG_FN(fn);
   1903    return sem_post_WRK(fn, sem);
   1904 }
   1905 
   1906 /* From man page:
   1907    sem_t *sem_open(const char *name, int oflag, ...);
   1908    ...
   1909    The oflag argument controls whether the semaphore is created or merely
   1910    accessed by the call to sem_open(). The following flag bits may be
   1911    set in oflag:
   1912    ...
   1913    If O_CREAT is set and the semaphore already exists, then O_CREAT has no
   1914    effect, except as noted under O_EXCL. Otherwise, sem_open() creates a
   1915    named semaphore. The O_CREAT flag requires a third and a fourth
   1916    argument: mode, which is of type mode_t, and value, which is of
   1917    type unsigned int. The semaphore is created with an initial value of value.
   1918 */
   1919 static sem_t *sem_open_WRK(OrigFn fn,
   1920                            const char *name, int oflag,
   1921                            mode_t mode, unsigned int value) {
   1922 
   1923    sem_t *ret;
   1924    CALL_FN_W_WWWW(ret, fn, name, oflag, mode, value);
   1925    if ((oflag & O_CREAT) &&
   1926        value > 0 &&
   1927        ret != SEM_FAILED) {
   1928      // This semaphore has been created with a non-zero value.
   1929      // The semaphore is initialized only on the first call to sem_open,
   1930      // next call will return an existing semaphore.
   1931      // Ideally, we need to handle it like sem_init with a non-zero value.
   1932      // But in such case we also need to handle sem_unlink.
   1933      //
   1934      // To avoid this complexity we simply do a SIGNAL here.
   1935      DO_CREQ_v_W(TSREQ_SIGNAL, sem_t*, ret);
   1936    }
   1937    return ret;
   1938 }
   1939 
   1940 PTH_FUNC(sem_t *, semZuopen, const char *name, int oflag,
   1941          mode_t mode, unsigned int value) { /* sem_open */
   1942    OrigFn fn;
   1943    VALGRIND_GET_ORIG_FN(fn);
   1944    return sem_open_WRK(fn, name, oflag, mode, value);
   1945 }
   1946 
   1947 PTH_FUNC(sem_t *, semZuopenZAZa, const char *name, int oflag,
   1948          mode_t mode, unsigned int value) { /* sem_open@* */
   1949    OrigFn fn;
   1950    VALGRIND_GET_ORIG_FN(fn);
   1951    return sem_open_WRK(fn, name, oflag, mode, value);
   1952 }
   1953 
   1954 
   1955 // atexit -> exit create a h-b arc.
   1956 static void *AtExitMagic(void) {
   1957   return (void*)0x12345678;
   1958 }
   1959 
   1960 #define ATEXIT_BODY { \
   1961    OrigFn fn;\
   1962    long    ret;\
   1963    VALGRIND_GET_ORIG_FN(fn);\
   1964    CALL_FN_W_W(ret, fn, callback);\
   1965    DO_CREQ_v_W(TSREQ_SIGNAL, void*, AtExitMagic());\
   1966    return ret;\
   1967 }\
   1968 
   1969 NONE_FUNC(long, atexit, void *callback)  ATEXIT_BODY
   1970 LIBC_FUNC(long, atexit, void *callback)  ATEXIT_BODY
   1971 
   1972 #define EXIT_BODY { \
   1973    OrigFn fn;\
   1974    VALGRIND_GET_ORIG_FN(fn);\
   1975    do_wait(AtExitMagic());\
   1976    CALL_FN_v_W(fn, x);\
   1977 }\
   1978 
   1979 LIBC_FUNC(void, exit, int x) EXIT_BODY
   1980 NONE_FUNC(void, exit, int x) EXIT_BODY
   1981 
   1982 // socket/file IO that creates happens-before arcs.
   1983 static void *SocketMagic(long s) {
   1984   return (void*)0xDEADFBAD;
   1985 }
   1986 
   1987 LIBC_FUNC(int, epoll_wait, int epfd, void * events, int maxevents, int timeout) {
   1988    OrigFn fn;
   1989    long    ret;
   1990    void *o;
   1991    VALGRIND_GET_ORIG_FN(fn);
   1992 //   fprintf(stderr, "T%d socket epoll_wait: %d\n", VALGRIND_TS_THREAD_ID(), epfd);
   1993    CALL_FN_W_WWWW(ret, fn, epfd, events, maxevents, timeout);
   1994    o = SocketMagic(epfd);
   1995    do_wait(o);
   1996    return ret;
   1997 }
   1998 
   1999 LIBC_FUNC(int, epoll_ctl, int epfd, int op, int fd, void *event) {
   2000    OrigFn fn;
   2001    long    ret;
   2002    void *o;
   2003    VALGRIND_GET_ORIG_FN(fn);
   2004 //   fprintf(stderr, "T%d socket epoll_ctl: %d\n", VALGRIND_TS_THREAD_ID(), epfd);
   2005    o = SocketMagic(epfd);
   2006    DO_CREQ_v_W(TSREQ_SIGNAL, void*, o);
   2007    CALL_FN_W_WWWW(ret, fn, epfd, op, fd, event);
   2008    return ret;
   2009 }
   2010 
   2011 PTH_FUNC(long, send, int s, void *buf, long len, int flags) {
   2012    OrigFn fn;
   2013    long    ret;
   2014    void *o;
   2015    VALGRIND_GET_ORIG_FN(fn);
   2016 //   fprintf(stderr, "T%d socket send: %d %ld\n", VALGRIND_TS_THREAD_ID(), s, len);
   2017    o = SocketMagic(s);
   2018    DO_CREQ_v_W(TSREQ_SIGNAL, void*, o);
   2019    CALL_FN_W_WWWW(ret, fn, s, buf, len, flags);
   2020    return ret;
   2021 }
   2022 
   2023 PTH_FUNC(long, sendmsg, int s, void *msg, int flags) {
   2024    OrigFn fn;
   2025    long    ret;
   2026    void *o;
   2027    VALGRIND_GET_ORIG_FN(fn);
   2028    o = SocketMagic(s);
   2029    DO_CREQ_v_W(TSREQ_SIGNAL, void*, o);
   2030    CALL_FN_W_WWW(ret, fn, s, msg, flags);
   2031    return ret;
   2032 }
   2033 
   2034 // TODO(timurrrr): sendto
   2035 
   2036 PTH_FUNC(long, recv, int s, void *buf, long len, int flags) {
   2037    OrigFn fn;
   2038    long    ret;
   2039    void *o;
   2040    VALGRIND_GET_ORIG_FN(fn);
   2041    CALL_FN_W_WWWW(ret, fn, s, buf, len, flags);
   2042 //   fprintf(stderr, "T%d socket recv: %d %ld %ld\n", VALGRIND_TS_THREAD_ID(), s, len, ret);
   2043    o = SocketMagic(s);
   2044    if (ret >= 0) {
   2045       // Do client request only if we received something
   2046       // or the connection was closed.
   2047       do_wait(o);
   2048    }
   2049    return ret;
   2050 }
   2051 
   2052 PTH_FUNC(long, recvmsg, int s, void *msg, int flags) {
   2053    OrigFn fn;
   2054    long    ret;
   2055    void *o;
   2056    VALGRIND_GET_ORIG_FN(fn);
   2057    CALL_FN_W_WWW(ret, fn, s, msg, flags);
   2058    o = SocketMagic(s);
   2059    if (ret >= 0) {
   2060       // Do client request only if we received something
   2061       // or the connection was closed.
   2062       do_wait(o);
   2063    }
   2064    return ret;
   2065 }
   2066 
   2067 // TODO(timurrrr): recvfrom
   2068 
   2069 PTH_FUNC(long, read, int s, void *a2, long count) {
   2070    OrigFn fn;
   2071    long    ret;
   2072    void *o;
   2073    VALGRIND_GET_ORIG_FN(fn);
   2074    CALL_FN_W_WWW(ret, fn, s, a2, count);
   2075 //   fprintf(stderr, "T%d socket read: %d %ld %ld\n", VALGRIND_TS_THREAD_ID(), s, count, ret);
   2076    o = SocketMagic(s);
   2077    if (ret >= 0) {
   2078       // Do client request only if we read something or the EOF was reached.
   2079       do_wait(o);
   2080    }
   2081    return ret;
   2082 }
   2083 
   2084 PTH_FUNC(long, write, int s, void *a2, long a3) {
   2085    OrigFn fn;
   2086    long    ret;
   2087    void *o;
   2088    VALGRIND_GET_ORIG_FN(fn);
   2089 //   fprintf(stderr, "T%d socket write: %d\n", VALGRIND_TS_THREAD_ID(), s);
   2090    o = SocketMagic(s);
   2091    DO_CREQ_v_W(TSREQ_SIGNAL, void*, o);
   2092    CALL_FN_W_WWW(ret, fn, s, a2, a3);
   2093    return ret;
   2094 }
   2095 
   2096 /* Linux: unlink
   2097  * Darwin: unlink */
   2098 LIBC_FUNC(long, unlink, void *path) {
   2099    OrigFn fn;
   2100    long    ret;
   2101    void *o;
   2102    VALGRIND_GET_ORIG_FN(fn);
   2103    o = SocketMagic((long)path);
   2104    DO_CREQ_v_W(TSREQ_SIGNAL, void*, o);
   2105    CALL_FN_W_W(ret, fn, path);
   2106    return ret;
   2107 }
   2108 
   2109 /* Linux: open
   2110  * Darwin: open$NOCANCEL$UNIX2003 */
   2111 static int open_WRK(void *path, int flags, int mode) {
   2112    OrigFn fn;
   2113    long    ret;
   2114    void *o;
   2115    VALGRIND_GET_ORIG_FN(fn);
   2116    o = SocketMagic((long)path);
   2117    DO_CREQ_v_W(TSREQ_SIGNAL, void*, o);
   2118    CALL_FN_W_WWW(ret, fn, path, flags, mode);
   2119    do_wait(o);
   2120    return ret;
   2121 }
   2122 
   2123 LIBC_FUNC(int, open, void *path, int flags, int mode) {
   2124   return open_WRK(path, flags, mode);
   2125 }
   2126 LIBC_FUNC(int, open$Za, void *path, int flags, int mode) {
   2127   return open_WRK(path, flags, mode);
   2128 }
   2129 
   2130 /* Linux: rmdir
   2131  * Darwin: rmdir */
   2132 LIBC_FUNC(int, rmdir, void *path) {
   2133    OrigFn fn;
   2134    long    ret;
   2135    void *o;
   2136    VALGRIND_GET_ORIG_FN(fn);
   2137    o = SocketMagic((long)path);
   2138    DO_CREQ_v_W(TSREQ_SIGNAL, void*, o);
   2139    CALL_FN_W_W(ret, fn, path);
   2140    return ret;
   2141 }
   2142 
   2143 /* Linux: opendir
   2144  * Darwin: opendir$UNIX2003 */
   2145 static long opendir_WRK(void *path) {
   2146    OrigFn fn;
   2147    long    ret;
   2148    void *o;
   2149    VALGRIND_GET_ORIG_FN(fn);
   2150    CALL_FN_W_W(ret, fn, path);
   2151    o = SocketMagic((long)path);
   2152    do_wait(o);
   2153    return ret;
   2154 }
   2155 
   2156 LIBC_FUNC(long, opendir, void *path) {
   2157   return opendir_WRK(path);
   2158 }
   2159 
   2160 LIBC_FUNC(long, opendir$Za, void *path) {
   2161   return opendir_WRK(path);
   2162 }
   2163 
   2164 #ifndef ANDROID
   2165 LIBC_FUNC(long, lockf, long fd, long cmd, OFF_T offset) {
   2166   // TODO: this doesn't support locking file subsections
   2167   const long offset_magic = 0xFEB0ACC0;
   2168   OrigFn fn;
   2169   long ret;
   2170   VALGRIND_GET_ORIG_FN(fn);
   2171   if (cmd == F_ULOCK)
   2172     DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_UNLOCK_PRE,
   2173                   long, fd ^ offset_magic);
   2174   CALL_FN_W_2WO_T(ret, fn, fd, cmd, offset);
   2175   if (cmd == F_LOCK && ret == 0)
   2176     DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST,
   2177                   long, fd ^ offset_magic,
   2178                   long, 1/*is_w*/);
   2179 
   2180   return ret;
   2181 }
   2182 #endif
   2183 
   2184 /*
   2185   Support for pthread_once and function-level static objects.
   2186 
   2187   pthread_once is supported by simply ignoring everything that happens
   2188   inside pthread_once.
   2189 
   2190   Another approach would be to SIGNAL when pthread_once with a given
   2191   pthread_once_t is called for the first time and to WAIT after
   2192   each pthread_once. But implementing this is a bit tricky and probably
   2193   not worth it.
   2194 
   2195   Thread safe initialization of function-level static objects is
   2196   supported in gcc (strarting from 4.something).
   2197   From gcc/cp/decl.c:
   2198   --------------------------------------------------------------
   2199        Emit code to perform this initialization but once.  This code
   2200        looks like:
   2201 
   2202        static <type> guard;
   2203        if (!guard.first_byte) {
   2204          if (__cxa_guard_acquire (&guard)) {
   2205            bool flag = false;
   2206            try {
   2207              // Do initialization.
   2208              flag = true; __cxa_guard_release (&guard);
   2209              // Register variable for destruction at end of program.
   2210             } catch {
   2211            if (!flag) __cxa_guard_abort (&guard);
   2212           }
   2213        }
   2214   --------------------------------------------------------------
   2215   So, when __cxa_guard_acquire returns true, we start ignoring all accesses
   2216   and in __cxa_guard_release we stop ignoring them.
   2217   We also need to ignore all accesses inside these two functions.
   2218 
   2219   For examples, see test106 and test108 at
   2220   http://code.google.com/p/data-race-test/source/browse/trunk/unittest/racecheck_unittest.cc
   2221 */
   2222 
   2223 PTH_FUNC(int, pthreadZuonce, void *ctl, void *rtn) {
   2224    OrigFn fn;
   2225    int    ret;
   2226    VALGRIND_GET_ORIG_FN(fn);
   2227    IGNORE_ALL_ACCESSES_BEGIN();
   2228    // fprintf(stderr, "T%d: ->pthread_once\n", VALGRIND_TS_THREAD_ID);
   2229    CALL_FN_W_WW(ret, fn, ctl, rtn);
   2230    // fprintf(stderr, "T%d: <-pthread_once\n", VALGRIND_TS_THREAD_ID);
   2231    IGNORE_ALL_ACCESSES_END();
   2232    return ret;
   2233 }
   2234 
   2235 LIBSTDCXX_FUNC(long, ZuZucxaZuguardZuacquire, void *p) {
   2236    OrigFn fn;
   2237    long    ret;
   2238    VALGRIND_GET_ORIG_FN(fn);
   2239    // fprintf(stderr, "T%d: ->__cxa_guard_acquire\n", VALGRIND_TS_THREAD_ID());
   2240    IGNORE_ALL_ACCESSES_BEGIN();
   2241    CALL_FN_W_W(ret, fn, p);
   2242    // fprintf(stderr, "T%d: <-__cxa_guard_acquire\n", VALGRIND_TS_THREAD_ID());
   2243    if (!ret) {
   2244      IGNORE_ALL_ACCESSES_END();
   2245    }
   2246    return ret;
   2247 }
   2248 LIBSTDCXX_FUNC(long, ZuZucxaZuguardZurelease, void *p) {
   2249    OrigFn fn;
   2250    long    ret;
   2251    VALGRIND_GET_ORIG_FN(fn);
   2252    // fprintf(stderr, "T%d: ->__cxa_guard_release\n", VALGRIND_TS_THREAD_ID());
   2253    CALL_FN_W_W(ret, fn, p);
   2254    // fprintf(stderr, "T%d: <-__cxa_guard_release\n", VALGRIND_TS_THREAD_ID());
   2255    IGNORE_ALL_ACCESSES_END();
   2256    return ret;
   2257 }
   2258 
   2259 
   2260 
   2261 
   2262 /*----------------------------------------------------------------*/
   2263 /*--- Replace glibc's wretched optimised string fns (again!)   ---*/
   2264 /*----------------------------------------------------------------*/
   2265 /* Why we have to do all this nonsense:
   2266 
   2267    Some implementations of strlen may read up to 7 bytes past the end
   2268    of the string thus touching memory which may not belong to this
   2269    string.
   2270 
   2271    Such race is benign because the data read past the end of the
   2272    string is not used.
   2273 */
   2274 // --- MEMCPY -----------------------------------------------------
   2275 //
   2276 #define MEMCPY(soname, fnname) \
   2277    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
   2278             ( void *dst, const void *src, SizeT len ); \
   2279    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
   2280             ( void *dst, const void *src, SizeT len ) \
   2281    { return Replace_memcpy(dst, src, len); }
   2282 
   2283 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
   2284 MEMCPY(NONE, memcpy)
   2285 /* icc9 blats these around all over the place.  Not only in the main
   2286    executable but various .so's.  They are highly tuned and read
   2287    memory beyond the source boundary (although work correctly and
   2288    never go across page boundaries), so give errors when run natively,
   2289    at least for misaligned source arg.  Just intercepting in the exe
   2290    only until we understand more about the problem.  See
   2291    http://bugs.kde.org/show_bug.cgi?id=139776
   2292  */
   2293 MEMCPY(NONE, _intel_fast_memcpy)
   2294 #if defined(VGO_linux)
   2295 MEMCPY(VG_Z_LIBC_SONAME, __GI_memcpy);
   2296 #endif
   2297 
   2298 // --- MEMMOVE -----------------------------------------------------
   2299 //
   2300 #define MEMMOVE(soname, fnname) \
   2301    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
   2302             ( void *dst, const void *src, SizeT len ); \
   2303    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
   2304             ( void *dst, const void *src, SizeT len ) \
   2305    { return Replace_memmove(dst, src, len); }
   2306 
   2307 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
   2308 MEMMOVE(NONE, memmove)
   2309 #if defined(VGO_linux)
   2310 MEMMOVE(VG_Z_LIBC_SONAME, __GI_memmove);
   2311 #endif
   2312 
   2313 
   2314 // --- STRCHR and INDEX -------------------------------------------
   2315 //
   2316 #define STRCHR(soname, fnname) \
   2317    char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
   2318    char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
   2319    { return Replace_strchr(s, c); }
   2320 
   2321 // Apparently index() is the same thing as strchr()
   2322 STRCHR(VG_Z_LIBC_SONAME, strchr)
   2323 STRCHR(VG_Z_LIBC_SONAME, index)
   2324 STRCHR(NONE,             strchr)
   2325 STRCHR(NONE,             index)
   2326 #if defined(VGO_linux)
   2327 STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
   2328 #endif
   2329 
   2330 // --- STRRCHR RINDEX -----------------------------------------------------
   2331 //
   2332 #define STRRCHR(soname, fnname) \
   2333    char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str, int c ); \
   2334    char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str, int c ) \
   2335    { return Replace_strrchr(str, c); }
   2336 
   2337 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
   2338 STRRCHR(VG_Z_LIBC_SONAME, rindex)
   2339 STRRCHR(NONE,             strrchr)
   2340 STRRCHR(NONE,             rindex)
   2341 #if defined(VGO_linux)
   2342 STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr)
   2343 #endif
   2344 
   2345 // --- STRCMP -----------------------------------------------------
   2346 //
   2347 #define STRCMP(soname, fnname) \
   2348    int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
   2349           ( const char* s1, const char* s2 ); \
   2350    int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
   2351           ( const char* s1, const char* s2 ) \
   2352    { return Replace_strcmp(s1, s2); }
   2353 
   2354 STRCMP(VG_Z_LIBC_SONAME, strcmp)
   2355 STRCMP(NONE,             strcmp)
   2356 #if defined(VGO_linux)
   2357 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
   2358 #endif
   2359 
   2360 #define MEMCMP(soname, fnname) \
   2361    int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
   2362           ( const char* s1, const char* s2 , size_t n); \
   2363    int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
   2364           ( const char* s1, const char* s2 , size_t n) \
   2365    { return Replace_memcmp(s1, s2, n); }
   2366 
   2367 MEMCMP(VG_Z_LIBC_SONAME, __memcmp_ssse3)
   2368 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
   2369 MEMCMP(NONE,             memcmp)
   2370 #if defined(VGO_linux)
   2371 MEMCMP(VG_Z_LIBC_SONAME, __GI_memcmp)
   2372 #endif
   2373 
   2374 #define MEMCHR(soname, fnname) \
   2375    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \
   2376    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \
   2377    { return Replace_memchr(s, c, n); }
   2378 
   2379 MEMCHR(VG_Z_LIBC_SONAME, memchr)
   2380 MEMCHR(NONE, memchr)
   2381 
   2382 #define STRNCMP(soname, fnname) \
   2383    int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
   2384           ( const char* s1, const char* s2, size_t n); \
   2385    int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
   2386           ( const char* s1, const char* s2, size_t n) \
   2387    { return Replace_strncmp(s1, s2, n); }
   2388 
   2389 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
   2390 STRNCMP(NONE,             strncmp)
   2391 #if defined(VGO_linux)
   2392 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
   2393 #endif
   2394 
   2395 // --- STRLEN -----------------------------------------------------
   2396 //
   2397 // Note that this replacement often doesn't get used because gcc inlines
   2398 // calls to strlen() with its own built-in version.  This can be very
   2399 // confusing if you aren't expecting it.  Other small functions in this file
   2400 // may also be inline by gcc.
   2401 #define STRLEN(soname, fnname) \
   2402    SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
   2403    SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
   2404    { return Replace_strlen(str); }
   2405 
   2406 STRLEN(VG_Z_LIBC_SONAME, strlen)
   2407 STRLEN(NONE,             strlen)
   2408 #if defined(VGO_linux)
   2409 STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
   2410 #endif
   2411 
   2412 // --- STRCPY -----------------------------------------------------
   2413 //
   2414 #define STRCPY(soname, fnname) \
   2415    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
   2416    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
   2417    { return Replace_strcpy(dst, src); }
   2418 
   2419 STRCPY(VG_Z_LIBC_SONAME, strcpy)
   2420 STRCPY(NONE,             strcpy)
   2421 #if defined(VGO_linux)
   2422 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
   2423 #endif
   2424 
   2425 // --- STRNCPY -----------------------------------------------------
   2426 //
   2427 #define STRNCPY(soname, fnname) \
   2428    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src, size_t n ); \
   2429    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src, size_t n ) \
   2430    { return Replace_strncpy(dst, src, n); }
   2431 
   2432 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
   2433 STRNCPY(NONE,             strncpy)
   2434 #if defined(VGO_linux)
   2435 STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
   2436 #endif
   2437 
   2438 // --- STRCAT -----------------------------------------------------
   2439 //
   2440 #define STRCAT(soname, fnname) \
   2441    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src); \
   2442    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src) \
   2443    { return Replace_strcat(dst, src); }
   2444 
   2445 STRCAT(VG_Z_LIBC_SONAME, strcat)
   2446 STRCAT(NONE,             strcat)
   2447 #if defined(VGO_linux)
   2448 STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
   2449 #endif
   2450 
   2451 // --- STPCPY -----------------------------------------------------
   2452 //
   2453 #define STPCPY(soname, fnname) \
   2454    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
   2455    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
   2456    { return Replace_stpcpy(dst, src); }
   2457 
   2458 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
   2459 STPCPY(NONE,             stpcpy)
   2460 #if defined(VGO_linux)
   2461 STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
   2462 #endif
   2463 
   2464 //------------------------ Annotations ---------------- {{{1
   2465 
   2466 
   2467 
   2468 #define ANN_FUNC(ret_ty, f, args...) \
   2469     ret_ty I_WRAP_SONAME_FNNAME_ZZ(Za,f)(args); \
   2470     ret_ty I_WRAP_SONAME_FNNAME_ZZ(Za,f)(args)
   2471 
   2472 
   2473 #define ANN_TRACE(args...) \
   2474     do{\
   2475       if(TRACE_ANN_FNS){\
   2476         int tid = VALGRIND_TS_THREAD_ID();\
   2477         int sid = VALGRIND_TS_SEGMENT_ID();\
   2478         fprintf(stderr, args);\
   2479         if(tid != 999999 && sid != 999999) fflush(stderr);\
   2480       }\
   2481     }while(0)
   2482 
   2483 ANN_FUNC(int, RunningOnValgrind, void) {
   2484   return 1;
   2485 }
   2486 
   2487 ANN_FUNC(const char *, ThreadSanitizerQuery, const char *query) {
   2488   Word res;
   2489   DO_CREQ_W_WW(res, TSREQ_THREAD_SANITIZER_QUERY, const char*, query, long, 0);
   2490   return (const char *)res;
   2491 }
   2492 
   2493 ANN_FUNC(void, AnnotateFlushState, const char *unused_file, int unused_line) {
   2494   DO_CREQ_v_v(TSREQ_FLUSH_STATE);
   2495 }
   2496 
   2497 ANN_FUNC(void, AnnotateRWLockCreate, const char *file, int line, void *lock)
   2498 {
   2499   const char *name = "AnnotateRWLockCreate";
   2500   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, lock, file, line);
   2501   DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_CREATE_POST, void*, lock, long, 0 /*non recur*/);
   2502 }
   2503 
   2504 ANN_FUNC(void, AnnotateRWLockDestroy, const char *file, int line, void *lock)
   2505 {
   2506   const char *name = "AnnotateRWLockDestroy";
   2507   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, lock, file, line);
   2508   DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_DESTROY_PRE, void*, lock);
   2509 }
   2510 
   2511 ANN_FUNC(void, AnnotateRWLockAcquired, const char *file, int line, void *lock, int is_w)
   2512 {
   2513   const char *name = "AnnotateRWLockAcquired";
   2514   ANN_TRACE("--#%d %s[%p] rw=%d %s:%d\n", tid, name, lock, is_w, file, line);
   2515   DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST,  void*,lock,long, (long)is_w);
   2516 }
   2517 
   2518 ANN_FUNC(void, AnnotateRWLockReleased, const char *file, int line, void *lock, int is_w)
   2519 {
   2520   const char *name = "AnnotateRWLockReleased";
   2521   ANN_TRACE("--#%d %s[%p] rw=%d %s:%d\n", tid, name, lock, is_w, file, line);
   2522   DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_UNLOCK_PRE, void*, lock);
   2523 }
   2524 
   2525 ANN_FUNC(void, AnnotateCondVarWait, const char *file, int line, void *cv, void *lock)
   2526 {
   2527   const char *name = "AnnotateCondVarWait";
   2528   ANN_TRACE("--#%d %s[%p|%p] %s:%d\n", tid, name, cv, lock, file, line);
   2529   do_wait(cv);
   2530 }
   2531 
   2532 ANN_FUNC(void, AnnotateCondVarSignal, const char *file, int line, void *cv)
   2533 {
   2534   const char *name = "AnnotateCondVarSignal";
   2535   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, cv, file, line);
   2536   DO_CREQ_v_W(TSREQ_SIGNAL, void*,cv);
   2537 }
   2538 
   2539 ANN_FUNC(void, AnnotateCondVarSignalAll, const char *file, int line, void *cv)
   2540 {
   2541   const char *name = "AnnotateCondVarSignalAll";
   2542   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, cv, file, line);
   2543   DO_CREQ_v_W(TSREQ_SIGNAL, void*,cv);
   2544 }
   2545 
   2546 ANN_FUNC(void, AnnotateHappensBefore, const char *file, int line, void *obj)
   2547 {
   2548   const char *name = "AnnotateHappensBefore";
   2549   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, obj, file, line);
   2550   DO_CREQ_v_W(TSREQ_SIGNAL, void*, obj);
   2551 }
   2552 
   2553 ANN_FUNC(void, WTFAnnotateHappensBefore, const char *file, int line, void *obj)
   2554 {
   2555   const char *name = "WTFAnnotateHappensBefore";
   2556   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, obj, file, line);
   2557   DO_CREQ_v_W(TSREQ_SIGNAL, void*, obj);
   2558 }
   2559 
   2560 ANN_FUNC(void, AnnotateHappensAfter, const char *file, int line, void *obj)
   2561 {
   2562   const char *name = "AnnotateHappensAfter";
   2563   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, obj, file, line);
   2564   do_wait(obj);
   2565 }
   2566 
   2567 ANN_FUNC(void, WTFAnnotateHappensAfter, const char *file, int line, void *obj)
   2568 {
   2569   const char *name = "WTFAnnotateHappensAfter";
   2570   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, obj, file, line);
   2571   do_wait(obj);
   2572 }
   2573 
   2574 ANN_FUNC(void, AnnotatePCQCreate, const char *file, int line, void *pcq)
   2575 {
   2576   const char *name = "AnnotatePCQCreate";
   2577   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, pcq, file, line);
   2578   DO_CREQ_v_W(TSREQ_PCQ_CREATE,   void*,pcq);
   2579 }
   2580 
   2581 ANN_FUNC(void, AnnotatePCQDestroy, const char *file, int line, void *pcq)
   2582 {
   2583   const char *name = "AnnotatePCQDestroy";
   2584   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, pcq, file, line);
   2585   DO_CREQ_v_W(TSREQ_PCQ_DESTROY,   void*,pcq);
   2586 }
   2587 
   2588 ANN_FUNC(void, AnnotatePCQPut, const char *file, int line, void *pcq)
   2589 {
   2590   const char *name = "AnnotatePCQPut";
   2591   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, pcq, file, line);
   2592   DO_CREQ_v_W(TSREQ_PCQ_PUT,   void*,pcq);
   2593 }
   2594 
   2595 ANN_FUNC(void, AnnotatePCQGet, const char *file, int line, void *pcq)
   2596 {
   2597   const char *name = "AnnotatePCQGet";
   2598   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, pcq, file, line);
   2599   DO_CREQ_v_W(TSREQ_PCQ_GET,   void*,pcq);
   2600 }
   2601 
   2602 ANN_FUNC(void, AnnotateExpectRace, const char *file, int line, void *mem, char *description)
   2603 {
   2604   const char *name = "AnnotateExpectRace";
   2605   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mem, file, line);
   2606   DO_CREQ_v_WWW(TSREQ_EXPECT_RACE, void*,mem, long, 1, char*,description);
   2607 }
   2608 
   2609 ANN_FUNC(void, AnnotateFlushExpectedRaces, const char *file, int line)
   2610 {
   2611   const char *name = __FUNCTION__;
   2612   ANN_TRACE("--#%d %s\n", tid, name);
   2613   DO_CREQ_v_v(TSREQ_FLUSH_EXPECTED_RACES);
   2614 }
   2615 
   2616 ANN_FUNC(void, AnnotateBenignRace, const char *file, int line, void *mem, char *description)
   2617 {
   2618   const char *name = "AnnotateBenignRace";
   2619   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mem, file, line);
   2620   DO_CREQ_v_WWW(TSREQ_BENIGN_RACE, void*,mem, long, 1, char*,description);
   2621 }
   2622 
   2623 ANN_FUNC(void, AnnotateBenignRaceSized, const char *file, int line, void *mem, long size, char *description)
   2624 {
   2625   const char *name = "AnnotateBenignRace";
   2626   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mem, file, line);
   2627   DO_CREQ_v_WWW(TSREQ_BENIGN_RACE, char*,(char*)mem, long, size,
   2628                 char*,description);
   2629 }
   2630 
   2631 ANN_FUNC(void, WTFAnnotateBenignRaceSized, const char *file, int line, void *mem, long size, char *description)
   2632 {
   2633   const char *name = "WTFAnnotateBenignRace";
   2634   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mem, file, line);
   2635   DO_CREQ_v_WWW(TSREQ_BENIGN_RACE, char*,(char*)mem, long, size,
   2636                 char*,description);
   2637 }
   2638 
   2639 
   2640 ANN_FUNC(void, AnnotateNewMemory, char *file, int line, void *mem, long size)
   2641 {
   2642   const char *name = "AnnotateNewMemory";
   2643   ANN_TRACE("--#%d %s[%p,%d] %s:%d\n", tid, name, mem, (int)size, file, line);
   2644   DO_CREQ_v_WWWW(TSREQ_CLEAN_MEMORY, void*,mem, long, size, char*, file, long, (long)line);
   2645 }
   2646 
   2647 ANN_FUNC(void, AnnotatePublishMemoryRange, char *file, int line, void *mem, long size)
   2648 {
   2649   const char *name = "AnnotatePublishMemoryRange";
   2650   ANN_TRACE("--#%d %s[%p,%d] %s:%d\n", tid, name, mem, (int)size, file, line);
   2651   DO_CREQ_v_WW(TSREQ_PUBLISH_MEMORY_RANGE,   void*, mem, long, size);
   2652 }
   2653 
   2654 ANN_FUNC(void, AnnotateUnpublishMemoryRange, char *file, int line, void *mem, long size)
   2655 {
   2656   const char *name = "AnnotateUnpublishMemoryRange";
   2657   ANN_TRACE("--#%d %s[%p,%d] %s:%d\n", tid, name, mem, (int)size, file, line);
   2658   DO_CREQ_v_WW(TSREQ_UNPUBLISH_MEMORY_RANGE,   void*, mem, long, size);
   2659 }
   2660 
   2661 ANN_FUNC(void, AnnotateIgnoreReadsBegin, char *file, int line, void *mu)
   2662 {
   2663   const char *name = "AnnotateIgnoreReadsBegin";
   2664   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line);
   2665   DO_CREQ_v_W(TSREQ_IGNORE_READS_BEGIN,   void*, mu);
   2666 }
   2667 
   2668 ANN_FUNC(void, AnnotateIgnoreReadsEnd, char *file, int line, void *mu)
   2669 {
   2670   const char *name = "AnnotateIgnoreReadsEnd";
   2671   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line);
   2672   DO_CREQ_v_W(TSREQ_IGNORE_READS_END,   void*, mu);
   2673 }
   2674 
   2675 ANN_FUNC(void, AnnotateIgnoreWritesBegin, char *file, int line, void *mu)
   2676 {
   2677   const char *name = "AnnotateIgnoreWritesBegin";
   2678   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line);
   2679   DO_CREQ_v_W(TSREQ_IGNORE_WRITES_BEGIN,   void*, mu);
   2680 }
   2681 
   2682 ANN_FUNC(void, AnnotateIgnoreWritesEnd, char *file, int line, void *mu)
   2683 {
   2684   const char *name = "AnnotateIgnoreWritesEnd";
   2685   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line);
   2686   DO_CREQ_v_W(TSREQ_IGNORE_WRITES_END,   void*, mu);
   2687 }
   2688 
   2689 ANN_FUNC(void, AnnotateIgnoreSyncBegin, char* file, int line, void *mu)
   2690 {
   2691   const char *name = "AnnotateIgnoreSyncBegin";
   2692   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line);
   2693   DO_CREQ_v_W(TSREQ_IGNORE_ALL_SYNC_BEGIN,  void*, mu);
   2694 }
   2695 
   2696 ANN_FUNC(void, AnnotateIgnoreSyncEnd, char* file, int line, void *mu)
   2697 {
   2698   const char *name = "AnnotateIgnoreSyncEnd";
   2699   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line);
   2700   DO_CREQ_v_W(TSREQ_IGNORE_ALL_SYNC_END,  void*, mu);
   2701 }
   2702 
   2703 ANN_FUNC(void, AnnotateEnableRaceDetection, char *file, int line, int enable)
   2704 {
   2705   const char *name = "AnnotateEnableRaceDetection";
   2706   ANN_TRACE("--#%d %s[%d] %s:%d\n", tid, name, enable, file, line);
   2707   DO_CREQ_v_W(enable == 0 ? TSREQ_GLOBAL_IGNORE_ON : TSREQ_GLOBAL_IGNORE_OFF,
   2708               long, 0);
   2709 }
   2710 
   2711 ANN_FUNC(void, AnnotateThreadName, char *file, int line, const char *thread_name)
   2712 {
   2713   const char *name = "AnnotateThreadName";
   2714   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, thread_name, file, line);
   2715   DO_CREQ_v_W(TSREQ_SET_THREAD_NAME, const char *, thread_name);
   2716 }
   2717 
   2718 ANN_FUNC(void, AnnotateMutexIsUsedAsCondVar, char *file, int line, void *mu)
   2719 {
   2720   const char *name = "AnnotateMutexIsUsedAsCondVar";
   2721   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line);
   2722   DO_CREQ_v_W(TSREQ_MUTEX_IS_USED_AS_CONDVAR,   void*, mu);
   2723 }
   2724 
   2725 ANN_FUNC(void, AnnotateMutexIsNotPHB, char *file, int line, void *mu)
   2726 {
   2727   const char *name = "AnnotateMutexIsNotPhb";
   2728   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line);
   2729   DO_CREQ_v_W(TSREQ_MUTEX_IS_NOT_PHB, void*, mu);
   2730 }
   2731 
   2732 ANN_FUNC(void, AnnotateTraceMemory, char *file, int line, void *mem)
   2733 {
   2734   const char *name = "AnnotateTraceMemory";
   2735   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mem, file, line);
   2736   DO_CREQ_v_W(TSREQ_TRACE_MEM,   void*, mem);
   2737 }
   2738 
   2739 #undef TRACE_ANN_FNS
   2740 #define TRACE_ANN_FNS 1
   2741 
   2742 ANN_FUNC(void, AnnotateNoOp, char *file, int line, void *mem)
   2743 {
   2744   const char *name = "AnnotateNoOp";
   2745   IGNORE_ALL_ACCESSES_BEGIN();
   2746   ANN_TRACE("--#%d/%d %s[%p] %s:%d\n", tid, sid, name, mem, file, line);
   2747   IGNORE_ALL_ACCESSES_END();
   2748 }
   2749 
   2750 ANN_FUNC(void, AnnotateSetVerbosity, char *file, int line, void *mem)
   2751 {
   2752   const char *name = "AnnotateSetVerbosity";
   2753   OrigFn fn;
   2754   VALGRIND_GET_ORIG_FN(fn);
   2755   fprintf(stderr, "%s fn=%p\n", name, (void*)fn.nraddr);
   2756   ANN_TRACE("--#%d/%d %s[%p] %s:%d\n", tid, sid, name, mem, file, line);
   2757 }
   2758 
   2759 
   2760 
   2761 //-------------- NaCl Support -------------- {{{1
   2762 // A bit hackish implementation of NaCl support.
   2763 // We need to notify the valgrind core about
   2764 //   a) nacl memory range
   2765 //   b) nacl .nexe file
   2766 #include "coregrind/pub_core_clreq.h"
   2767 void I_WRAP_SONAME_FNNAME_ZZ(NONE, StopForDebuggerInit) (void *arg);
   2768 void I_WRAP_SONAME_FNNAME_ZZ(NONE, StopForDebuggerInit) (void *arg) {
   2769   int res;
   2770   OrigFn fn;
   2771   VALGRIND_GET_ORIG_FN(fn);
   2772   CALL_FN_v_W(fn, arg);
   2773   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__NACL_MEM_START, arg, 0, 0, 0, 0);
   2774 }
   2775 
   2776 int I_WRAP_SONAME_FNNAME_ZZ(NONE, GioMemoryFileSnapshotCtor) (void *a, char *file);
   2777 int I_WRAP_SONAME_FNNAME_ZZ(NONE, GioMemoryFileSnapshotCtor) (void *a, char *file) {
   2778   int res;
   2779   OrigFn fn;
   2780   int ret;
   2781   VALGRIND_GET_ORIG_FN(fn);
   2782   CALL_FN_W_WW(ret, fn, a, file);
   2783   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__NACL_FILE, file, 0, 0, 0, 0);
   2784   return ret;
   2785 }
   2786 
   2787 //-------------- Functions to Ignore -------------- {{{1
   2788 // For some functions we want to ignore everything that happens
   2789 // after they were called and before they returned.
   2790 // Is there any way that allows to do this via a command line?
   2791 #define WRAP_AND_IGNORE(soname, fnname) \
   2792   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *a1, void *a2, void *a3, void *a4); \
   2793   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *a1, void *a2, void *a3, void *a4) { \
   2794     void* ret; \
   2795     OrigFn fn;\
   2796     VALGRIND_GET_ORIG_FN(fn);\
   2797     IGNORE_ALL_ACCESSES_BEGIN(); \
   2798       CALL_FN_W_WWWW(ret, fn, a1, a2, a3, a4); \
   2799     IGNORE_ALL_ACCESSES_END(); \
   2800     return ret; \
   2801   }
   2802 
   2803 WRAP_AND_IGNORE(NONE, getenv);
   2804 
   2805 // {{{1 end
   2806 // vim:shiftwidth=2:softtabstop=2:expandtab
   2807