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