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