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