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