• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@google.com
7   Copyright (C) 2007-2008 OpenWorks LLP
8       info@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 
VALGRIND_TS_THREAD_ID(void)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 
VALGRIND_VG_THREAD_ID(void)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 
VALGRIND_TS_SEGMENT_ID(void)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 
IGNORE_ALL_ACCESSES_BEGIN(void)199 static inline void IGNORE_ALL_ACCESSES_BEGIN(void) {
200    DO_CREQ_v_W(TSREQ_IGNORE_ALL_ACCESSES_BEGIN,  void*, NULL);
201 }
202 
IGNORE_ALL_ACCESSES_END(void)203 static inline void IGNORE_ALL_ACCESSES_END(void) {
204    DO_CREQ_v_W(TSREQ_IGNORE_ALL_ACCESSES_END,  void*, NULL);
205 }
206 
IGNORE_ALL_SYNC_BEGIN(void)207 static inline void IGNORE_ALL_SYNC_BEGIN(void) {
208    DO_CREQ_v_W(TSREQ_IGNORE_ALL_SYNC_BEGIN,  void*, NULL);
209 }
210 
IGNORE_ALL_SYNC_END(void)211 static inline void IGNORE_ALL_SYNC_END(void) {
212    DO_CREQ_v_W(TSREQ_IGNORE_ALL_SYNC_END,  void*, NULL);
213 }
214 
IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(void)215 static inline void IGNORE_ALL_ACCESSES_AND_SYNC_BEGIN(void) {
216   IGNORE_ALL_ACCESSES_BEGIN();
217   IGNORE_ALL_SYNC_BEGIN();
218 }
219 
IGNORE_ALL_ACCESSES_AND_SYNC_END(void)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);
I_WRAP_SONAME_FNNAME_ZU(VG_Z_LIBC_SONAME,fwrite)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);
I_WRAP_SONAME_FNNAME_ZU(VG_Z_LIBC_SONAME,puts)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) */
lame_strerror(long err)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.
pthread_lib_enter(void)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().
pthread_lib_exit(void)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 
ThreadSanitizerStartThread(void * xargsV)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 
pthread_create_WRK(pthread_t * thread,const pthread_attr_t * attr,void * (* start)(void *),void * arg)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 
PTH_FUNC(int,pthreadZucreate,pthread_t * thread,const pthread_attr_t * attr,void * (* start)(void *),void * arg)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 }
PTH_FUNC(int,pthreadZucreateZAZa,pthread_t * thread,const pthread_attr_t * attr,void * (* start)(void *),void * arg)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
pthread_join_WRK(pthread_t thread,void ** value_pointer)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 
PTH_FUNC(int,pthreadZujoin,pthread_t thread,void ** value_pointer)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 
PTH_FUNC(int,pthreadZujoin$Za,pthread_t thread,void ** value_pointer)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.
PTH_FUNC(int,pthreadZuexit,void * retval)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
PTH_FUNC(int,pthreadZumutexZuinit,pthread_mutex_t * mutex,pthread_mutexattr_t * attr)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
PTH_FUNC(int,pthreadZumutexZudestroy,pthread_mutex_t * mutex)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
PTH_FUNC(int,pthreadZumutexZulock,pthread_mutex_t * mutex)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.
pthread_mutex_trylock_WRK(pthread_mutex_t * mutex)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 
PTH_FUNC(int,pthreadZumutexZutrylock,pthread_mutex_t * mutex)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.
PTH_FUNC(int,pthreadZumutexZutimedlock,pthread_mutex_t * mutex,void * timeout)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
PTH_FUNC(int,pthreadZumutexZuunlock,pthread_mutex_t * mutex)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
PTH_FUNC(int,pthreadZuspinZuinit,void * lock,int pshared)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
PTH_FUNC(int,pthreadZuspinZudestroy,void * lock)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
PTH_FUNC(int,pthreadZuspinZulock,void * 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
PTH_FUNC(int,pthreadZuspinZutrylock,void * lock)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
PTH_FUNC(int,pthreadZuspinZuunlock,void * lock)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
pthread_cond_wait_WRK(pthread_cond_t * cond,pthread_mutex_t * mutex)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 
PTH_FUNC(int,pthreadZucondZuwaitZAZa,pthread_cond_t * cond,pthread_mutex_t * mutex)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 
PTH_FUNC(int,pthreadZucondZuwait$Za,pthread_cond_t * cond,pthread_mutex_t * mutex)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
pthread_cond_timedwait_WRK(pthread_cond_t * cond,pthread_mutex_t * mutex,struct timespec * abstime)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 
PTH_FUNC(int,pthreadZucondZutimedwaitZAZa,pthread_cond_t * cond,pthread_mutex_t * mutex,struct timespec * abstime)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 
PTH_FUNC(int,pthreadZucondZutimedwait$Za,pthread_cond_t * cond,pthread_mutex_t * mutex,struct timespec * abstime)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 
PTH_FUNC(int,pthreadZucondZutimedwaitZurelativeZunp,pthread_cond_t * cond,pthread_mutex_t * mutex,struct timespec * abstime)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
pthread_cond_signal_WRK(pthread_cond_t * cond)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 
PTH_FUNC(int,pthreadZucondZusignal,pthread_cond_t * cond)1308 PTH_FUNC(int, pthreadZucondZusignal, // pthread_cond_signal
1309               pthread_cond_t* cond)
1310 {
1311   return pthread_cond_signal_WRK(cond);
1312 }
1313 
PTH_FUNC(int,pthreadZucondZusignalZAZa,pthread_cond_t * cond)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.
pthread_cond_broadcast_WRK(pthread_cond_t * cond)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 
PTH_FUNC(int,pthreadZucondZubroadcast,pthread_cond_t * cond)1353 PTH_FUNC(int, pthreadZucondZubroadcast, // pthread_cond_broadcast
1354               pthread_cond_t* cond)
1355 {
1356   return pthread_cond_broadcast_WRK(cond);
1357 }
1358 
PTH_FUNC(int,pthreadZucondZubroadcastZAZa,pthread_cond_t * cond)1359 PTH_FUNC(int, pthreadZucondZubroadcastZAZa, // pthread_cond_broadcast@*
1360               pthread_cond_t* cond)
1361 {
1362   return pthread_cond_broadcast_WRK(cond);
1363 }
1364 
do_wait(void * cv)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
pthread_barrier_wait_WRK(pthread_barrier_t * b)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 
PTH_FUNC(int,pthreadZubarrierZuwait,pthread_barrier_t * b)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
PTH_FUNC(int,pthreadZubarrierZuinit,void * b,void * a,unsigned n)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
pthread_rwlock_init_WRK(pthread_rwlock_t * rwl,pthread_rwlockattr_t * attr)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 
PTH_FUNC(int,pthreadZurwlockZuinit,pthread_rwlock_t * rwl,pthread_rwlockattr_t * attr)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 
PTH_FUNC(int,pthreadZurwlockZuinit$Za,pthread_rwlock_t * rwl,pthread_rwlockattr_t * attr)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
pthread_rwlock_destroy_WRK(pthread_rwlock_t * rwl)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 
PTH_FUNC(int,pthreadZurwlockZudestroy,pthread_rwlock_t * rwl)1495 PTH_FUNC(int, pthreadZurwlockZudestroy, // pthread_rwlock_destroy
1496               pthread_rwlock_t *rwl)
1497 {
1498   return pthread_rwlock_destroy_WRK(rwl);
1499 }
1500 
PTH_FUNC(int,pthreadZurwlockZudestroy$Za,pthread_rwlock_t * rwl)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
pthread_rwlock_wrlock_WRK(pthread_rwlock_t * rwlock)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 
PTH_FUNC(int,pthreadZurwlockZuwrlock,pthread_rwlock_t * rwlock)1536 PTH_FUNC(int, pthreadZurwlockZuwrlock, // pthread_rwlock_wrlock
1537 	 pthread_rwlock_t* rwlock)
1538 {
1539   return pthread_rwlock_wrlock_WRK(rwlock);
1540 }
1541 
PTH_FUNC(int,pthreadZurwlockZuwrlock$Za,pthread_rwlock_t * rwlock)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
pthread_rwlock_rdlock_WRK(pthread_rwlock_t * rwlock)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 
PTH_FUNC(int,pthreadZurwlockZurdlock,pthread_rwlock_t * rwlock)1575 PTH_FUNC(int, pthreadZurwlockZurdlock, // pthread_rwlock_rdlock
1576 	 pthread_rwlock_t* rwlock)
1577 {
1578   return pthread_rwlock_rdlock_WRK(rwlock);
1579 }
1580 
PTH_FUNC(int,pthreadZurwlockZurdlock$Za,pthread_rwlock_t * rwlock)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
pthread_rwlock_trywrlock_WRK(pthread_rwlock_t * rwlock)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 
PTH_FUNC(int,pthreadZurwlockZutrywrlock,pthread_rwlock_t * rwlock)1620 PTH_FUNC(int, pthreadZurwlockZutrywrlock, // pthread_rwlock_trywrlock
1621 	 pthread_rwlock_t* rwlock)
1622 {
1623   return pthread_rwlock_trywrlock_WRK(rwlock);
1624 }
1625 
PTH_FUNC(int,pthreadZurwlockZutrywrlock$Za,pthread_rwlock_t * rwlock)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
pthread_rwlock_tryrdlock_WRK(pthread_rwlock_t * rwlock)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 
PTH_FUNC(int,pthreadZurwlockZutryrdlock,pthread_rwlock_t * rwlock)1665 PTH_FUNC(int, pthreadZurwlockZutryrdlock, // pthread_rwlock_tryrdlock
1666 	 pthread_rwlock_t* rwlock)
1667 {
1668   return pthread_rwlock_tryrdlock_WRK(rwlock);
1669 }
1670 
PTH_FUNC(int,pthreadZurwlockZutryrdlock$Za,pthread_rwlock_t * rwlock)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
pthread_rwlock_unlock_WRK(pthread_rwlock_t * rwlock)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 
PTH_FUNC(int,pthreadZurwlockZuunlock,pthread_rwlock_t * rwlock)1705 PTH_FUNC(int, pthreadZurwlockZuunlock, // pthread_rwlock_unlock
1706 	 pthread_rwlock_t* rwlock)
1707 {
1708   return pthread_rwlock_unlock_WRK(rwlock);
1709 }
1710 
PTH_FUNC(int,pthreadZurwlockZuunlock$Za,pthread_rwlock_t * rwlock)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. */
PTH_FUNC(int,semZuinitZAZa,sem_t * sem,int pshared,unsigned long value)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 
sem_destroy_WRK(sem_t * sem)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@* */
PTH_FUNC(int,semZudestroyZAZa,sem_t * sem)1798 PTH_FUNC(int, semZudestroyZAZa, sem_t* sem)
1799 {
1800   return sem_destroy_WRK(sem);
1801 }
1802 
1803 // Darwin has sem_destroy.
PTH_FUNC(int,semZudestroy,sem_t * sem)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 */
sem_wait_WRK(sem_t * sem,const char * name,int is_try)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 }
PTH_FUNC(int,semZuwait,sem_t * sem)1840 PTH_FUNC(int, semZuwait, sem_t* sem) { /* sem_wait */
1841    return sem_wait_WRK(sem, "sem_wait", 0);
1842 }
PTH_FUNC(int,semZuwaitZAZa,sem_t * sem)1843 PTH_FUNC(int, semZuwaitZAZa, sem_t* sem) { /* sem_wait@* */
1844    return sem_wait_WRK(sem, "sem_wait", 0);
1845 }
PTH_FUNC(int,semZuwait$Za,sem_t * sem)1846 PTH_FUNC(int, semZuwait$Za, sem_t* sem) { /* sem_wait$* */
1847    return sem_wait_WRK(sem, "sem_wait", 0);
1848 }
PTH_FUNC(int,semZutrywait,sem_t * sem)1849 PTH_FUNC(int, semZutrywait, sem_t* sem) { /* sem_trywait */
1850    return sem_wait_WRK(sem, "sem_trywait", 1);
1851 }
PTH_FUNC(int,semZutrywaitZAZa,sem_t * sem)1852 PTH_FUNC(int, semZutrywaitZAZa, sem_t* sem) { /* sem_trywait@* */
1853    return sem_wait_WRK(sem, "sem_trywait", 1);
1854 }
PTH_FUNC(int,semZutrywait$Za,sem_t * sem)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 */
sem_post_WRK(OrigFn fn,sem_t * sem)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 }
PTH_FUNC(int,semZupost,sem_t * sem)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 }
PTH_FUNC(int,semZupostZAZa,sem_t * sem)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 }
PTH_FUNC(int,semZupost$Za,sem_t * sem)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 */
sem_open_WRK(OrigFn fn,const char * name,int oflag,mode_t mode,unsigned int value)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 
PTH_FUNC(sem_t *,semZuopen,const char * name,int oflag,mode_t mode,unsigned int value)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 
PTH_FUNC(sem_t *,semZuopenZAZa,const char * name,int oflag,mode_t mode,unsigned int value)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.
AtExitMagic(void)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 
NONE_FUNC(long,atexit,void * callback)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 
LIBC_FUNC(int,epoll_wait,int epfd,void * events,int maxevents,int timeout)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 
LIBC_FUNC(int,epoll_ctl,int epfd,int op,int fd,void * event)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 
PTH_FUNC(long,send,int s,void * buf,long len,int flags)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 
PTH_FUNC(long,sendmsg,int s,void * msg,int flags)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 
PTH_FUNC(long,recv,int s,void * buf,long len,int flags)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 
PTH_FUNC(long,recvmsg,int s,void * msg,int flags)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 
PTH_FUNC(long,read,int s,void * a2,long count)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 
PTH_FUNC(long,write,int s,void * a2,long a3)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 */
LIBC_FUNC(long,unlink,void * path)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 */
open_WRK(void * path,int flags,int mode)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 
LIBC_FUNC(int,open,void * path,int flags,int mode)2123 LIBC_FUNC(int, open, void *path, int flags, int mode) {
2124   return open_WRK(path, flags, mode);
2125 }
LIBC_FUNC(int,open$Za,void * path,int flags,int mode)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 */
LIBC_FUNC(int,rmdir,void * path)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 */
opendir_WRK(void * path)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 
LIBC_FUNC(long,opendir,void * path)2156 LIBC_FUNC(long, opendir, void *path) {
2157   return opendir_WRK(path);
2158 }
2159 
LIBC_FUNC(long,opendir$Za,void * path)2160 LIBC_FUNC(long, opendir$Za, void *path) {
2161   return opendir_WRK(path);
2162 }
2163 
2164 #if !defined(ANDROID)
LIBC_FUNC(int,lockf,int fd,int cmd,OFF_T offset)2165 LIBC_FUNC(int, lockf, int fd, int cmd, OFF_T offset) {
2166   OrigFn fn;
2167   void *o;
2168   long ret;
2169   VALGRIND_GET_ORIG_FN(fn);
2170   o = SocketMagic(fd);
2171   if (cmd == F_ULOCK) {
2172     DO_CREQ_v_W(TSREQ_SIGNAL, void*, o);
2173   }
2174   CALL_FN_W_2WO_T(ret, fn, fd, cmd, offset);
2175   if (cmd == F_LOCK && ret == 0) {
2176     do_wait(o);
2177   }
2178   return ret;
2179 }
2180 #endif
2181 
2182 /*
2183   Support for pthread_once and function-level static objects.
2184 
2185   pthread_once is supported by simply ignoring everything that happens
2186   inside pthread_once.
2187 
2188   Another approach would be to SIGNAL when pthread_once with a given
2189   pthread_once_t is called for the first time and to WAIT after
2190   each pthread_once. But implementing this is a bit tricky and probably
2191   not worth it.
2192 
2193   Thread safe initialization of function-level static objects is
2194   supported in gcc (strarting from 4.something).
2195   From gcc/cp/decl.c:
2196   --------------------------------------------------------------
2197        Emit code to perform this initialization but once.  This code
2198        looks like:
2199 
2200        static <type> guard;
2201        if (!guard.first_byte) {
2202          if (__cxa_guard_acquire (&guard)) {
2203            bool flag = false;
2204            try {
2205              // Do initialization.
2206              flag = true; __cxa_guard_release (&guard);
2207              // Register variable for destruction at end of program.
2208             } catch {
2209            if (!flag) __cxa_guard_abort (&guard);
2210           }
2211        }
2212   --------------------------------------------------------------
2213   So, when __cxa_guard_acquire returns true, we start ignoring all accesses
2214   and in __cxa_guard_release we stop ignoring them.
2215   We also need to ignore all accesses inside these two functions.
2216 
2217   For examples, see test106 and test108 at
2218   http://code.google.com/p/data-race-test/source/browse/trunk/unittest/racecheck_unittest.cc
2219 */
2220 
PTH_FUNC(int,pthreadZuonce,void * ctl,void * rtn)2221 PTH_FUNC(int, pthreadZuonce, void *ctl, void *rtn) {
2222    OrigFn fn;
2223    int    ret;
2224    VALGRIND_GET_ORIG_FN(fn);
2225    IGNORE_ALL_ACCESSES_BEGIN();
2226    // fprintf(stderr, "T%d: ->pthread_once\n", VALGRIND_TS_THREAD_ID);
2227    CALL_FN_W_WW(ret, fn, ctl, rtn);
2228    // fprintf(stderr, "T%d: <-pthread_once\n", VALGRIND_TS_THREAD_ID);
2229    IGNORE_ALL_ACCESSES_END();
2230    return ret;
2231 }
2232 
LIBSTDCXX_FUNC(long,ZuZucxaZuguardZuacquire,void * p)2233 LIBSTDCXX_FUNC(long, ZuZucxaZuguardZuacquire, void *p) {
2234    OrigFn fn;
2235    long    ret;
2236    VALGRIND_GET_ORIG_FN(fn);
2237    // fprintf(stderr, "T%d: ->__cxa_guard_acquire\n", VALGRIND_TS_THREAD_ID());
2238    IGNORE_ALL_ACCESSES_BEGIN();
2239    CALL_FN_W_W(ret, fn, p);
2240    // fprintf(stderr, "T%d: <-__cxa_guard_acquire\n", VALGRIND_TS_THREAD_ID());
2241    if (!ret) {
2242      IGNORE_ALL_ACCESSES_END();
2243    }
2244    return ret;
2245 }
LIBSTDCXX_FUNC(long,ZuZucxaZuguardZurelease,void * p)2246 LIBSTDCXX_FUNC(long, ZuZucxaZuguardZurelease, void *p) {
2247    OrigFn fn;
2248    long    ret;
2249    VALGRIND_GET_ORIG_FN(fn);
2250    // fprintf(stderr, "T%d: ->__cxa_guard_release\n", VALGRIND_TS_THREAD_ID());
2251    CALL_FN_W_W(ret, fn, p);
2252    // fprintf(stderr, "T%d: <-__cxa_guard_release\n", VALGRIND_TS_THREAD_ID());
2253    IGNORE_ALL_ACCESSES_END();
2254    return ret;
2255 }
2256 
2257 
2258 
2259 
2260 /*----------------------------------------------------------------*/
2261 /*--- Replace glibc's wretched optimised string fns (again!)   ---*/
2262 /*----------------------------------------------------------------*/
2263 /* Why we have to do all this nonsense:
2264 
2265    Some implementations of strlen may read up to 7 bytes past the end
2266    of the string thus touching memory which may not belong to this
2267    string.
2268 
2269    Such race is benign because the data read past the end of the
2270    string is not used.
2271 */
2272 // --- MEMCPY -----------------------------------------------------
2273 //
2274 #define MEMCPY(soname, fnname) \
2275    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2276             ( void *dst, const void *src, SizeT len ); \
2277    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2278             ( void *dst, const void *src, SizeT len ) \
2279    { return Replace_memcpy(dst, src, len); }
2280 
2281 MEMCPY(VG_Z_LIBC_SONAME, memcpy)
2282 MEMCPY(NONE, memcpy)
2283 /* icc9 blats these around all over the place.  Not only in the main
2284    executable but various .so's.  They are highly tuned and read
2285    memory beyond the source boundary (although work correctly and
2286    never go across page boundaries), so give errors when run natively,
2287    at least for misaligned source arg.  Just intercepting in the exe
2288    only until we understand more about the problem.  See
2289    http://bugs.kde.org/show_bug.cgi?id=139776
2290  */
2291 MEMCPY(NONE, _intel_fast_memcpy)
2292 #if defined(VGO_linux)
2293 MEMCPY(VG_Z_LIBC_SONAME, __GI_memcpy);
2294 #endif
2295 
2296 // --- MEMMOVE -----------------------------------------------------
2297 //
2298 #define MEMMOVE(soname, fnname) \
2299    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2300             ( void *dst, const void *src, SizeT len ); \
2301    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2302             ( void *dst, const void *src, SizeT len ) \
2303    { return Replace_memmove(dst, src, len); }
2304 
2305 MEMMOVE(VG_Z_LIBC_SONAME, memmove)
2306 MEMMOVE(NONE, memmove)
2307 #if defined(VGO_linux)
2308 MEMMOVE(VG_Z_LIBC_SONAME, __GI_memmove);
2309 #endif
2310 
2311 
2312 // --- STRCHR and INDEX -------------------------------------------
2313 //
2314 #define STRCHR(soname, fnname) \
2315    char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
2316    char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
2317    { return Replace_strchr(s, c); }
2318 
2319 // Apparently index() is the same thing as strchr()
STRCHR(VG_Z_LIBC_SONAME,strchr)2320 STRCHR(VG_Z_LIBC_SONAME, strchr)
2321 STRCHR(VG_Z_LIBC_SONAME, index)
2322 STRCHR(NONE,             strchr)
2323 STRCHR(NONE,             index)
2324 #if defined(VGO_linux)
2325 STRCHR(VG_Z_LIBC_SONAME, __GI_strchr)
2326 #endif
2327 
2328 // --- STRCHRNUL --------------------------------------------------
2329 //
2330 #define STRCHRNUL(soname, fnname) \
2331    char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ); \
2332    char* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( const char* s, int c ) \
2333    { return Replace_strchrnul(s, c); }
2334 
2335 STRCHRNUL(VG_Z_LIBC_SONAME, strchrnul)
2336 STRCHRNUL(NONE,             strchrnul)
2337 #if defined(VGO_linux)
2338 STRCHRNUL(VG_Z_LIBC_SONAME, __GI_strchrnul)
2339 #endif
2340 
2341 // --- STRRCHR RINDEX -----------------------------------------------------
2342 //
2343 #define STRRCHR(soname, fnname) \
2344    char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str, int c ); \
2345    char* VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str, int c ) \
2346    { return Replace_strrchr(str, c); }
2347 
2348 // Apparently rindex() is the same thing as strrchr()
2349 STRRCHR(VG_Z_LIBC_SONAME, strrchr)
2350 STRRCHR(VG_Z_LIBC_SONAME, rindex)
2351 STRRCHR(NONE,             strrchr)
2352 STRRCHR(NONE,             rindex)
2353 #if defined(VGO_linux)
2354 STRRCHR(VG_Z_LIBC_SONAME, __GI_strrchr)
2355 #endif
2356 
2357 // --- STRCMP -----------------------------------------------------
2358 //
2359 #define STRCMP(soname, fnname) \
2360    int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2361           ( const char* s1, const char* s2 ); \
2362    int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2363           ( const char* s1, const char* s2 ) \
2364    { return Replace_strcmp(s1, s2); }
2365 
2366 STRCMP(VG_Z_LIBC_SONAME, strcmp)
2367 STRCMP(NONE,             strcmp)
2368 #if defined(VGO_linux)
2369 STRCMP(VG_Z_LIBC_SONAME, __GI_strcmp)
2370 #endif
2371 
2372 #define MEMCMP(soname, fnname) \
2373    int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2374           ( const char* s1, const char* s2 , size_t n); \
2375    int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2376           ( const char* s1, const char* s2 , size_t n) \
2377    { return Replace_memcmp(s1, s2, n); }
2378 
2379 MEMCMP(VG_Z_LIBC_SONAME, __memcmp_ssse3)
2380 MEMCMP(VG_Z_LIBC_SONAME, memcmp)
2381 MEMCMP(NONE,             memcmp)
2382 #if defined(VGO_linux)
2383 MEMCMP(VG_Z_LIBC_SONAME, __GI_memcmp)
2384 #endif
2385 
2386 #define MEMCHR(soname, fnname) \
2387    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n); \
2388    void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (const void *s, int c, SizeT n) \
2389    { return Replace_memchr(s, c, n); }
2390 
2391 MEMCHR(VG_Z_LIBC_SONAME, memchr)
2392 MEMCHR(NONE, memchr)
2393 
2394 #define STRNCMP(soname, fnname) \
2395    int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2396           ( const char* s1, const char* s2, size_t n); \
2397    int VG_REPLACE_FUNCTION_ZU(soname,fnname) \
2398           ( const char* s1, const char* s2, size_t n) \
2399    { return Replace_strncmp(s1, s2, n); }
2400 
2401 STRNCMP(VG_Z_LIBC_SONAME, strncmp)
2402 STRNCMP(NONE,             strncmp)
2403 #if defined(VGO_linux)
2404 STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
2405 #endif
2406 
2407 // --- STRLEN -----------------------------------------------------
2408 //
2409 // Note that this replacement often doesn't get used because gcc inlines
2410 // calls to strlen() with its own built-in version.  This can be very
2411 // confusing if you aren't expecting it.  Other small functions in this file
2412 // may also be inline by gcc.
2413 #define STRLEN(soname, fnname) \
2414    SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ); \
2415    SizeT VG_REPLACE_FUNCTION_ZU(soname,fnname)( const char* str ) \
2416    { return Replace_strlen(str); }
2417 
2418 STRLEN(VG_Z_LIBC_SONAME, strlen)
2419 STRLEN(NONE,             strlen)
2420 #if defined(VGO_linux)
2421 STRLEN(VG_Z_LIBC_SONAME, __GI_strlen)
2422 #endif
2423 
2424 // --- STRCPY -----------------------------------------------------
2425 //
2426 #define STRCPY(soname, fnname) \
2427    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
2428    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
2429    { return Replace_strcpy(dst, src); }
2430 
2431 STRCPY(VG_Z_LIBC_SONAME, strcpy)
2432 STRCPY(NONE,             strcpy)
2433 #if defined(VGO_linux)
2434 STRCPY(VG_Z_LIBC_SONAME, __GI_strcpy)
2435 #endif
2436 
2437 // --- STRNCPY -----------------------------------------------------
2438 //
2439 #define STRNCPY(soname, fnname) \
2440    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src, size_t n ); \
2441    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src, size_t n ) \
2442    { return Replace_strncpy(dst, src, n); }
2443 
2444 STRNCPY(VG_Z_LIBC_SONAME, strncpy)
2445 STRNCPY(NONE,             strncpy)
2446 #if defined(VGO_linux)
2447 STRNCPY(VG_Z_LIBC_SONAME, __GI_strncpy)
2448 #endif
2449 
2450 // --- STRCAT -----------------------------------------------------
2451 //
2452 #define STRCAT(soname, fnname) \
2453    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src); \
2454    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src) \
2455    { return Replace_strcat(dst, src); }
2456 
2457 STRCAT(VG_Z_LIBC_SONAME, strcat)
2458 STRCAT(NONE,             strcat)
2459 #if defined(VGO_linux)
2460 STRCAT(VG_Z_LIBC_SONAME, __GI_strcat)
2461 #endif
2462 
2463 // --- STPCPY -----------------------------------------------------
2464 //
2465 #define STPCPY(soname, fnname) \
2466    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ); \
2467    char* VG_REPLACE_FUNCTION_ZU(soname, fnname) ( char* dst, const char* src ) \
2468    { return Replace_stpcpy(dst, src); }
2469 
2470 STPCPY(VG_Z_LIBC_SONAME, stpcpy)
2471 STPCPY(NONE,             stpcpy)
2472 #if defined(VGO_linux)
2473 STPCPY(VG_Z_LIBC_SONAME, __GI_stpcpy)
2474 #endif
2475 
2476 //------------------------ Annotations ---------------- {{{1
2477 
2478 
2479 
2480 #define ANN_FUNC(ret_ty, f, args...) \
2481     ret_ty I_WRAP_SONAME_FNNAME_ZZ(Za,f)(args); \
2482     ret_ty I_WRAP_SONAME_FNNAME_ZZ(Za,f)(args)
2483 
2484 
2485 #define ANN_TRACE(args...) \
2486     do{\
2487       if(TRACE_ANN_FNS){\
2488         int tid = VALGRIND_TS_THREAD_ID();\
2489         int sid = VALGRIND_TS_SEGMENT_ID();\
2490         fprintf(stderr, args);\
2491         if(tid != 999999 && sid != 999999) fflush(stderr);\
2492       }\
2493     }while(0)
2494 
2495 ANN_FUNC(int, RunningOnValgrind, void) {
2496   return 1;
2497 }
2498 
ANN_FUNC(const char *,ThreadSanitizerQuery,const char * query)2499 ANN_FUNC(const char *, ThreadSanitizerQuery, const char *query) {
2500   Word res;
2501   DO_CREQ_W_WW(res, TSREQ_THREAD_SANITIZER_QUERY, const char*, query, long, 0);
2502   return (const char *)res;
2503 }
2504 
ANN_FUNC(void,AnnotateFlushState,const char * unused_file,int unused_line)2505 ANN_FUNC(void, AnnotateFlushState, const char *unused_file, int unused_line) {
2506   DO_CREQ_v_v(TSREQ_FLUSH_STATE);
2507 }
2508 
ANN_FUNC(void,AnnotateRWLockCreate,const char * file,int line,void * lock)2509 ANN_FUNC(void, AnnotateRWLockCreate, const char *file, int line, void *lock)
2510 {
2511   const char *name = "AnnotateRWLockCreate";
2512   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, lock, file, line);
2513   DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_CREATE_POST, void*, lock, long, 0 /*non recur*/);
2514 }
2515 
ANN_FUNC(void,AnnotateRWLockDestroy,const char * file,int line,void * lock)2516 ANN_FUNC(void, AnnotateRWLockDestroy, const char *file, int line, void *lock)
2517 {
2518   const char *name = "AnnotateRWLockDestroy";
2519   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, lock, file, line);
2520   DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_DESTROY_PRE, void*, lock);
2521 }
2522 
ANN_FUNC(void,AnnotateRWLockAcquired,const char * file,int line,void * lock,int is_w)2523 ANN_FUNC(void, AnnotateRWLockAcquired, const char *file, int line, void *lock, int is_w)
2524 {
2525   const char *name = "AnnotateRWLockAcquired";
2526   ANN_TRACE("--#%d %s[%p] rw=%d %s:%d\n", tid, name, lock, is_w, file, line);
2527   DO_CREQ_v_WW(TSREQ_PTHREAD_RWLOCK_LOCK_POST,  void*,lock,long, (long)is_w);
2528 }
2529 
ANN_FUNC(void,AnnotateRWLockReleased,const char * file,int line,void * lock,int is_w)2530 ANN_FUNC(void, AnnotateRWLockReleased, const char *file, int line, void *lock, int is_w)
2531 {
2532   const char *name = "AnnotateRWLockReleased";
2533   ANN_TRACE("--#%d %s[%p] rw=%d %s:%d\n", tid, name, lock, is_w, file, line);
2534   DO_CREQ_v_W(TSREQ_PTHREAD_RWLOCK_UNLOCK_PRE, void*, lock);
2535 }
2536 
ANN_FUNC(void,AnnotateCondVarWait,const char * file,int line,void * cv,void * lock)2537 ANN_FUNC(void, AnnotateCondVarWait, const char *file, int line, void *cv, void *lock)
2538 {
2539   const char *name = "AnnotateCondVarWait";
2540   ANN_TRACE("--#%d %s[%p|%p] %s:%d\n", tid, name, cv, lock, file, line);
2541   do_wait(cv);
2542 }
2543 
ANN_FUNC(void,AnnotateCondVarSignal,const char * file,int line,void * cv)2544 ANN_FUNC(void, AnnotateCondVarSignal, const char *file, int line, void *cv)
2545 {
2546   const char *name = "AnnotateCondVarSignal";
2547   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, cv, file, line);
2548   DO_CREQ_v_W(TSREQ_SIGNAL, void*,cv);
2549 }
2550 
ANN_FUNC(void,AnnotateCondVarSignalAll,const char * file,int line,void * cv)2551 ANN_FUNC(void, AnnotateCondVarSignalAll, const char *file, int line, void *cv)
2552 {
2553   const char *name = "AnnotateCondVarSignalAll";
2554   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, cv, file, line);
2555   DO_CREQ_v_W(TSREQ_SIGNAL, void*,cv);
2556 }
2557 
ANN_FUNC(void,AnnotateHappensBefore,const char * file,int line,void * obj)2558 ANN_FUNC(void, AnnotateHappensBefore, const char *file, int line, void *obj)
2559 {
2560   const char *name = "AnnotateHappensBefore";
2561   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, obj, file, line);
2562   DO_CREQ_v_W(TSREQ_SIGNAL, void*, obj);
2563 }
2564 
ANN_FUNC(void,WTFAnnotateHappensBefore,const char * file,int line,void * obj)2565 ANN_FUNC(void, WTFAnnotateHappensBefore, const char *file, int line, void *obj)
2566 {
2567   const char *name = "WTFAnnotateHappensBefore";
2568   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, obj, file, line);
2569   DO_CREQ_v_W(TSREQ_SIGNAL, void*, obj);
2570 }
2571 
ANN_FUNC(void,AnnotateHappensAfter,const char * file,int line,void * obj)2572 ANN_FUNC(void, AnnotateHappensAfter, const char *file, int line, void *obj)
2573 {
2574   const char *name = "AnnotateHappensAfter";
2575   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, obj, file, line);
2576   do_wait(obj);
2577 }
2578 
ANN_FUNC(void,WTFAnnotateHappensAfter,const char * file,int line,void * obj)2579 ANN_FUNC(void, WTFAnnotateHappensAfter, const char *file, int line, void *obj)
2580 {
2581   const char *name = "WTFAnnotateHappensAfter";
2582   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, obj, file, line);
2583   do_wait(obj);
2584 }
2585 
ANN_FUNC(void,AnnotatePCQCreate,const char * file,int line,void * pcq)2586 ANN_FUNC(void, AnnotatePCQCreate, const char *file, int line, void *pcq)
2587 {
2588   const char *name = "AnnotatePCQCreate";
2589   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, pcq, file, line);
2590   DO_CREQ_v_W(TSREQ_PCQ_CREATE,   void*,pcq);
2591 }
2592 
ANN_FUNC(void,AnnotatePCQDestroy,const char * file,int line,void * pcq)2593 ANN_FUNC(void, AnnotatePCQDestroy, const char *file, int line, void *pcq)
2594 {
2595   const char *name = "AnnotatePCQDestroy";
2596   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, pcq, file, line);
2597   DO_CREQ_v_W(TSREQ_PCQ_DESTROY,   void*,pcq);
2598 }
2599 
ANN_FUNC(void,AnnotatePCQPut,const char * file,int line,void * pcq)2600 ANN_FUNC(void, AnnotatePCQPut, const char *file, int line, void *pcq)
2601 {
2602   const char *name = "AnnotatePCQPut";
2603   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, pcq, file, line);
2604   DO_CREQ_v_W(TSREQ_PCQ_PUT,   void*,pcq);
2605 }
2606 
ANN_FUNC(void,AnnotatePCQGet,const char * file,int line,void * pcq)2607 ANN_FUNC(void, AnnotatePCQGet, const char *file, int line, void *pcq)
2608 {
2609   const char *name = "AnnotatePCQGet";
2610   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, pcq, file, line);
2611   DO_CREQ_v_W(TSREQ_PCQ_GET,   void*,pcq);
2612 }
2613 
ANN_FUNC(void,AnnotateExpectRace,const char * file,int line,void * mem,char * description)2614 ANN_FUNC(void, AnnotateExpectRace, const char *file, int line, void *mem, char *description)
2615 {
2616   const char *name = "AnnotateExpectRace";
2617   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mem, file, line);
2618   DO_CREQ_v_WW(TSREQ_EXPECT_RACE, void*,mem, char*,description);
2619 }
2620 
ANN_FUNC(void,AnnotateFlushExpectedRaces,const char * file,int line)2621 ANN_FUNC(void, AnnotateFlushExpectedRaces, const char *file, int line)
2622 {
2623   const char *name = __FUNCTION__;
2624   ANN_TRACE("--#%d %s\n", tid, name);
2625   DO_CREQ_v_v(TSREQ_FLUSH_EXPECTED_RACES);
2626 }
2627 
ANN_FUNC(void,AnnotateBenignRace,const char * file,int line,void * mem,char * description)2628 ANN_FUNC(void, AnnotateBenignRace, const char *file, int line, void *mem, char *description)
2629 {
2630   const char *name = "AnnotateBenignRace";
2631   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mem, file, line);
2632   DO_CREQ_v_WWW(TSREQ_BENIGN_RACE, void*,mem, long, 1, char*,description);
2633 }
2634 
ANN_FUNC(void,AnnotateBenignRaceSized,const char * file,int line,void * mem,long size,char * description)2635 ANN_FUNC(void, AnnotateBenignRaceSized, const char *file, int line, void *mem, long size, char *description)
2636 {
2637   const char *name = "AnnotateBenignRace";
2638   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mem, file, line);
2639   DO_CREQ_v_WWW(TSREQ_BENIGN_RACE, char*,(char*)mem, long, size,
2640                 char*,description);
2641 }
2642 
ANN_FUNC(void,WTFAnnotateBenignRaceSized,const char * file,int line,void * mem,long size,char * description)2643 ANN_FUNC(void, WTFAnnotateBenignRaceSized, const char *file, int line, void *mem, long size, char *description)
2644 {
2645   const char *name = "WTFAnnotateBenignRace";
2646   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mem, file, line);
2647   DO_CREQ_v_WWW(TSREQ_BENIGN_RACE, char*,(char*)mem, long, size,
2648                 char*,description);
2649 }
2650 
2651 
ANN_FUNC(void,AnnotateNewMemory,char * file,int line,void * mem,long size)2652 ANN_FUNC(void, AnnotateNewMemory, char *file, int line, void *mem, long size)
2653 {
2654   const char *name = "AnnotateNewMemory";
2655   ANN_TRACE("--#%d %s[%p,%d] %s:%d\n", tid, name, mem, (int)size, file, line);
2656   DO_CREQ_v_WWWW(TSREQ_CLEAN_MEMORY, void*,mem, long, size, char*, file, long, (long)line);
2657 }
2658 
ANN_FUNC(void,AnnotatePublishMemoryRange,char * file,int line,void * mem,long size)2659 ANN_FUNC(void, AnnotatePublishMemoryRange, char *file, int line, void *mem, long size)
2660 {
2661   const char *name = "AnnotatePublishMemoryRange";
2662   ANN_TRACE("--#%d %s[%p,%d] %s:%d\n", tid, name, mem, (int)size, file, line);
2663   DO_CREQ_v_WW(TSREQ_PUBLISH_MEMORY_RANGE,   void*, mem, long, size);
2664 }
2665 
ANN_FUNC(void,AnnotateUnpublishMemoryRange,char * file,int line,void * mem,long size)2666 ANN_FUNC(void, AnnotateUnpublishMemoryRange, char *file, int line, void *mem, long size)
2667 {
2668   const char *name = "AnnotateUnpublishMemoryRange";
2669   ANN_TRACE("--#%d %s[%p,%d] %s:%d\n", tid, name, mem, (int)size, file, line);
2670   DO_CREQ_v_WW(TSREQ_UNPUBLISH_MEMORY_RANGE,   void*, mem, long, size);
2671 }
2672 
ANN_FUNC(void,AnnotateIgnoreReadsBegin,char * file,int line,void * mu)2673 ANN_FUNC(void, AnnotateIgnoreReadsBegin, char *file, int line, void *mu)
2674 {
2675   const char *name = "AnnotateIgnoreReadsBegin";
2676   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line);
2677   DO_CREQ_v_W(TSREQ_IGNORE_READS_BEGIN,   void*, mu);
2678 }
2679 
ANN_FUNC(void,AnnotateIgnoreReadsEnd,char * file,int line,void * mu)2680 ANN_FUNC(void, AnnotateIgnoreReadsEnd, char *file, int line, void *mu)
2681 {
2682   const char *name = "AnnotateIgnoreReadsEnd";
2683   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line);
2684   DO_CREQ_v_W(TSREQ_IGNORE_READS_END,   void*, mu);
2685 }
2686 
ANN_FUNC(void,AnnotateIgnoreWritesBegin,char * file,int line,void * mu)2687 ANN_FUNC(void, AnnotateIgnoreWritesBegin, char *file, int line, void *mu)
2688 {
2689   const char *name = "AnnotateIgnoreWritesBegin";
2690   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line);
2691   DO_CREQ_v_W(TSREQ_IGNORE_WRITES_BEGIN,   void*, mu);
2692 }
2693 
ANN_FUNC(void,AnnotateIgnoreWritesEnd,char * file,int line,void * mu)2694 ANN_FUNC(void, AnnotateIgnoreWritesEnd, char *file, int line, void *mu)
2695 {
2696   const char *name = "AnnotateIgnoreWritesEnd";
2697   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line);
2698   DO_CREQ_v_W(TSREQ_IGNORE_WRITES_END,   void*, mu);
2699 }
2700 
ANN_FUNC(void,AnnotateIgnoreSyncBegin,char * file,int line,void * mu)2701 ANN_FUNC(void, AnnotateIgnoreSyncBegin, char* file, int line, void *mu)
2702 {
2703   const char *name = "AnnotateIgnoreSyncBegin";
2704   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line);
2705   DO_CREQ_v_W(TSREQ_IGNORE_ALL_SYNC_BEGIN,  void*, mu);
2706 }
2707 
ANN_FUNC(void,AnnotateIgnoreSyncEnd,char * file,int line,void * mu)2708 ANN_FUNC(void, AnnotateIgnoreSyncEnd, char* file, int line, void *mu)
2709 {
2710   const char *name = "AnnotateIgnoreSyncEnd";
2711   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line);
2712   DO_CREQ_v_W(TSREQ_IGNORE_ALL_SYNC_END,  void*, mu);
2713 }
2714 
ANN_FUNC(void,AnnotateEnableRaceDetection,char * file,int line,int enable)2715 ANN_FUNC(void, AnnotateEnableRaceDetection, char *file, int line, int enable)
2716 {
2717   const char *name = "AnnotateEnableRaceDetection";
2718   ANN_TRACE("--#%d %s[%d] %s:%d\n", tid, name, enable, file, line);
2719   DO_CREQ_v_W(enable == 0 ? TSREQ_GLOBAL_IGNORE_ON : TSREQ_GLOBAL_IGNORE_OFF,
2720               long, 0);
2721 }
2722 
ANN_FUNC(void,AnnotateThreadName,char * file,int line,const char * thread_name)2723 ANN_FUNC(void, AnnotateThreadName, char *file, int line, const char *thread_name)
2724 {
2725   const char *name = "AnnotateThreadName";
2726   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, thread_name, file, line);
2727   DO_CREQ_v_W(TSREQ_SET_THREAD_NAME, const char *, thread_name);
2728 }
2729 
ANN_FUNC(void,AnnotateMutexIsUsedAsCondVar,char * file,int line,void * mu)2730 ANN_FUNC(void, AnnotateMutexIsUsedAsCondVar, char *file, int line, void *mu)
2731 {
2732   const char *name = "AnnotateMutexIsUsedAsCondVar";
2733   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line);
2734   DO_CREQ_v_W(TSREQ_MUTEX_IS_USED_AS_CONDVAR,   void*, mu);
2735 }
2736 
ANN_FUNC(void,AnnotateMutexIsNotPHB,char * file,int line,void * mu)2737 ANN_FUNC(void, AnnotateMutexIsNotPHB, char *file, int line, void *mu)
2738 {
2739   const char *name = "AnnotateMutexIsNotPhb";
2740   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mu, file, line);
2741   DO_CREQ_v_W(TSREQ_MUTEX_IS_NOT_PHB, void*, mu);
2742 }
2743 
ANN_FUNC(void,AnnotateTraceMemory,char * file,int line,void * mem)2744 ANN_FUNC(void, AnnotateTraceMemory, char *file, int line, void *mem)
2745 {
2746   const char *name = "AnnotateTraceMemory";
2747   ANN_TRACE("--#%d %s[%p] %s:%d\n", tid, name, mem, file, line);
2748   DO_CREQ_v_W(TSREQ_TRACE_MEM,   void*, mem);
2749 }
2750 
2751 #undef TRACE_ANN_FNS
2752 #define TRACE_ANN_FNS 1
2753 
ANN_FUNC(void,AnnotateNoOp,char * file,int line,void * mem)2754 ANN_FUNC(void, AnnotateNoOp, char *file, int line, void *mem)
2755 {
2756   const char *name = "AnnotateNoOp";
2757   IGNORE_ALL_ACCESSES_BEGIN();
2758   ANN_TRACE("--#%d/%d %s[%p] %s:%d\n", tid, sid, name, mem, file, line);
2759   IGNORE_ALL_ACCESSES_END();
2760 }
2761 
ANN_FUNC(void,AnnotateSetVerbosity,char * file,int line,void * mem)2762 ANN_FUNC(void, AnnotateSetVerbosity, char *file, int line, void *mem)
2763 {
2764   const char *name = "AnnotateSetVerbosity";
2765   OrigFn fn;
2766   VALGRIND_GET_ORIG_FN(fn);
2767   fprintf(stderr, "%s fn=%p\n", name, (void*)fn.nraddr);
2768   ANN_TRACE("--#%d/%d %s[%p] %s:%d\n", tid, sid, name, mem, file, line);
2769 }
2770 
2771 
2772 
2773 //-------------- NaCl Support -------------- {{{1
2774 // A bit hackish implementation of NaCl support.
2775 // We need to notify the valgrind core about
2776 //   a) nacl memory range
2777 //   b) nacl .nexe file
2778 #include "coregrind/pub_core_clreq.h"
2779 
2780 void I_WRAP_SONAME_FNNAME_ZZ(NONE, NaClSandboxMemoryStartForValgrind) (void *mem_start);
I_WRAP_SONAME_FNNAME_ZZ(NONE,NaClSandboxMemoryStartForValgrind)2781 void I_WRAP_SONAME_FNNAME_ZZ(NONE, NaClSandboxMemoryStartForValgrind) (void *mem_start) {
2782   OrigFn fn;
2783   int res;
2784   VALGRIND_GET_ORIG_FN(fn);
2785   CALL_FN_v_W(fn, mem_start);
2786   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__NACL_MEM_START, mem_start, 0, 0, 0, 0);
2787 }
2788 
2789 int I_WRAP_SONAME_FNNAME_ZZ(NONE, NaClFileNameForValgrind) (char *file);
I_WRAP_SONAME_FNNAME_ZZ(NONE,NaClFileNameForValgrind)2790 int I_WRAP_SONAME_FNNAME_ZZ(NONE, NaClFileNameForValgrind) (char *file) {
2791   OrigFn fn;
2792   int ret, res;
2793   VALGRIND_GET_ORIG_FN(fn);
2794   CALL_FN_W_W(ret, fn, file);
2795   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__NACL_FILE, file, 0, 0, 0, 0);
2796   return ret;
2797 }
2798 
2799 void I_WRAP_SONAME_FNNAME_ZZ(NONE, NaClFileMappingForValgrind) (UWord vma, UWord size, UWord file_offset);
I_WRAP_SONAME_FNNAME_ZZ(NONE,NaClFileMappingForValgrind)2800 void I_WRAP_SONAME_FNNAME_ZZ(NONE, NaClFileMappingForValgrind) (UWord vma, UWord size, UWord file_offset) {
2801   OrigFn fn;
2802   int res;
2803   VALGRIND_GET_ORIG_FN(fn);
2804   CALL_FN_v_WWW(fn, vma, size, file_offset);
2805   VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__NACL_MMAP, vma, size, file_offset, 0, 0);
2806 }
2807 
2808 
2809 //-------------- Functions to Ignore -------------- {{{1
2810 // For some functions we want to ignore everything that happens
2811 // after they were called and before they returned.
2812 // Is there any way that allows to do this via a command line?
2813 #define WRAP_AND_IGNORE(soname, fnname) \
2814   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *a1, void *a2, void *a3, void *a4); \
2815   void* I_WRAP_SONAME_FNNAME_ZU(soname,fnname) (void *a1, void *a2, void *a3, void *a4) { \
2816     void* ret; \
2817     OrigFn fn;\
2818     VALGRIND_GET_ORIG_FN(fn);\
2819     IGNORE_ALL_ACCESSES_BEGIN(); \
2820       CALL_FN_W_WWWW(ret, fn, a1, a2, a3, a4); \
2821     IGNORE_ALL_ACCESSES_END(); \
2822     return ret; \
2823   }
2824 
2825 WRAP_AND_IGNORE(NONE, getenv);
2826 
2827 // {{{1 end
2828 // vim:shiftwidth=2:softtabstop=2:expandtab
2829