drd_pthread_intercepts.c revision d2d744c4b4ec47822a9d88833d2fa0500efb342a
1/* -*- mode: C; c-basic-offset: 3; -*- */ 2 3/*--------------------------------------------------------------------*/ 4/*--- Client-space code for DRD. drd_pthread_intercepts.c ---*/ 5/*--------------------------------------------------------------------*/ 6 7/* 8 This file is part of DRD, a thread error detector. 9 10 Copyright (C) 2006-2009 Bart Van Assche <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/* 44 * Define _GNU_SOURCE to make sure that pthread_spinlock_t is available when 45 * compiling with older glibc versions (2.3 or before). 46 */ 47#ifndef _GNU_SOURCE 48#define _GNU_SOURCE 49#endif 50 51#include <assert.h> /* assert() */ 52#include <pthread.h> /* pthread_mutex_t */ 53#include <semaphore.h> /* sem_t */ 54#include <stdio.h> /* fprintf() */ 55#include <stdlib.h> /* malloc(), free() */ 56#include <unistd.h> /* confstr() */ 57#include "config.h" /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP etc. */ 58#include "drd_basics.h" /* DRD_() */ 59#include "drd_clientreq.h" 60#include "pub_tool_redir.h" /* VG_WRAP_FUNCTION_ZZ() */ 61 62 63/* Defines. */ 64 65/* 66 * Do not undefine the two macro's below, or the following two subtle race 67 * conditions will be introduced in the data race detection algorithm: 68 * - sg_init() runs on the context of the created thread and copies the 69 * vector clock of the creator thread. This only works reliably if 70 * the creator thread waits until this copy has been performed. 71 * - Since DRD_(thread_compute_minimum_vc)() does not take the vector 72 * clocks into account that are involved in thread creation but 73 * for which the corresponding thread has not yet been created, by 74 * undefining the macro below it becomes possible that segments get 75 * discarded that should not yet be discarded. Or: some data races 76 * are not detected. 77 */ 78#define WAIT_UNTIL_CREATED_THREAD_STARTED 79#define ALLOCATE_THREAD_ARGS_ON_THE_STACK 80 81#define PTH_FUNC(ret_ty, f, args...) \ 82 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args); \ 83 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args) 84 85 86/* Local data structures. */ 87 88typedef struct 89{ 90 void* (*start)(void*); 91 void* arg; 92 int detachstate; 93#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) 94 int wrapper_started; 95#endif 96} DrdPosixThreadArgs; 97 98 99/* Local function declarations. */ 100 101static void DRD_(init)(void) __attribute__((constructor)); 102static void DRD_(check_threading_library)(void); 103static void DRD_(set_main_thread_state)(void); 104 105 106/* Function definitions. */ 107 108/** 109 * Shared library initialization function. The function init() is called after 110 * dlopen() has loaded the shared library with DRD client intercepts because 111 * the constructor attribute was specified in the declaration of this function. 112 * Note: do specify the -nostdlib option to gcc when linking this code into a 113 * shared library because doing so would cancel the effect of the constructor 114 * attribute ! Using the gcc option -nodefaultlibs is fine because this last 115 * option preserves the shared library initialization code that calls 116 * constructor and destructor functions. 117 */ 118static void DRD_(init)(void) 119{ 120 DRD_(check_threading_library)(); 121 DRD_(set_main_thread_state)(); 122} 123 124/** 125 * POSIX threads and DRD each have their own mutex type identification. 126 * Convert POSIX threads' mutex type to DRD's mutex type. In the code below 127 * if-statements are used to test the value of 'kind' instead of a switch 128 * statement because some of the PTHREAD_MUTEX_ macro's may have the same 129 * value. 130 */ 131static MutexT DRD_(pthread_to_drd_mutex_type)(const int kind) 132{ 133 if (kind == PTHREAD_MUTEX_RECURSIVE) 134 return mutex_type_recursive_mutex; 135 else if (kind == PTHREAD_MUTEX_ERRORCHECK) 136 return mutex_type_errorcheck_mutex; 137 else if (kind == PTHREAD_MUTEX_NORMAL) 138 return mutex_type_default_mutex; 139 else if (kind == PTHREAD_MUTEX_DEFAULT) 140 return mutex_type_default_mutex; 141#if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP) 142 else if (kind == PTHREAD_MUTEX_ADAPTIVE_NP) 143 return mutex_type_default_mutex; 144#endif 145 else 146 { 147 return mutex_type_invalid_mutex; 148 } 149} 150 151/** 152 * Read the mutex type stored in the client memory used for the mutex 153 * implementation. 154 * 155 * @note This function depends on the implementation of the POSIX threads 156 * library -- the POSIX standard does not define the name of the member in 157 * which the mutex type is stored. 158 * @note The function mutex_type() has been declared inline in order 159 * to avoid that it shows up in call stacks (drd/tests/...exp* files). 160 * @note glibc stores the mutex type in the lowest two bits, and uses the 161 * higher bits for flags like PTHREAD_MUTEXATTR_FLAG_ROBUST and 162 * PTHREAD_MUTEXATTR_FLAG_PSHARED. 163 */ 164static __inline__ MutexT DRD_(mutex_type)(pthread_mutex_t* mutex) 165{ 166#if defined(HAVE_PTHREAD_MUTEX_T__M_KIND) 167 /* glibc + LinuxThreads. */ 168 const int kind = mutex->__m_kind & 3; 169 return DRD_(pthread_to_drd_mutex_type)(kind); 170#elif defined(HAVE_PTHREAD_MUTEX_T__DATA__KIND) 171 /* glibc + NPTL. */ 172 const int kind = mutex->__data.__kind & 3; 173 return DRD_(pthread_to_drd_mutex_type)(kind); 174#else 175 /* 176 * Another POSIX threads implementation. The mutex type won't be printed 177 * when enabling --trace-mutex=yes. 178 */ 179 return mutex_type_unknown; 180#endif 181} 182 183/** 184 * Tell DRD whether 'tid' is a joinable thread or a detached thread. 185 */ 186static void DRD_(set_joinable)(const pthread_t tid, const int joinable) 187{ 188 int res; 189 assert(joinable == 0 || joinable == 1); 190 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__SET_JOINABLE, 191 tid, joinable, 0, 0, 0); 192} 193 194/** 195 * The function called from the thread created by pthread_create(). 196 */ 197static void* DRD_(thread_wrapper)(void* arg) 198{ 199 int res; 200 DrdPosixThreadArgs* arg_ptr; 201 DrdPosixThreadArgs arg_copy; 202 203 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK, 204 0, 0, 0, 0, 0); 205 206 arg_ptr = (DrdPosixThreadArgs*)arg; 207 arg_copy = *arg_ptr; 208#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) 209 arg_ptr->wrapper_started = 1; 210#else 211#if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK) 212#error Defining ALLOCATE_THREAD_ARGS_ON_THE_STACK but not \ 213 WAIT_UNTIL_CREATED_THREAD_STARTED is not supported. 214#else 215 free(arg_ptr); 216#endif 217#endif 218 219 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID, 220 pthread_self(), 0, 0, 0, 0); 221 222 DRD_(set_joinable)(pthread_self(), 223 arg_copy.detachstate == PTHREAD_CREATE_JOINABLE); 224 225 return (arg_copy.start)(arg_copy.arg); 226} 227 228/** 229 * Return 1 if the LinuxThreads implementation of POSIX Threads has been 230 * detected, and 0 otherwise. 231 * 232 * @see For more information about the confstr() function, see also 233 * http://www.opengroup.org/onlinepubs/009695399/functions/confstr.html 234 */ 235static int DRD_(detected_linuxthreads)(void) 236{ 237#if defined(linux) 238#if defined(_CS_GNU_LIBPTHREAD_VERSION) 239 /* Linux with a recent glibc. */ 240 char buffer[256]; 241 unsigned len; 242 len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer)); 243 assert(len <= sizeof(buffer)); 244 return len > 0 && buffer[0] == 'l'; 245#else 246 /* Linux without _CS_GNU_LIBPTHREAD_VERSION: most likely LinuxThreads. */ 247 return 1; 248#endif 249#else 250 /* Another OS than Linux, hence no LinuxThreads. */ 251 return 0; 252#endif 253} 254 255/** 256 * Stop and print an error message in case a non-supported threading 257 * library implementation (LinuxThreads) has been detected. 258 */ 259static void DRD_(check_threading_library)(void) 260{ 261 if (DRD_(detected_linuxthreads)()) 262 { 263 if (getenv("LD_ASSUME_KERNEL")) 264 { 265 fprintf(stderr, 266"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n" 267"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n" 268"after having unset the environment variable LD_ASSUME_KERNEL. Giving up.\n" 269); 270 } 271 else 272 { 273 fprintf(stderr, 274"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n" 275"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n" 276"after having upgraded to a newer version of your Linux distribution.\n" 277"Giving up.\n" 278); 279 } 280 abort(); 281 } 282} 283 284/** 285 * The main thread is the only thread not created by pthread_create(). 286 * Update DRD's state information about the main thread. 287 */ 288static void DRD_(set_main_thread_state)(void) 289{ 290 int res; 291 292 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK, 293 0, 0, 0, 0, 0); 294 295 // Make sure that DRD knows about the main thread's POSIX thread ID. 296 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID, 297 pthread_self(), 0, 0, 0, 0); 298 299} 300 301 302/* 303 * Note: as of today there exist three different versions of pthread_create: 304 * - pthread_create@GLIBC_2.0 305 * - pthread_create@@GLIBC_2.1 306 * - pthread_create@@GLIBC_2.2.5 307 * As an example, in libpthread-2.3.4 both pthread_create@GLIBC_2.0 and 308 * pthread_create@@GLIBC_2.1 are defined, while in libpthread-2.9 all three 309 * versions have been implemented. In any glibc version where more than one 310 * pthread_create function has been implemented, older versions call the 311 * newer versions. Or: the pthread_create* wrapper defined below can be 312 * called recursively. Any code in this wrapper should take this in account. 313 * As an example, it is not safe to invoke the DRD_STOP_RECORDING 314 * / DRD_START_RECORDING client requests from the pthread_create wrapper. 315 * See also the implementation of pthread_create@GLIBC_2.0 in 316 * glibc-2.9/nptl/pthread_create.c. 317 */ 318 319// pthread_create 320PTH_FUNC(int, pthreadZucreateZa, // pthread_create* 321 pthread_t *thread, const pthread_attr_t *attr, 322 void *(*start) (void *), void *arg) 323{ 324 int res; 325 int ret; 326 OrigFn fn; 327#if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK) 328 DrdPosixThreadArgs thread_args; 329#endif 330 DrdPosixThreadArgs* thread_args_p; 331 332 VALGRIND_GET_ORIG_FN(fn); 333 334#if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK) 335 thread_args_p = &thread_args; 336#else 337 thread_args_p = malloc(sizeof(*thread_args_p)); 338#endif 339 assert(thread_args_p); 340 341 thread_args_p->start = start; 342 thread_args_p->arg = arg; 343#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) 344 DRD_IGNORE_VAR(thread_args_p->wrapper_started); 345 thread_args_p->wrapper_started = 0; 346#endif 347 /* 348 * Find out whether the thread will be started as a joinable thread 349 * or as a detached thread. If no thread attributes have been specified, 350 * this means that the new thread will be started as a joinable thread. 351 */ 352 thread_args_p->detachstate = PTHREAD_CREATE_JOINABLE; 353 if (attr) 354 { 355 if (pthread_attr_getdetachstate(attr, &thread_args_p->detachstate) != 0) 356 { 357 assert(0); 358 } 359 } 360 assert(thread_args_p->detachstate == PTHREAD_CREATE_JOINABLE 361 || thread_args_p->detachstate == PTHREAD_CREATE_DETACHED); 362 363 CALL_FN_W_WWWW(ret, fn, thread, attr, DRD_(thread_wrapper), thread_args_p); 364 365#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) 366 if (ret == 0) 367 { 368 /* 369 * Wait until the thread wrapper started. 370 * @todo Find out why some regression tests fail if thread arguments are 371 * passed via dynamically allocated memory and if the loop below is 372 * removed. 373 */ 374 while (! thread_args_p->wrapper_started) 375 { 376 sched_yield(); 377 } 378 } 379 380#if defined(ALLOCATE_THREAD_ARGS_DYNAMICALLY) 381 free(thread_args_p); 382#endif 383 384#endif 385 386 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_START_NEW_SEGMENT, 387 pthread_self(), 0, 0, 0, 0); 388 389 return ret; 390} 391 392// pthread_join 393PTH_FUNC(int, pthreadZujoinZa, // pthread_join* 394 pthread_t pt_joinee, void **thread_return) 395{ 396 int ret; 397 int res; 398 OrigFn fn; 399 400 VALGRIND_GET_ORIG_FN(fn); 401 CALL_FN_W_WW(ret, fn, pt_joinee, thread_return); 402 if (ret == 0) 403 { 404 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_JOIN, 405 pt_joinee, 0, 0, 0, 0); 406 } 407 return ret; 408} 409 410// pthread_detach 411PTH_FUNC(int, pthreadZudetach, pthread_t pt_thread) 412{ 413 int ret; 414 OrigFn fn; 415 VALGRIND_GET_ORIG_FN(fn); 416 { 417 CALL_FN_W_W(ret, fn, pt_thread); 418 if (ret == 0) 419 { 420 DRD_(set_joinable)(pt_thread, 0); 421 } 422 } 423 return ret; 424} 425 426// pthread_cancel* 427PTH_FUNC(int, pthreadZucancelZa, pthread_t pt_thread) 428{ 429 int res; 430 int ret; 431 OrigFn fn; 432 VALGRIND_GET_ORIG_FN(fn); 433 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_THREAD_CANCEL, 434 pt_thread, 0, 0, 0, 0); 435 CALL_FN_W_W(ret, fn, pt_thread); 436 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_CANCEL, 437 pt_thread, ret==0, 0, 0, 0); 438 return ret; 439} 440 441// pthread_mutex_init 442PTH_FUNC(int, pthreadZumutexZuinit, 443 pthread_mutex_t *mutex, 444 const pthread_mutexattr_t* attr) 445{ 446 int ret; 447 int res; 448 OrigFn fn; 449 int mt; 450 VALGRIND_GET_ORIG_FN(fn); 451 mt = PTHREAD_MUTEX_DEFAULT; 452 if (attr) 453 pthread_mutexattr_gettype(attr, &mt); 454 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT, 455 mutex, DRD_(pthread_to_drd_mutex_type)(mt), 456 0, 0, 0); 457 CALL_FN_W_WW(ret, fn, mutex, attr); 458 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT, 459 mutex, 0, 0, 0, 0); 460 return ret; 461} 462 463// pthread_mutex_destroy 464PTH_FUNC(int, pthreadZumutexZudestroy, 465 pthread_mutex_t *mutex) 466{ 467 int ret; 468 int res; 469 OrigFn fn; 470 VALGRIND_GET_ORIG_FN(fn); 471 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, 472 mutex, 0, 0, 0, 0); 473 CALL_FN_W_W(ret, fn, mutex); 474 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, 475 mutex, DRD_(mutex_type)(mutex), 0, 0, 0); 476 return ret; 477} 478 479// pthread_mutex_lock 480PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock 481 pthread_mutex_t *mutex) 482{ 483 int ret; 484 int res; 485 OrigFn fn; 486 VALGRIND_GET_ORIG_FN(fn); 487 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 488 mutex, DRD_(mutex_type)(mutex), 0, 0, 0); 489 CALL_FN_W_W(ret, fn, mutex); 490 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_MUTEX_LOCK, 491 mutex, ret == 0, 0, 0, 0); 492 return ret; 493} 494 495// pthread_mutex_trylock 496PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock 497 pthread_mutex_t *mutex) 498{ 499 int ret; 500 int res; 501 OrigFn fn; 502 VALGRIND_GET_ORIG_FN(fn); 503 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 504 mutex, DRD_(mutex_type)(mutex), 1, 0, 0); 505 CALL_FN_W_W(ret, fn, mutex); 506 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, 507 mutex, ret == 0, 0, 0, 0); 508 return ret; 509} 510 511// pthread_mutex_timedlock 512PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock 513 pthread_mutex_t *mutex, 514 const struct timespec *abs_timeout) 515{ 516 int ret; 517 int res; 518 OrigFn fn; 519 VALGRIND_GET_ORIG_FN(fn); 520 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 521 mutex, DRD_(mutex_type)(mutex), 0, 0, 0); 522 CALL_FN_W_WW(ret, fn, mutex, abs_timeout); 523 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, 524 mutex, ret == 0, 0, 0, 0); 525 return ret; 526} 527 528// pthread_mutex_unlock 529PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock 530 pthread_mutex_t *mutex) 531{ 532 int ret; 533 int res; 534 OrigFn fn; 535 VALGRIND_GET_ORIG_FN(fn); 536 VALGRIND_DO_CLIENT_REQUEST(res, -1, 537 VG_USERREQ__PRE_MUTEX_UNLOCK, 538 mutex, DRD_(mutex_type)(mutex), 0, 0, 0); 539 CALL_FN_W_W(ret, fn, mutex); 540 VALGRIND_DO_CLIENT_REQUEST(res, -1, 541 VG_USERREQ__POST_MUTEX_UNLOCK, 542 mutex, 0, 0, 0, 0); 543 return ret; 544} 545 546// pthread_cond_init 547PTH_FUNC(int, pthreadZucondZuinitZa, // pthread_cond_init* 548 pthread_cond_t* cond, 549 const pthread_condattr_t* attr) 550{ 551 int ret; 552 int res; 553 OrigFn fn; 554 VALGRIND_GET_ORIG_FN(fn); 555 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_INIT, 556 cond, 0, 0, 0, 0); 557 CALL_FN_W_WW(ret, fn, cond, attr); 558 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_INIT, 559 cond, 0, 0, 0, 0); 560 return ret; 561} 562 563// pthread_cond_destroy 564PTH_FUNC(int, pthreadZucondZudestroyZa, // pthread_cond_destroy* 565 pthread_cond_t* cond) 566{ 567 int ret; 568 int res; 569 OrigFn fn; 570 VALGRIND_GET_ORIG_FN(fn); 571 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_DESTROY, 572 cond, 0, 0, 0, 0); 573 CALL_FN_W_W(ret, fn, cond); 574 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_DESTROY, 575 cond, 0, 0, 0, 0); 576 return ret; 577} 578 579// pthread_cond_wait 580PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait* 581 pthread_cond_t *cond, 582 pthread_mutex_t *mutex) 583{ 584 int ret; 585 int res; 586 OrigFn fn; 587 VALGRIND_GET_ORIG_FN(fn); 588 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_WAIT, 589 cond, mutex, DRD_(mutex_type)(mutex), 0, 0); 590 CALL_FN_W_WW(ret, fn, cond, mutex); 591 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT, 592 cond, mutex, 1, 0, 0); 593 return ret; 594} 595 596// pthread_cond_timedwait 597PTH_FUNC(int, pthreadZucondZutimedwaitZa, // pthread_cond_timedwait* 598 pthread_cond_t *cond, 599 pthread_mutex_t *mutex, 600 const struct timespec* abstime) 601{ 602 int ret; 603 int res; 604 OrigFn fn; 605 VALGRIND_GET_ORIG_FN(fn); 606 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_WAIT, 607 cond, mutex, DRD_(mutex_type)(mutex), 0, 0); 608 CALL_FN_W_WWW(ret, fn, cond, mutex, abstime); 609 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT, 610 cond, mutex, 1, 0, 0); 611 return ret; 612} 613 614// NOTE: be careful to intercept only pthread_cond_signal() and not Darwin's 615// pthread_cond_signal_thread_np(). The former accepts one argument; the latter 616// two. Intercepting all pthread_cond_signal* functions will cause only one 617// argument to be passed to pthread_cond_signal_np() and hence will cause this 618// last function to crash. 619 620// pthread_cond_signal 621PTH_FUNC(int, pthreadZucondZusignal, // pthread_cond_signal 622 pthread_cond_t* cond) 623{ 624 int ret; 625 int res; 626 OrigFn fn; 627 VALGRIND_GET_ORIG_FN(fn); 628 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_SIGNAL, 629 cond, 0, 0, 0, 0); 630 CALL_FN_W_W(ret, fn, cond); 631 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_SIGNAL, 632 cond, 0, 0, 0, 0); 633 return ret; 634} 635 636PTH_FUNC(int, pthreadZucondZusignalZAZa, // pthread_cond_signal@* 637 pthread_cond_t* cond) 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_COND_SIGNAL, 644 cond, 0, 0, 0, 0); 645 CALL_FN_W_W(ret, fn, cond); 646 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_SIGNAL, 647 cond, 0, 0, 0, 0); 648 return ret; 649} 650 651// pthread_cond_broadcast 652PTH_FUNC(int, pthreadZucondZubroadcastZa, // pthread_cond_broadcast* 653 pthread_cond_t* cond) 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_COND_BROADCAST, 660 cond, 0, 0, 0, 0); 661 CALL_FN_W_W(ret, fn, cond); 662 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_BROADCAST, 663 cond, 0, 0, 0, 0); 664 return ret; 665} 666 667 668#if defined(HAVE_PTHREAD_SPIN_LOCK) 669// pthread_spin_init 670PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init 671 pthread_spinlock_t *spinlock, 672 int pshared) 673{ 674 int ret; 675 int res; 676 OrigFn fn; 677 VALGRIND_GET_ORIG_FN(fn); 678 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK, 679 spinlock, 0, 0, 0, 0); 680 CALL_FN_W_WW(ret, fn, spinlock, pshared); 681 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK, 682 spinlock, 0, 0, 0, 0); 683 return ret; 684} 685 686// pthread_spin_destroy 687PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy 688 pthread_spinlock_t *spinlock) 689{ 690 int ret; 691 int res; 692 OrigFn fn; 693 VALGRIND_GET_ORIG_FN(fn); 694 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, 695 spinlock, 0, 0, 0, 0); 696 CALL_FN_W_W(ret, fn, spinlock); 697 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, 698 spinlock, mutex_type_spinlock, 0, 0, 0); 699 return ret; 700} 701 702// pthread_spin_lock 703PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock 704 pthread_spinlock_t *spinlock) 705{ 706 int ret; 707 int res; 708 OrigFn fn; 709 VALGRIND_GET_ORIG_FN(fn); 710 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 711 spinlock, mutex_type_spinlock, 0, 0, 0); 712 CALL_FN_W_W(ret, fn, spinlock); 713 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, 714 spinlock, ret == 0, 0, 0, 0); 715 return ret; 716} 717 718// pthread_spin_trylock 719PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock 720 pthread_spinlock_t *spinlock) 721{ 722 int ret; 723 int res; 724 OrigFn fn; 725 VALGRIND_GET_ORIG_FN(fn); 726 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 727 spinlock, mutex_type_spinlock, 0, 0, 0); 728 CALL_FN_W_W(ret, fn, spinlock); 729 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, 730 spinlock, ret == 0, 0, 0, 0); 731 return ret; 732} 733 734// pthread_spin_unlock 735PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock 736 pthread_spinlock_t *spinlock) 737{ 738 int ret; 739 int res; 740 OrigFn fn; 741 VALGRIND_GET_ORIG_FN(fn); 742 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK, 743 spinlock, mutex_type_spinlock, 0, 0, 0); 744 CALL_FN_W_W(ret, fn, spinlock); 745 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK, 746 spinlock, 0, 0, 0, 0); 747 return ret; 748} 749#endif // HAVE_PTHREAD_SPIN_LOCK 750 751 752#if defined(HAVE_PTHREAD_BARRIER_INIT) 753// pthread_barrier_init 754PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init 755 pthread_barrier_t* barrier, 756 const pthread_barrierattr_t* attr, 757 unsigned count) 758{ 759 int ret; 760 int res; 761 OrigFn fn; 762 VALGRIND_GET_ORIG_FN(fn); 763 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_INIT, 764 barrier, pthread_barrier, count, 0, 0); 765 CALL_FN_W_WWW(ret, fn, barrier, attr, count); 766 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_INIT, 767 barrier, pthread_barrier, 0, 0, 0); 768 return ret; 769} 770 771// pthread_barrier_destroy 772PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy 773 pthread_barrier_t* barrier) 774{ 775 int ret; 776 int res; 777 OrigFn fn; 778 VALGRIND_GET_ORIG_FN(fn); 779 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_DESTROY, 780 barrier, pthread_barrier, 0, 0, 0); 781 CALL_FN_W_W(ret, fn, barrier); 782 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_DESTROY, 783 barrier, pthread_barrier, 0, 0, 0); 784 return ret; 785} 786 787// pthread_barrier_wait 788PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait 789 pthread_barrier_t* barrier) 790{ 791 int ret; 792 int res; 793 OrigFn fn; 794 VALGRIND_GET_ORIG_FN(fn); 795 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT, 796 barrier, pthread_barrier, 0, 0, 0); 797 CALL_FN_W_W(ret, fn, barrier); 798 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT, 799 barrier, pthread_barrier, 800 ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD, 801 ret == PTHREAD_BARRIER_SERIAL_THREAD, 0); 802 return ret; 803} 804#endif // HAVE_PTHREAD_BARRIER_INIT 805 806 807// sem_init 808PTH_FUNC(int, semZuinitZa, // sem_init* 809 sem_t *sem, 810 int pshared, 811 unsigned int value) 812{ 813 int ret; 814 int res; 815 OrigFn fn; 816 VALGRIND_GET_ORIG_FN(fn); 817 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_INIT, 818 sem, pshared, value, 0, 0); 819 CALL_FN_W_WWW(ret, fn, sem, pshared, value); 820 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_INIT, 821 sem, 0, 0, 0, 0); 822 return ret; 823} 824 825// sem_destroy 826PTH_FUNC(int, semZudestroyZa, // sem_destroy* 827 sem_t *sem) 828{ 829 int ret; 830 int res; 831 OrigFn fn; 832 VALGRIND_GET_ORIG_FN(fn); 833 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_DESTROY, 834 sem, 0, 0, 0, 0); 835 CALL_FN_W_W(ret, fn, sem); 836 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_DESTROY, 837 sem, 0, 0, 0, 0); 838 return ret; 839} 840 841// sem_wait 842PTH_FUNC(int, semZuwaitZa, // sem_wait* 843 sem_t *sem) 844{ 845 int ret; 846 int res; 847 OrigFn fn; 848 VALGRIND_GET_ORIG_FN(fn); 849 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, 850 sem, 0, 0, 0, 0); 851 CALL_FN_W_W(ret, fn, sem); 852 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, 853 sem, ret == 0, 0, 0, 0); 854 return ret; 855} 856 857// sem_trywait 858PTH_FUNC(int, semZutrywaitZa, // sem_trywait* 859 sem_t *sem) 860{ 861 int ret; 862 int res; 863 OrigFn fn; 864 VALGRIND_GET_ORIG_FN(fn); 865 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, 866 sem, 0, 0, 0, 0); 867 CALL_FN_W_W(ret, fn, sem); 868 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, 869 sem, ret == 0, 0, 0, 0); 870 return ret; 871} 872 873// sem_timedwait 874PTH_FUNC(int, semZutimedwait, // sem_timedwait 875 sem_t *sem, const struct timespec *abs_timeout) 876{ 877 int ret; 878 int res; 879 OrigFn fn; 880 VALGRIND_GET_ORIG_FN(fn); 881 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, 882 sem, 0, 0, 0, 0); 883 CALL_FN_W_WW(ret, fn, sem, abs_timeout); 884 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, 885 sem, ret == 0, 0, 0, 0); 886 return ret; 887} 888 889// sem_post 890PTH_FUNC(int, semZupostZa, // sem_post* 891 sem_t *sem) 892{ 893 int ret; 894 int res; 895 OrigFn fn; 896 VALGRIND_GET_ORIG_FN(fn); 897 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST, 898 sem, 0, 0, 0, 0); 899 CALL_FN_W_W(ret, fn, sem); 900 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST, 901 sem, ret == 0, 0, 0, 0); 902 return ret; 903} 904 905// pthread_rwlock_init 906PTH_FUNC(int, 907 pthreadZurwlockZuinitZa, // pthread_rwlock_init* 908 pthread_rwlock_t* rwlock, 909 const pthread_rwlockattr_t* attr) 910{ 911 int ret; 912 int res; 913 OrigFn fn; 914 VALGRIND_GET_ORIG_FN(fn); 915 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_INIT, 916 rwlock, 0, 0, 0, 0); 917 CALL_FN_W_WW(ret, fn, rwlock, attr); 918 return ret; 919} 920 921// pthread_rwlock_destroy 922PTH_FUNC(int, 923 pthreadZurwlockZudestroyZa, // pthread_rwlock_destroy* 924 pthread_rwlock_t* rwlock) 925{ 926 int ret; 927 int res; 928 OrigFn fn; 929 VALGRIND_GET_ORIG_FN(fn); 930 CALL_FN_W_W(ret, fn, rwlock); 931 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_DESTROY, 932 rwlock, 0, 0, 0, 0); 933 return ret; 934} 935 936// pthread_rwlock_rdlock 937PTH_FUNC(int, 938 pthreadZurwlockZurdlockZa, // pthread_rwlock_rdlock* 939 pthread_rwlock_t* rwlock) 940{ 941 int ret; 942 int res; 943 OrigFn fn; 944 VALGRIND_GET_ORIG_FN(fn); 945 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, 946 rwlock, 0, 0, 0, 0); 947 CALL_FN_W_W(ret, fn, rwlock); 948 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, 949 rwlock, ret == 0, 0, 0, 0); 950 return ret; 951} 952 953// pthread_rwlock_wrlock 954PTH_FUNC(int, 955 pthreadZurwlockZuwrlockZa, // pthread_rwlock_wrlock* 956 pthread_rwlock_t* rwlock) 957{ 958 int ret; 959 int res; 960 OrigFn fn; 961 VALGRIND_GET_ORIG_FN(fn); 962 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, 963 rwlock, 0, 0, 0, 0); 964 CALL_FN_W_W(ret, fn, rwlock); 965 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, 966 rwlock, ret == 0, 0, 0, 0); 967 return ret; 968} 969 970// pthread_rwlock_timedrdlock 971PTH_FUNC(int, 972 pthreadZurwlockZutimedrdlockZa, // pthread_rwlock_timedrdlock* 973 pthread_rwlock_t* rwlock) 974{ 975 int ret; 976 int res; 977 OrigFn fn; 978 VALGRIND_GET_ORIG_FN(fn); 979 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, 980 rwlock, 0, 0, 0, 0); 981 CALL_FN_W_W(ret, fn, rwlock); 982 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, 983 rwlock, ret == 0, 0, 0, 0); 984 return ret; 985} 986 987// pthread_rwlock_timedwrlock 988PTH_FUNC(int, 989 pthreadZurwlockZutimedwrlockZa, // pthread_rwlock_timedwrlock* 990 pthread_rwlock_t* rwlock) 991{ 992 int ret; 993 int res; 994 OrigFn fn; 995 VALGRIND_GET_ORIG_FN(fn); 996 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, 997 rwlock, 0, 0, 0, 0); 998 CALL_FN_W_W(ret, fn, rwlock); 999 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, 1000 rwlock, ret == 0, 0, 0, 0); 1001 return ret; 1002} 1003 1004// pthread_rwlock_tryrdlock 1005PTH_FUNC(int, 1006 pthreadZurwlockZutryrdlockZa, // pthread_rwlock_tryrdlock* 1007 pthread_rwlock_t* rwlock) 1008{ 1009 int ret; 1010 int res; 1011 OrigFn fn; 1012 VALGRIND_GET_ORIG_FN(fn); 1013 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, 1014 rwlock, 0, 0, 0, 0); 1015 CALL_FN_W_W(ret, fn, rwlock); 1016 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, 1017 rwlock, ret == 0, 0, 0, 0); 1018 return ret; 1019} 1020 1021// pthread_rwlock_trywrlock 1022PTH_FUNC(int, 1023 pthreadZurwlockZutrywrlockZa, // pthread_rwlock_trywrlock* 1024 pthread_rwlock_t* rwlock) 1025{ 1026 int ret; 1027 int res; 1028 OrigFn fn; 1029 VALGRIND_GET_ORIG_FN(fn); 1030 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, 1031 rwlock, 0, 0, 0, 0); 1032 CALL_FN_W_W(ret, fn, rwlock); 1033 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, 1034 rwlock, ret == 0, 0, 0, 0); 1035 return ret; 1036} 1037 1038// pthread_rwlock_unlock 1039PTH_FUNC(int, 1040 pthreadZurwlockZuunlockZa, // pthread_rwlock_unlock* 1041 pthread_rwlock_t* rwlock) 1042{ 1043 int ret; 1044 int res; 1045 OrigFn fn; 1046 VALGRIND_GET_ORIG_FN(fn); 1047 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_UNLOCK, 1048 rwlock, 0, 0, 0, 0); 1049 CALL_FN_W_W(ret, fn, rwlock); 1050 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_UNLOCK, 1051 rwlock, ret == 0, 0, 0, 0); 1052 return ret; 1053} 1054