drd_pthread_intercepts.c revision 3f4623e4ab3a3ab66c0685610e0f338a56f0426d
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 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 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_INIT, 464 cond, 0, 0, 0, 0); 465 return ret; 466} 467 468// pthread_cond_destroy 469PTH_FUNC(int, pthreadZucondZudestroyZa, // pthread_cond_destroy* 470 pthread_cond_t* cond) 471{ 472 int ret; 473 int res; 474 OrigFn fn; 475 VALGRIND_GET_ORIG_FN(fn); 476 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_DESTROY, 477 cond, 0, 0, 0, 0); 478 CALL_FN_W_W(ret, fn, cond); 479 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_DESTROY, 480 cond, 0, 0, 0, 0); 481 return ret; 482} 483 484// pthread_cond_wait 485PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait* 486 pthread_cond_t *cond, 487 pthread_mutex_t *mutex) 488{ 489 int ret; 490 int res; 491 OrigFn fn; 492 VALGRIND_GET_ORIG_FN(fn); 493 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_WAIT, 494 cond, mutex, mutex_type(mutex), 0, 0); 495 CALL_FN_W_WW(ret, fn, cond, mutex); 496 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT, 497 cond, mutex, 1, 0, 0); 498 return ret; 499} 500 501// pthread_cond_timedwait 502PTH_FUNC(int, pthreadZucondZutimedwaitZa, // pthread_cond_timedwait* 503 pthread_cond_t *cond, 504 pthread_mutex_t *mutex, 505 const struct timespec* abstime) 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_WWW(ret, fn, cond, mutex, abstime); 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_signal 520PTH_FUNC(int, pthreadZucondZusignalZa, // pthread_cond_signal* 521 pthread_cond_t* cond) 522{ 523 int ret; 524 int res; 525 OrigFn fn; 526 VALGRIND_GET_ORIG_FN(fn); 527 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_SIGNAL, 528 cond, 0, 0, 0, 0); 529 CALL_FN_W_W(ret, fn, cond); 530 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_SIGNAL, 531 cond, 0, 0, 0, 0); 532 return ret; 533} 534 535// pthread_cond_broadcast 536PTH_FUNC(int, pthreadZucondZubroadcastZa, // pthread_cond_broadcast* 537 pthread_cond_t* cond) 538{ 539 int ret; 540 int res; 541 OrigFn fn; 542 VALGRIND_GET_ORIG_FN(fn); 543 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_BROADCAST, 544 cond, 0, 0, 0, 0); 545 CALL_FN_W_W(ret, fn, cond); 546 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_BROADCAST, 547 cond, 0, 0, 0, 0); 548 return ret; 549} 550 551 552// pthread_spin_init 553PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init 554 pthread_spinlock_t *spinlock, 555 int pshared) 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_SPIN_INIT_OR_UNLOCK, 562 spinlock, 0, 0, 0, 0); 563 CALL_FN_W_WW(ret, fn, spinlock, pshared); 564 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK, 565 spinlock, 0, 0, 0, 0); 566 return ret; 567} 568 569// pthread_spin_destroy 570PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy 571 pthread_spinlock_t *spinlock) 572{ 573 int ret; 574 int res; 575 OrigFn fn; 576 VALGRIND_GET_ORIG_FN(fn); 577 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, 578 spinlock, 0, 0, 0, 0); 579 CALL_FN_W_W(ret, fn, spinlock); 580 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, 581 spinlock, mutex_type_spinlock, 0, 0, 0); 582 return ret; 583} 584 585// pthread_spin_lock 586PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock 587 pthread_spinlock_t *spinlock) 588{ 589 int ret; 590 int res; 591 OrigFn fn; 592 VALGRIND_GET_ORIG_FN(fn); 593 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 594 spinlock, mutex_type_spinlock, 0, 0, 0); 595 CALL_FN_W_W(ret, fn, spinlock); 596 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, 597 spinlock, ret == 0, 0, 0, 0); 598 return ret; 599} 600 601// pthread_spin_trylock 602PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock 603 pthread_spinlock_t *spinlock) 604{ 605 int ret; 606 int res; 607 OrigFn fn; 608 VALGRIND_GET_ORIG_FN(fn); 609 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 610 spinlock, mutex_type_spinlock, 0, 0, 0); 611 CALL_FN_W_W(ret, fn, spinlock); 612 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, 613 spinlock, ret == 0, 0, 0, 0); 614 return ret; 615} 616 617// pthread_spin_unlock 618PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock 619 pthread_spinlock_t *spinlock) 620{ 621 int ret; 622 int res; 623 OrigFn fn; 624 VALGRIND_GET_ORIG_FN(fn); 625 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK, 626 spinlock, mutex_type_spinlock, 0, 0, 0); 627 CALL_FN_W_W(ret, fn, spinlock); 628 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK, 629 spinlock, 0, 0, 0, 0); 630 return ret; 631} 632 633// pthread_barrier_init 634PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init 635 pthread_barrier_t* barrier, 636 const pthread_barrierattr_t* attr, 637 unsigned count) 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_BARRIER_INIT, 644 barrier, pthread_barrier, count, 0, 0); 645 CALL_FN_W_WWW(ret, fn, barrier, attr, count); 646 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_INIT, 647 barrier, pthread_barrier, 0, 0, 0); 648 return ret; 649} 650 651// pthread_barrier_destroy 652PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy 653 pthread_barrier_t* barrier) 654{ 655 int ret; 656 int res; 657 OrigFn fn; 658 VALGRIND_GET_ORIG_FN(fn); 659 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_DESTROY, 660 barrier, pthread_barrier, 0, 0, 0); 661 CALL_FN_W_W(ret, fn, barrier); 662 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_DESTROY, 663 barrier, pthread_barrier, 0, 0, 0); 664 return ret; 665} 666 667// pthread_barrier_wait 668PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait 669 pthread_barrier_t* barrier) 670{ 671 int ret; 672 int res; 673 OrigFn fn; 674 VALGRIND_GET_ORIG_FN(fn); 675 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT, 676 barrier, pthread_barrier, 0, 0, 0); 677 CALL_FN_W_W(ret, fn, barrier); 678 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT, 679 barrier, pthread_barrier, 680 ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD, 681 0, 0); 682 return ret; 683} 684 685 686// sem_init 687PTH_FUNC(int, semZuinitZa, // sem_init* 688 sem_t *sem, 689 int pshared, 690 unsigned int value) 691{ 692 int ret; 693 int res; 694 OrigFn fn; 695 VALGRIND_GET_ORIG_FN(fn); 696 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_INIT, 697 sem, pshared, value, 0, 0); 698 CALL_FN_W_WWW(ret, fn, sem, pshared, value); 699 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_INIT, 700 sem, 0, 0, 0, 0); 701 return ret; 702} 703 704// sem_destroy 705PTH_FUNC(int, semZudestroyZa, // sem_destroy* 706 sem_t *sem) 707{ 708 int ret; 709 int res; 710 OrigFn fn; 711 VALGRIND_GET_ORIG_FN(fn); 712 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_DESTROY, 713 sem, 0, 0, 0, 0); 714 CALL_FN_W_W(ret, fn, sem); 715 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_DESTROY, 716 sem, 0, 0, 0, 0); 717 return ret; 718} 719 720// sem_wait 721PTH_FUNC(int, semZuwaitZa, // sem_wait* 722 sem_t *sem) 723{ 724 int ret; 725 int res; 726 OrigFn fn; 727 VALGRIND_GET_ORIG_FN(fn); 728 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, 729 sem, 0, 0, 0, 0); 730 CALL_FN_W_W(ret, fn, sem); 731 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, 732 sem, ret == 0, 0, 0, 0); 733 return ret; 734} 735 736// sem_trywait 737PTH_FUNC(int, semZutrywaitZa, // sem_trywait* 738 sem_t *sem) 739{ 740 int ret; 741 int res; 742 OrigFn fn; 743 VALGRIND_GET_ORIG_FN(fn); 744 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, 745 sem, 0, 0, 0, 0); 746 CALL_FN_W_W(ret, fn, sem); 747 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, 748 sem, ret == 0, 0, 0, 0); 749 return ret; 750} 751 752// sem_timedwait 753PTH_FUNC(int, semZutimedwait, // sem_timedwait 754 sem_t *sem, const struct timespec *abs_timeout) 755{ 756 int ret; 757 int res; 758 OrigFn fn; 759 VALGRIND_GET_ORIG_FN(fn); 760 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, 761 sem, 0, 0, 0, 0); 762 CALL_FN_W_WW(ret, fn, sem, abs_timeout); 763 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, 764 sem, ret == 0, 0, 0, 0); 765 return ret; 766} 767 768// sem_post 769PTH_FUNC(int, semZupostZa, // sem_post* 770 sem_t *sem) 771{ 772 int ret; 773 int res; 774 OrigFn fn; 775 VALGRIND_GET_ORIG_FN(fn); 776 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST, 777 sem, 0, 0, 0, 0); 778 CALL_FN_W_W(ret, fn, sem); 779 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST, 780 sem, ret == 0, 0, 0, 0); 781 return ret; 782} 783 784// pthread_rwlock_init 785PTH_FUNC(int, 786 pthreadZurwlockZuinitZa, // pthread_rwlock_init* 787 pthread_rwlock_t* rwlock, 788 const pthread_rwlockattr_t* attr) 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_RWLOCK_INIT, 795 rwlock, 0, 0, 0, 0); 796 CALL_FN_W_WW(ret, fn, rwlock, attr); 797 return ret; 798} 799 800// pthread_rwlock_destroy 801PTH_FUNC(int, 802 pthreadZurwlockZudestroyZa, // pthread_rwlock_destroy* 803 pthread_rwlock_t* rwlock) 804{ 805 int ret; 806 int res; 807 OrigFn fn; 808 VALGRIND_GET_ORIG_FN(fn); 809 CALL_FN_W_W(ret, fn, rwlock); 810 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_DESTROY, 811 rwlock, 0, 0, 0, 0); 812 return ret; 813} 814 815// pthread_rwlock_rdlock 816PTH_FUNC(int, 817 pthreadZurwlockZurdlockZa, // pthread_rwlock_rdlock* 818 pthread_rwlock_t* rwlock) 819{ 820 int ret; 821 int res; 822 OrigFn fn; 823 VALGRIND_GET_ORIG_FN(fn); 824 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, 825 rwlock, 0, 0, 0, 0); 826 CALL_FN_W_W(ret, fn, rwlock); 827 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, 828 rwlock, ret == 0, 0, 0, 0); 829 return ret; 830} 831 832// pthread_rwlock_wrlock 833PTH_FUNC(int, 834 pthreadZurwlockZuwrlockZa, // pthread_rwlock_wrlock* 835 pthread_rwlock_t* rwlock) 836{ 837 int ret; 838 int res; 839 OrigFn fn; 840 VALGRIND_GET_ORIG_FN(fn); 841 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, 842 rwlock, 0, 0, 0, 0); 843 CALL_FN_W_W(ret, fn, rwlock); 844 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, 845 rwlock, ret == 0, 0, 0, 0); 846 return ret; 847} 848 849// pthread_rwlock_timedrdlock 850PTH_FUNC(int, 851 pthreadZurwlockZutimedrdlockZa, // pthread_rwlock_timedrdlock* 852 pthread_rwlock_t* rwlock) 853{ 854 int ret; 855 int res; 856 OrigFn fn; 857 VALGRIND_GET_ORIG_FN(fn); 858 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, 859 rwlock, 0, 0, 0, 0); 860 CALL_FN_W_W(ret, fn, rwlock); 861 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, 862 rwlock, ret == 0, 0, 0, 0); 863 return ret; 864} 865 866// pthread_rwlock_timedwrlock 867PTH_FUNC(int, 868 pthreadZurwlockZutimedwrlockZa, // pthread_rwlock_timedwrlock* 869 pthread_rwlock_t* rwlock) 870{ 871 int ret; 872 int res; 873 OrigFn fn; 874 VALGRIND_GET_ORIG_FN(fn); 875 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, 876 rwlock, 0, 0, 0, 0); 877 CALL_FN_W_W(ret, fn, rwlock); 878 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, 879 rwlock, ret == 0, 0, 0, 0); 880 return ret; 881} 882 883// pthread_rwlock_tryrdlock 884PTH_FUNC(int, 885 pthreadZurwlockZutryrdlockZa, // pthread_rwlock_tryrdlock* 886 pthread_rwlock_t* rwlock) 887{ 888 int ret; 889 int res; 890 OrigFn fn; 891 VALGRIND_GET_ORIG_FN(fn); 892 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, 893 rwlock, 0, 0, 0, 0); 894 CALL_FN_W_W(ret, fn, rwlock); 895 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, 896 rwlock, ret == 0, 0, 0, 0); 897 return ret; 898} 899 900// pthread_rwlock_trywrlock 901PTH_FUNC(int, 902 pthreadZurwlockZutrywrlockZa, // pthread_rwlock_trywrlock* 903 pthread_rwlock_t* rwlock) 904{ 905 int ret; 906 int res; 907 OrigFn fn; 908 VALGRIND_GET_ORIG_FN(fn); 909 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, 910 rwlock, 0, 0, 0, 0); 911 CALL_FN_W_W(ret, fn, rwlock); 912 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, 913 rwlock, ret == 0, 0, 0, 0); 914 return ret; 915} 916 917// pthread_rwlock_unlock 918PTH_FUNC(int, 919 pthreadZurwlockZuunlockZa, // pthread_rwlock_unlock* 920 pthread_rwlock_t* rwlock) 921{ 922 int ret; 923 int res; 924 OrigFn fn; 925 VALGRIND_GET_ORIG_FN(fn); 926 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_UNLOCK, 927 rwlock, 0, 0, 0, 0); 928 CALL_FN_W_W(ret, fn, rwlock); 929 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_UNLOCK, 930 rwlock, ret == 0, 0, 0, 0); 931 return ret; 932} 933