drd_pthread_intercepts.c revision 6d79b74ed20abe9e497d05a6669585678e80d027
1/*--------------------------------------------------------------------*/ 2/*--- Client-space code for DRD. drd_pthread_intercepts.c ---*/ 3/*--------------------------------------------------------------------*/ 4 5/* 6 This file is part of DRD, a thread error detector. 7 8 Copyright (C) 2006-2012 Bart Van Assche <bvanassche@acm.org>. 9 10 This program is free software; you can redistribute it and/or 11 modify it under the terms of the GNU General Public License as 12 published by the Free Software Foundation; either version 2 of the 13 License, or (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, but 16 WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 23 02111-1307, USA. 24 25 The GNU General Public License is contained in the file COPYING. 26*/ 27 28/* --------------------------------------------------------------------- 29 ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU. 30 31 These functions are not called directly - they're the targets of code 32 redirection or load notifications (see pub_core_redir.h for info). 33 They're named weirdly so that the intercept code can find them when the 34 shared object is initially loaded. 35 36 Note that this filename has the "drd_" prefix because it can appear 37 in stack traces, and the "drd_" makes it a little clearer that it 38 originates from Valgrind. 39 ------------------------------------------------------------------ */ 40 41/* 42 * Define _GNU_SOURCE to make sure that pthread_spinlock_t is available when 43 * compiling with older glibc versions (2.3 or before). 44 */ 45#ifndef _GNU_SOURCE 46#define _GNU_SOURCE 47#endif 48 49#include <assert.h> /* assert() */ 50#include <errno.h> 51#include <pthread.h> /* pthread_mutex_t */ 52#include <semaphore.h> /* sem_t */ 53#include <stdint.h> /* uintptr_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#ifdef HAVE_USABLE_LINUX_FUTEX_H 59#include <asm/unistd.h> /* __NR_futex */ 60#include <linux/futex.h> /* FUTEX_WAIT */ 61#ifndef FUTEX_PRIVATE_FLAG 62#define FUTEX_PRIVATE_FLAG 0 63#endif 64#endif 65#include "drd_basics.h" /* DRD_() */ 66#include "drd_clientreq.h" 67#include "pub_tool_redir.h" /* VG_WRAP_FUNCTION_ZZ() */ 68 69 70/* 71 * Notes regarding thread creation: 72 * - sg_init() runs on the context of the created thread and copies the vector 73 * clock of the creator thread. This only works reliably if the creator 74 * thread waits until this copy has been performed. 75 * - DRD_(thread_compute_minimum_vc)() does not take the vector clocks into 76 * account that are involved in thread creation and for which the 77 * corresponding thread has not yet been created. So not waiting until the 78 * created thread has been started would make it possible that segments get 79 * discarded that should not yet be discarded. Or: some data races are not 80 * detected. 81 */ 82 83/** 84 * Macro for generating a Valgrind interception function. 85 * @param[in] ret_ty Return type of the function to be generated. 86 * @param[in] zf Z-encoded name of the interception function. 87 * @param[in] implf Name of the function that implements the intercept. 88 * @param[in] arg_decl Argument declaration list enclosed in parentheses. 89 * @param[in] argl Argument list enclosed in parentheses. 90 */ 91#ifdef VGO_darwin 92static int never_true; 93#define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl) \ 94 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl; \ 95 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl \ 96 { \ 97 ret_ty pth_func_result = implf argl; \ 98 /* Apparently inserting a function call in wrapper functions */ \ 99 /* is sufficient to avoid misaligned stack errors. */ \ 100 if (never_true) \ 101 fflush(stdout); \ 102 return pth_func_result; \ 103 } 104#else 105#define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl) \ 106 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl; \ 107 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl \ 108 { return implf argl; } 109#endif 110 111/** 112 * Macro for generating three Valgrind interception functions: one with the 113 * Z-encoded name zf, one with ZAZa ("@*") appended to the name zf and one 114 * with ZDZa ("$*") appended to the name zf. The second generated interception 115 * function will intercept versioned symbols on Linux, and the third will 116 * intercept versioned symbols on Darwin. 117 */ 118#define PTH_FUNCS(ret_ty, zf, implf, argl_decl, argl) \ 119 PTH_FUNC(ret_ty, zf, implf, argl_decl, argl); \ 120 PTH_FUNC(ret_ty, zf ## ZAZa, implf, argl_decl, argl); \ 121 PTH_FUNC(ret_ty, zf ## ZDZa, implf, argl_decl, argl); 122 123/* 124 * Not inlining one of the intercept functions will cause the regression 125 * tests to fail because this would cause an additional stackfram to appear 126 * in the output. The __always_inline macro guarantees that inlining will 127 * happen, even when compiling with optimization disabled. 128 */ 129#undef __always_inline /* since already defined in <cdefs.h> */ 130#if __GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 2 131#define __always_inline __inline__ __attribute__((always_inline)) 132#else 133#define __always_inline __inline__ 134#endif 135 136/* Local data structures. */ 137 138typedef struct { 139 pthread_mutex_t mutex; 140 int counter; 141 int waiters; 142} DrdSema; 143 144typedef struct 145{ 146 void* (*start)(void*); 147 void* arg; 148 int detachstate; 149 DrdSema* wrapper_started; 150} DrdPosixThreadArgs; 151 152 153/* Local function declarations. */ 154 155static void DRD_(init)(void) __attribute__((constructor)); 156static void DRD_(check_threading_library)(void); 157static void DRD_(set_main_thread_state)(void); 158static void DRD_(sema_init)(DrdSema* sema); 159static void DRD_(sema_destroy)(DrdSema* sema); 160static void DRD_(sema_down)(DrdSema* sema); 161static void DRD_(sema_up)(DrdSema* sema); 162 163 164/* Function definitions. */ 165 166/** 167 * Shared library initialization function. The function init() is called after 168 * dlopen() has loaded the shared library with DRD client intercepts because 169 * the constructor attribute was specified in the declaration of this function. 170 * Note: do specify the -nostdlib option to gcc when linking this code into a 171 * shared library because doing so would cancel the effect of the constructor 172 * attribute ! Using the gcc option -nodefaultlibs is fine because this last 173 * option preserves the shared library initialization code that calls 174 * constructor and destructor functions. 175 */ 176static void DRD_(init)(void) 177{ 178 DRD_(check_threading_library)(); 179 DRD_(set_main_thread_state)(); 180} 181 182static void DRD_(sema_init)(DrdSema* sema) 183{ 184 DRD_IGNORE_VAR(sema->counter); 185 pthread_mutex_init(&sema->mutex, NULL); 186 sema->counter = 0; 187 sema->waiters = 0; 188} 189 190static void DRD_(sema_destroy)(DrdSema* sema) 191{ 192 pthread_mutex_destroy(&sema->mutex); 193} 194 195static void DRD_(sema_down)(DrdSema* sema) 196{ 197 int res = ENOSYS; 198 199 pthread_mutex_lock(&sema->mutex); 200 if (sema->counter == 0) { 201 sema->waiters++; 202 while (sema->counter == 0) { 203 pthread_mutex_unlock(&sema->mutex); 204#ifdef HAVE_USABLE_LINUX_FUTEX_H 205 if (syscall(__NR_futex, (UWord)&sema->counter, 206 FUTEX_WAIT | FUTEX_PRIVATE_FLAG, 0) == 0) 207 res = 0; 208 else 209 res = errno; 210#endif 211 /* 212 * Invoke sched_yield() on non-Linux systems, if the futex syscall has 213 * not been invoked or if this code has been built on a Linux system 214 * where __NR_futex is defined and is run on a Linux system that does 215 * not support the futex syscall. 216 */ 217 if (res != 0 && res != EWOULDBLOCK) 218 sched_yield(); 219 pthread_mutex_lock(&sema->mutex); 220 } 221 sema->waiters--; 222 } 223 sema->counter--; 224 pthread_mutex_unlock(&sema->mutex); 225} 226 227static void DRD_(sema_up)(DrdSema* sema) 228{ 229 pthread_mutex_lock(&sema->mutex); 230 sema->counter++; 231#ifdef HAVE_USABLE_LINUX_FUTEX_H 232 if (sema->waiters > 0) 233 syscall(__NR_futex, (UWord)&sema->counter, 234 FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1); 235#endif 236 pthread_mutex_unlock(&sema->mutex); 237} 238 239/** 240 * POSIX threads and DRD each have their own mutex type identification. 241 * Convert POSIX threads' mutex type to DRD's mutex type. In the code below 242 * if-statements are used to test the value of 'kind' instead of a switch 243 * statement because some of the PTHREAD_MUTEX_ macro's may have the same 244 * value. 245 */ 246static MutexT DRD_(pthread_to_drd_mutex_type)(const int kind) 247{ 248 if (kind == PTHREAD_MUTEX_RECURSIVE) 249 return mutex_type_recursive_mutex; 250 else if (kind == PTHREAD_MUTEX_ERRORCHECK) 251 return mutex_type_errorcheck_mutex; 252 else if (kind == PTHREAD_MUTEX_NORMAL) 253 return mutex_type_default_mutex; 254 else if (kind == PTHREAD_MUTEX_DEFAULT) 255 return mutex_type_default_mutex; 256#if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP) 257 else if (kind == PTHREAD_MUTEX_ADAPTIVE_NP) 258 return mutex_type_default_mutex; 259#endif 260 else 261 { 262 return mutex_type_invalid_mutex; 263 } 264} 265 266#define IS_ALIGNED(p) (((uintptr_t)(p) & (sizeof(*(p)) - 1)) == 0) 267 268/** 269 * Read the mutex type stored in the client memory used for the mutex 270 * implementation. 271 * 272 * @note This function depends on the implementation of the POSIX threads 273 * library -- the POSIX standard does not define the name of the member in 274 * which the mutex type is stored. 275 * @note The function mutex_type() has been declared inline in order 276 * to avoid that it shows up in call stacks (drd/tests/...exp* files). 277 * @note glibc stores the mutex type in the lowest two bits, and uses the 278 * higher bits for flags like PTHREAD_MUTEXATTR_FLAG_ROBUST and 279 * PTHREAD_MUTEXATTR_FLAG_PSHARED. 280 */ 281static __always_inline MutexT DRD_(mutex_type)(pthread_mutex_t* mutex) 282{ 283#if defined(HAVE_PTHREAD_MUTEX_T__M_KIND) 284 /* glibc + LinuxThreads. */ 285 if (IS_ALIGNED(&mutex->__m_kind)) 286 { 287 const int kind = mutex->__m_kind & 3; 288 return DRD_(pthread_to_drd_mutex_type)(kind); 289 } 290#elif defined(HAVE_PTHREAD_MUTEX_T__DATA__KIND) 291 /* glibc + NPTL. */ 292 if (IS_ALIGNED(&mutex->__data.__kind)) 293 { 294 const int kind = mutex->__data.__kind & 3; 295 return DRD_(pthread_to_drd_mutex_type)(kind); 296 } 297#else 298 /* 299 * Another POSIX threads implementation. The mutex type won't be printed 300 * when enabling --trace-mutex=yes. 301 */ 302#endif 303 return mutex_type_unknown; 304} 305 306/** 307 * Tell DRD whether 'tid' is a joinable thread or a detached thread. 308 */ 309static void DRD_(set_joinable)(const pthread_t tid, const int joinable) 310{ 311 assert(joinable == 0 || joinable == 1); 312 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__SET_JOINABLE, 313 tid, joinable, 0, 0, 0); 314} 315 316/** Tell DRD that the calling thread is about to enter pthread_create(). */ 317static __always_inline void DRD_(entering_pthread_create)(void) 318{ 319 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__ENTERING_PTHREAD_CREATE, 320 0, 0, 0, 0, 0); 321} 322 323/** Tell DRD that the calling thread has left pthread_create(). */ 324static __always_inline void DRD_(left_pthread_create)(void) 325{ 326 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LEFT_PTHREAD_CREATE, 327 0, 0, 0, 0, 0); 328} 329 330/** 331 * Entry point for newly created threads. This function is called from the 332 * thread created by pthread_create(). 333 */ 334static void* DRD_(thread_wrapper)(void* arg) 335{ 336 DrdPosixThreadArgs* arg_ptr; 337 DrdPosixThreadArgs arg_copy; 338 339 arg_ptr = (DrdPosixThreadArgs*)arg; 340 arg_copy = *arg_ptr; 341 342 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__SET_PTHREADID, 343 pthread_self(), 0, 0, 0, 0); 344 345 DRD_(set_joinable)(pthread_self(), 346 arg_copy.detachstate == PTHREAD_CREATE_JOINABLE); 347 348 /* 349 * Only set 'wrapper_started' after VG_USERREQ__SET_PTHREADID and 350 * DRD_(set_joinable)() have been invoked to avoid a race with 351 * a pthread_detach() invocation for this thread from another thread. 352 */ 353 DRD_(sema_up)(arg_copy.wrapper_started); 354 355 return (arg_copy.start)(arg_copy.arg); 356} 357 358/** 359 * Return 1 if the LinuxThreads implementation of POSIX Threads has been 360 * detected, and 0 otherwise. 361 * 362 * @see For more information about the confstr() function, see also 363 * http://www.opengroup.org/onlinepubs/009695399/functions/confstr.html 364 */ 365static int DRD_(detected_linuxthreads)(void) 366{ 367#if defined(linux) 368#if defined(_CS_GNU_LIBPTHREAD_VERSION) 369 /* Linux with a recent glibc. */ 370 HChar buffer[256]; 371 unsigned len; 372 len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer)); 373 assert(len <= sizeof(buffer)); 374 return len > 0 && buffer[0] == 'l'; 375#else 376 /* Linux without _CS_GNU_LIBPTHREAD_VERSION: most likely LinuxThreads. */ 377 return 1; 378#endif 379#else 380 /* Another OS than Linux, hence no LinuxThreads. */ 381 return 0; 382#endif 383} 384 385/** 386 * Stop and print an error message in case a non-supported threading 387 * library implementation (LinuxThreads) has been detected. 388 */ 389static void DRD_(check_threading_library)(void) 390{ 391 if (DRD_(detected_linuxthreads)()) 392 { 393 if (getenv("LD_ASSUME_KERNEL")) 394 { 395 fprintf(stderr, 396"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n" 397"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n" 398"after having unset the environment variable LD_ASSUME_KERNEL. Giving up.\n" 399); 400 } 401 else 402 { 403 fprintf(stderr, 404"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n" 405"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n" 406"after having upgraded to a newer version of your Linux distribution.\n" 407"Giving up.\n" 408); 409 } 410 abort(); 411 } 412} 413 414/** 415 * The main thread is the only thread not created by pthread_create(). 416 * Update DRD's state information about the main thread. 417 */ 418static void DRD_(set_main_thread_state)(void) 419{ 420 // Make sure that DRD knows about the main thread's POSIX thread ID. 421 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__SET_PTHREADID, 422 pthread_self(), 0, 0, 0, 0); 423} 424 425/* 426 * Note: as of today there exist three different versions of pthread_create 427 * in Linux: 428 * - pthread_create@GLIBC_2.0 429 * - pthread_create@@GLIBC_2.1 430 * - pthread_create@@GLIBC_2.2.5 431 * As an example, in libpthread-2.3.4 both pthread_create@GLIBC_2.0 and 432 * pthread_create@@GLIBC_2.1 are defined, while in libpthread-2.9 all three 433 * versions have been implemented. In any glibc version where more than one 434 * pthread_create function has been implemented, older versions call the 435 * newer versions. Or: the pthread_create* wrapper defined below can be 436 * called recursively. Any code in this wrapper should take this in account. 437 * As an example, it is not safe to invoke the DRD_STOP_RECORDING 438 * / DRD_START_RECORDING client requests from the pthread_create wrapper. 439 * See also the implementation of pthread_create@GLIBC_2.0 in 440 * glibc-2.9/nptl/pthread_create.c. 441 */ 442 443static __always_inline 444int pthread_create_intercept(pthread_t* thread, const pthread_attr_t* attr, 445 void* (*start)(void*), void* arg) 446{ 447 int ret; 448 OrigFn fn; 449 DrdSema wrapper_started; 450 DrdPosixThreadArgs thread_args; 451 452 VALGRIND_GET_ORIG_FN(fn); 453 454 DRD_(sema_init)(&wrapper_started); 455 thread_args.start = start; 456 thread_args.arg = arg; 457 thread_args.wrapper_started = &wrapper_started; 458 /* 459 * Find out whether the thread will be started as a joinable thread 460 * or as a detached thread. If no thread attributes have been specified, 461 * this means that the new thread will be started as a joinable thread. 462 */ 463 thread_args.detachstate = PTHREAD_CREATE_JOINABLE; 464 if (attr) 465 { 466 if (pthread_attr_getdetachstate(attr, &thread_args.detachstate) != 0) 467 assert(0); 468 } 469 assert(thread_args.detachstate == PTHREAD_CREATE_JOINABLE 470 || thread_args.detachstate == PTHREAD_CREATE_DETACHED); 471 472 DRD_(entering_pthread_create)(); 473 CALL_FN_W_WWWW(ret, fn, thread, attr, DRD_(thread_wrapper), &thread_args); 474 DRD_(left_pthread_create)(); 475 476 if (ret == 0) { 477 /* Wait until the thread wrapper started. */ 478 DRD_(sema_down)(&wrapper_started); 479 } 480 481 DRD_(sema_destroy)(&wrapper_started); 482 483 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DRD_START_NEW_SEGMENT, 484 pthread_self(), 0, 0, 0, 0); 485 486 return ret; 487} 488 489PTH_FUNCS(int, pthreadZucreate, pthread_create_intercept, 490 (pthread_t *thread, const pthread_attr_t *attr, 491 void *(*start) (void *), void *arg), 492 (thread, attr, start, arg)); 493 494static __always_inline 495int pthread_join_intercept(pthread_t pt_joinee, void **thread_return) 496{ 497 int ret; 498 OrigFn fn; 499 500 VALGRIND_GET_ORIG_FN(fn); 501 /* 502 * Avoid that the sys_futex(td->tid) call invoked by the NPTL pthread_join() 503 * implementation triggers a (false positive) race report. 504 */ 505 ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); 506 CALL_FN_W_WW(ret, fn, pt_joinee, thread_return); 507 if (ret == 0) 508 { 509 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_THREAD_JOIN, 510 pt_joinee, 0, 0, 0, 0); 511 } 512 ANNOTATE_IGNORE_READS_AND_WRITES_END(); 513 return ret; 514} 515 516PTH_FUNCS(int, pthreadZujoin, pthread_join_intercept, 517 (pthread_t pt_joinee, void **thread_return), 518 (pt_joinee, thread_return)); 519 520static __always_inline 521int pthread_detach_intercept(pthread_t pt_thread) 522{ 523 int ret; 524 OrigFn fn; 525 526 VALGRIND_GET_ORIG_FN(fn); 527 CALL_FN_W_W(ret, fn, pt_thread); 528 DRD_(set_joinable)(pt_thread, 0); 529 530 return ret; 531} 532 533PTH_FUNCS(int, pthreadZudetach, pthread_detach_intercept, 534 (pthread_t thread), (thread)); 535 536// NOTE: be careful to intercept only pthread_cancel() and not 537// pthread_cancel_init() on Linux. 538 539static __always_inline 540int pthread_cancel_intercept(pthread_t pt_thread) 541{ 542 int ret; 543 OrigFn fn; 544 VALGRIND_GET_ORIG_FN(fn); 545 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_THREAD_CANCEL, 546 pt_thread, 0, 0, 0, 0); 547 CALL_FN_W_W(ret, fn, pt_thread); 548 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_THREAD_CANCEL, 549 pt_thread, ret==0, 0, 0, 0); 550 return ret; 551} 552 553PTH_FUNCS(int, pthreadZucancel, pthread_cancel_intercept, 554 (pthread_t thread), (thread)) 555 556static __always_inline 557int pthread_once_intercept(pthread_once_t *once_control, 558 void (*init_routine)(void)) 559{ 560 int ret; 561 OrigFn fn; 562 VALGRIND_GET_ORIG_FN(fn); 563 /* 564 * Ignore any data races triggered by the implementation of pthread_once(). 565 * Necessary for Darwin. This is not necessary for Linux but doesn't have 566 * any known adverse effects. 567 */ 568 DRD_IGNORE_VAR(*once_control); 569 ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); 570 CALL_FN_W_WW(ret, fn, once_control, init_routine); 571 ANNOTATE_IGNORE_READS_AND_WRITES_END(); 572 DRD_STOP_IGNORING_VAR(*once_control); 573 return ret; 574} 575 576PTH_FUNCS(int, pthreadZuonce, pthread_once_intercept, 577 (pthread_once_t *once_control, void (*init_routine)(void)), 578 (once_control, init_routine)); 579 580static __always_inline 581int pthread_mutex_init_intercept(pthread_mutex_t *mutex, 582 const pthread_mutexattr_t* attr) 583{ 584 int ret; 585 OrigFn fn; 586 int mt; 587 VALGRIND_GET_ORIG_FN(fn); 588 mt = PTHREAD_MUTEX_DEFAULT; 589 if (attr) 590 pthread_mutexattr_gettype(attr, &mt); 591 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_INIT, 592 mutex, DRD_(pthread_to_drd_mutex_type)(mt), 593 0, 0, 0); 594 CALL_FN_W_WW(ret, fn, mutex, attr); 595 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_INIT, 596 mutex, 0, 0, 0, 0); 597 return ret; 598} 599 600PTH_FUNCS(int, pthreadZumutexZuinit, pthread_mutex_init_intercept, 601 (pthread_mutex_t *mutex, const pthread_mutexattr_t* attr), 602 (mutex, attr)); 603 604static __always_inline 605int pthread_mutex_destroy_intercept(pthread_mutex_t* mutex) 606{ 607 int ret; 608 OrigFn fn; 609 VALGRIND_GET_ORIG_FN(fn); 610 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_DESTROY, 611 mutex, 0, 0, 0, 0); 612 CALL_FN_W_W(ret, fn, mutex); 613 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_DESTROY, 614 mutex, DRD_(mutex_type)(mutex), 0, 0, 0); 615 return ret; 616} 617 618PTH_FUNCS(int, pthreadZumutexZudestroy, pthread_mutex_destroy_intercept, 619 (pthread_mutex_t *mutex), (mutex)); 620 621static __always_inline 622int pthread_mutex_lock_intercept(pthread_mutex_t* mutex) 623{ 624 int ret; 625 OrigFn fn; 626 VALGRIND_GET_ORIG_FN(fn); 627 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK, 628 mutex, DRD_(mutex_type)(mutex), 0, 0, 0); 629 CALL_FN_W_W(ret, fn, mutex); 630 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK, 631 mutex, ret == 0, 0, 0, 0); 632 return ret; 633} 634 635PTH_FUNCS(int, pthreadZumutexZulock, pthread_mutex_lock_intercept, 636 (pthread_mutex_t *mutex), (mutex)); 637 638static __always_inline 639int pthread_mutex_trylock_intercept(pthread_mutex_t* mutex) 640{ 641 int ret; 642 OrigFn fn; 643 VALGRIND_GET_ORIG_FN(fn); 644 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK, 645 mutex, DRD_(mutex_type)(mutex), 1, 0, 0); 646 CALL_FN_W_W(ret, fn, mutex); 647 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK, 648 mutex, ret == 0, 0, 0, 0); 649 return ret; 650} 651 652PTH_FUNCS(int, pthreadZumutexZutrylock, pthread_mutex_trylock_intercept, 653 (pthread_mutex_t *mutex), (mutex)); 654 655static __always_inline 656int pthread_mutex_timedlock_intercept(pthread_mutex_t *mutex, 657 const struct timespec *abs_timeout) 658{ 659 int ret; 660 OrigFn fn; 661 VALGRIND_GET_ORIG_FN(fn); 662 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK, 663 mutex, DRD_(mutex_type)(mutex), 0, 0, 0); 664 CALL_FN_W_WW(ret, fn, mutex, abs_timeout); 665 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK, 666 mutex, ret == 0, 0, 0, 0); 667 return ret; 668} 669 670PTH_FUNCS(int, pthreadZumutexZutimedlock, pthread_mutex_timedlock_intercept, 671 (pthread_mutex_t *mutex, const struct timespec *abs_timeout), 672 (mutex, abs_timeout)); 673 674static __always_inline 675int pthread_mutex_unlock_intercept(pthread_mutex_t *mutex) 676{ 677 int ret; 678 OrigFn fn; 679 VALGRIND_GET_ORIG_FN(fn); 680 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_UNLOCK, 681 mutex, DRD_(mutex_type)(mutex), 0, 0, 0); 682 CALL_FN_W_W(ret, fn, mutex); 683 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_UNLOCK, 684 mutex, 0, 0, 0, 0); 685 return ret; 686} 687 688PTH_FUNCS(int, pthreadZumutexZuunlock, pthread_mutex_unlock_intercept, 689 (pthread_mutex_t *mutex), (mutex)); 690 691static __always_inline 692int pthread_cond_init_intercept(pthread_cond_t* cond, 693 const pthread_condattr_t* attr) 694{ 695 int ret; 696 OrigFn fn; 697 VALGRIND_GET_ORIG_FN(fn); 698 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_INIT, 699 cond, 0, 0, 0, 0); 700 CALL_FN_W_WW(ret, fn, cond, attr); 701 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_INIT, 702 cond, 0, 0, 0, 0); 703 return ret; 704} 705 706PTH_FUNCS(int, pthreadZucondZuinit, pthread_cond_init_intercept, 707 (pthread_cond_t* cond, const pthread_condattr_t* attr), 708 (cond, attr)); 709 710static __always_inline 711int pthread_cond_destroy_intercept(pthread_cond_t* cond) 712{ 713 int ret; 714 OrigFn fn; 715 VALGRIND_GET_ORIG_FN(fn); 716 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_DESTROY, 717 cond, 0, 0, 0, 0); 718 CALL_FN_W_W(ret, fn, cond); 719 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_DESTROY, 720 cond, 0, 0, 0, 0); 721 return ret; 722} 723 724PTH_FUNCS(int, pthreadZucondZudestroy, pthread_cond_destroy_intercept, 725 (pthread_cond_t* cond), (cond)); 726 727static __always_inline 728int pthread_cond_wait_intercept(pthread_cond_t *cond, pthread_mutex_t *mutex) 729{ 730 int ret; 731 OrigFn fn; 732 VALGRIND_GET_ORIG_FN(fn); 733 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_WAIT, 734 cond, mutex, DRD_(mutex_type)(mutex), 0, 0); 735 CALL_FN_W_WW(ret, fn, cond, mutex); 736 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_WAIT, 737 cond, mutex, 1, 0, 0); 738 return ret; 739} 740 741PTH_FUNCS(int, pthreadZucondZuwait, pthread_cond_wait_intercept, 742 (pthread_cond_t *cond, pthread_mutex_t *mutex), 743 (cond, mutex)); 744 745static __always_inline 746int pthread_cond_timedwait_intercept(pthread_cond_t *cond, 747 pthread_mutex_t *mutex, 748 const struct timespec* abstime) 749{ 750 int ret; 751 OrigFn fn; 752 VALGRIND_GET_ORIG_FN(fn); 753 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_WAIT, 754 cond, mutex, DRD_(mutex_type)(mutex), 0, 0); 755 CALL_FN_W_WWW(ret, fn, cond, mutex, abstime); 756 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_WAIT, 757 cond, mutex, 1, 0, 0); 758 return ret; 759} 760 761PTH_FUNCS(int, pthreadZucondZutimedwait, pthread_cond_timedwait_intercept, 762 (pthread_cond_t *cond, pthread_mutex_t *mutex, 763 const struct timespec* abstime), 764 (cond, mutex, abstime)); 765 766// NOTE: be careful to intercept only pthread_cond_signal() and not Darwin's 767// pthread_cond_signal_thread_np(). The former accepts one argument; the latter 768// two. Intercepting all pthread_cond_signal* functions will cause only one 769// argument to be passed to pthread_cond_signal_np() and hence will cause this 770// last function to crash. 771 772static __always_inline 773int pthread_cond_signal_intercept(pthread_cond_t* cond) 774{ 775 int ret; 776 OrigFn fn; 777 VALGRIND_GET_ORIG_FN(fn); 778 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_SIGNAL, 779 cond, 0, 0, 0, 0); 780 CALL_FN_W_W(ret, fn, cond); 781 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_SIGNAL, 782 cond, 0, 0, 0, 0); 783 return ret; 784} 785 786PTH_FUNCS(int, pthreadZucondZusignal, pthread_cond_signal_intercept, 787 (pthread_cond_t* cond), (cond)); 788 789static __always_inline 790int pthread_cond_broadcast_intercept(pthread_cond_t* cond) 791{ 792 int ret; 793 OrigFn fn; 794 VALGRIND_GET_ORIG_FN(fn); 795 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_COND_BROADCAST, 796 cond, 0, 0, 0, 0); 797 CALL_FN_W_W(ret, fn, cond); 798 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_COND_BROADCAST, 799 cond, 0, 0, 0, 0); 800 return ret; 801} 802 803PTH_FUNCS(int, pthreadZucondZubroadcast, pthread_cond_broadcast_intercept, 804 (pthread_cond_t* cond), (cond)); 805 806#if defined(HAVE_PTHREAD_SPIN_LOCK) \ 807 && !defined(DISABLE_PTHREAD_SPINLOCK_INTERCEPT) 808static __always_inline 809int pthread_spin_init_intercept(pthread_spinlock_t *spinlock, int pshared) 810{ 811 int ret; 812 OrigFn fn; 813 VALGRIND_GET_ORIG_FN(fn); 814 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK, 815 spinlock, 0, 0, 0, 0); 816 CALL_FN_W_WW(ret, fn, spinlock, pshared); 817 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK, 818 spinlock, 0, 0, 0, 0); 819 return ret; 820} 821 822PTH_FUNCS(int, pthreadZuspinZuinit, pthread_spin_init_intercept, 823 (pthread_spinlock_t *spinlock, int pshared), (spinlock, pshared)); 824 825static __always_inline 826int pthread_spin_destroy_intercept(pthread_spinlock_t *spinlock) 827{ 828 int ret; 829 OrigFn fn; 830 VALGRIND_GET_ORIG_FN(fn); 831 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_DESTROY, 832 spinlock, 0, 0, 0, 0); 833 CALL_FN_W_W(ret, fn, spinlock); 834 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_DESTROY, 835 spinlock, mutex_type_spinlock, 0, 0, 0); 836 return ret; 837} 838 839PTH_FUNCS(int, pthreadZuspinZudestroy, pthread_spin_destroy_intercept, 840 (pthread_spinlock_t *spinlock), (spinlock)); 841 842static __always_inline 843int pthread_spin_lock_intercept(pthread_spinlock_t *spinlock) 844{ 845 int ret; 846 OrigFn fn; 847 VALGRIND_GET_ORIG_FN(fn); 848 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK, 849 spinlock, mutex_type_spinlock, 0, 0, 0); 850 CALL_FN_W_W(ret, fn, spinlock); 851 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK, 852 spinlock, ret == 0, 0, 0, 0); 853 return ret; 854} 855 856PTH_FUNCS(int, pthreadZuspinZulock, pthread_spin_lock_intercept, 857 (pthread_spinlock_t *spinlock), (spinlock)); 858 859static __always_inline 860int pthread_spin_trylock_intercept(pthread_spinlock_t *spinlock) 861{ 862 int ret; 863 OrigFn fn; 864 VALGRIND_GET_ORIG_FN(fn); 865 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_MUTEX_LOCK, 866 spinlock, mutex_type_spinlock, 0, 0, 0); 867 CALL_FN_W_W(ret, fn, spinlock); 868 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_MUTEX_LOCK, 869 spinlock, ret == 0, 0, 0, 0); 870 return ret; 871} 872 873PTH_FUNCS(int, pthreadZuspinZutrylock, pthread_spin_trylock_intercept, 874 (pthread_spinlock_t *spinlock), (spinlock)); 875 876static __always_inline 877int pthread_spin_unlock_intercept(pthread_spinlock_t *spinlock) 878{ 879 int ret; 880 OrigFn fn; 881 VALGRIND_GET_ORIG_FN(fn); 882 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK, 883 spinlock, mutex_type_spinlock, 0, 0, 0); 884 CALL_FN_W_W(ret, fn, spinlock); 885 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK, 886 spinlock, 0, 0, 0, 0); 887 return ret; 888} 889 890PTH_FUNCS(int, pthreadZuspinZuunlock, pthread_spin_unlock_intercept, 891 (pthread_spinlock_t *spinlock), (spinlock)); 892#endif // HAVE_PTHREAD_SPIN_LOCK 893 894 895#if defined(HAVE_PTHREAD_BARRIER_INIT) 896static __always_inline 897int pthread_barrier_init_intercept(pthread_barrier_t* barrier, 898 const pthread_barrierattr_t* attr, 899 unsigned count) 900{ 901 int ret; 902 OrigFn fn; 903 VALGRIND_GET_ORIG_FN(fn); 904 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_BARRIER_INIT, 905 barrier, pthread_barrier, count, 0, 0); 906 CALL_FN_W_WWW(ret, fn, barrier, attr, count); 907 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_BARRIER_INIT, 908 barrier, pthread_barrier, 0, 0, 0); 909 return ret; 910} 911 912PTH_FUNCS(int, pthreadZubarrierZuinit, pthread_barrier_init_intercept, 913 (pthread_barrier_t* barrier, const pthread_barrierattr_t* attr, 914 unsigned count), (barrier, attr, count)); 915 916static __always_inline 917int pthread_barrier_destroy_intercept(pthread_barrier_t* barrier) 918{ 919 int ret; 920 OrigFn fn; 921 VALGRIND_GET_ORIG_FN(fn); 922 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_BARRIER_DESTROY, 923 barrier, pthread_barrier, 0, 0, 0); 924 CALL_FN_W_W(ret, fn, barrier); 925 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_BARRIER_DESTROY, 926 barrier, pthread_barrier, 0, 0, 0); 927 return ret; 928} 929 930PTH_FUNCS(int, pthreadZubarrierZudestroy, pthread_barrier_destroy_intercept, 931 (pthread_barrier_t* barrier), (barrier)); 932 933static __always_inline 934int pthread_barrier_wait_intercept(pthread_barrier_t* barrier) 935{ 936 int ret; 937 OrigFn fn; 938 VALGRIND_GET_ORIG_FN(fn); 939 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_BARRIER_WAIT, 940 barrier, pthread_barrier, 0, 0, 0); 941 CALL_FN_W_W(ret, fn, barrier); 942 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_BARRIER_WAIT, 943 barrier, pthread_barrier, 944 ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD, 945 ret == PTHREAD_BARRIER_SERIAL_THREAD, 0); 946 return ret; 947} 948 949PTH_FUNCS(int, pthreadZubarrierZuwait, pthread_barrier_wait_intercept, 950 (pthread_barrier_t* barrier), (barrier)); 951#endif // HAVE_PTHREAD_BARRIER_INIT 952 953 954static __always_inline 955int sem_init_intercept(sem_t *sem, int pshared, unsigned int value) 956{ 957 int ret; 958 OrigFn fn; 959 VALGRIND_GET_ORIG_FN(fn); 960 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_INIT, 961 sem, pshared, value, 0, 0); 962 CALL_FN_W_WWW(ret, fn, sem, pshared, value); 963 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_INIT, 964 sem, 0, 0, 0, 0); 965 return ret; 966} 967 968PTH_FUNCS(int, semZuinit, sem_init_intercept, 969 (sem_t *sem, int pshared, unsigned int value), (sem, pshared, value)); 970 971static __always_inline 972int sem_destroy_intercept(sem_t *sem) 973{ 974 int ret; 975 OrigFn fn; 976 VALGRIND_GET_ORIG_FN(fn); 977 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_DESTROY, 978 sem, 0, 0, 0, 0); 979 CALL_FN_W_W(ret, fn, sem); 980 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_DESTROY, 981 sem, 0, 0, 0, 0); 982 return ret; 983} 984 985PTH_FUNCS(int, semZudestroy, sem_destroy_intercept, (sem_t *sem), (sem)); 986 987static __always_inline 988sem_t* sem_open_intercept(const char *name, int oflag, mode_t mode, 989 unsigned int value) 990{ 991 sem_t *ret; 992 OrigFn fn; 993 VALGRIND_GET_ORIG_FN(fn); 994 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_OPEN, 995 name, oflag, mode, value, 0); 996 CALL_FN_W_WWWW(ret, fn, name, oflag, mode, value); 997 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_OPEN, 998 ret != SEM_FAILED ? ret : 0, 999 name, oflag, mode, value); 1000 return ret; 1001} 1002 1003PTH_FUNCS(sem_t *, semZuopen, sem_open_intercept, 1004 (const char *name, int oflag, mode_t mode, unsigned int value), 1005 (name, oflag, mode, value)); 1006 1007static __always_inline int sem_close_intercept(sem_t *sem) 1008{ 1009 int ret; 1010 OrigFn fn; 1011 VALGRIND_GET_ORIG_FN(fn); 1012 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_CLOSE, 1013 sem, 0, 0, 0, 0); 1014 CALL_FN_W_W(ret, fn, sem); 1015 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_CLOSE, 1016 sem, 0, 0, 0, 0); 1017 return ret; 1018} 1019 1020PTH_FUNCS(int, semZuclose, sem_close_intercept, (sem_t *sem), (sem)); 1021 1022static __always_inline int sem_wait_intercept(sem_t *sem) 1023{ 1024 int ret; 1025 OrigFn fn; 1026 VALGRIND_GET_ORIG_FN(fn); 1027 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_WAIT, 1028 sem, 0, 0, 0, 0); 1029 CALL_FN_W_W(ret, fn, sem); 1030 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_WAIT, 1031 sem, ret == 0, 0, 0, 0); 1032 return ret; 1033} 1034 1035PTH_FUNCS(int, semZuwait, sem_wait_intercept, (sem_t *sem), (sem)); 1036 1037static __always_inline int sem_trywait_intercept(sem_t *sem) 1038{ 1039 int ret; 1040 OrigFn fn; 1041 VALGRIND_GET_ORIG_FN(fn); 1042 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_WAIT, 1043 sem, 0, 0, 0, 0); 1044 CALL_FN_W_W(ret, fn, sem); 1045 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_WAIT, 1046 sem, ret == 0, 0, 0, 0); 1047 return ret; 1048} 1049 1050PTH_FUNCS(int, semZutrywait, sem_trywait_intercept, (sem_t *sem), (sem)); 1051 1052static __always_inline 1053int sem_timedwait_intercept(sem_t *sem, const struct timespec *abs_timeout) 1054{ 1055 int ret; 1056 OrigFn fn; 1057 VALGRIND_GET_ORIG_FN(fn); 1058 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_WAIT, 1059 sem, 0, 0, 0, 0); 1060 CALL_FN_W_WW(ret, fn, sem, abs_timeout); 1061 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_WAIT, 1062 sem, ret == 0, 0, 0, 0); 1063 return ret; 1064} 1065 1066PTH_FUNCS(int, semZutimedwait, sem_timedwait_intercept, 1067 (sem_t *sem, const struct timespec *abs_timeout), 1068 (sem, abs_timeout)); 1069 1070static __always_inline int sem_post_intercept(sem_t *sem) 1071{ 1072 int ret; 1073 OrigFn fn; 1074 VALGRIND_GET_ORIG_FN(fn); 1075 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_SEM_POST, 1076 sem, 0, 0, 0, 0); 1077 CALL_FN_W_W(ret, fn, sem); 1078 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_SEM_POST, 1079 sem, ret == 0, 0, 0, 0); 1080 return ret; 1081} 1082 1083PTH_FUNCS(int, semZupost, sem_post_intercept, (sem_t *sem), (sem)); 1084 1085/* Android's pthread.h doesn't say anything about rwlocks, hence these 1086 functions have to be conditionally compiled. */ 1087#if defined(HAVE_PTHREAD_RWLOCK_T) 1088 1089static __always_inline 1090int pthread_rwlock_init_intercept(pthread_rwlock_t* rwlock, 1091 const pthread_rwlockattr_t* attr) 1092{ 1093 int ret; 1094 OrigFn fn; 1095 VALGRIND_GET_ORIG_FN(fn); 1096 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_INIT, 1097 rwlock, 0, 0, 0, 0); 1098 CALL_FN_W_WW(ret, fn, rwlock, attr); 1099 return ret; 1100} 1101 1102PTH_FUNCS(int, 1103 pthreadZurwlockZuinit, pthread_rwlock_init_intercept, 1104 (pthread_rwlock_t* rwlock, const pthread_rwlockattr_t* attr), 1105 (rwlock, attr)); 1106 1107static __always_inline 1108int pthread_rwlock_destroy_intercept(pthread_rwlock_t* rwlock) 1109{ 1110 int ret; 1111 OrigFn fn; 1112 VALGRIND_GET_ORIG_FN(fn); 1113 CALL_FN_W_W(ret, fn, rwlock); 1114 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_DESTROY, 1115 rwlock, 0, 0, 0, 0); 1116 return ret; 1117} 1118 1119PTH_FUNCS(int, 1120 pthreadZurwlockZudestroy, pthread_rwlock_destroy_intercept, 1121 (pthread_rwlock_t* rwlock), (rwlock)); 1122 1123static __always_inline 1124int pthread_rwlock_rdlock_intercept(pthread_rwlock_t* rwlock) 1125{ 1126 int ret; 1127 OrigFn fn; 1128 VALGRIND_GET_ORIG_FN(fn); 1129 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_RDLOCK, 1130 rwlock, 0, 0, 0, 0); 1131 CALL_FN_W_W(ret, fn, rwlock); 1132 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_RDLOCK, 1133 rwlock, ret == 0, 0, 0, 0); 1134 return ret; 1135} 1136 1137PTH_FUNCS(int, 1138 pthreadZurwlockZurdlock, pthread_rwlock_rdlock_intercept, 1139 (pthread_rwlock_t* rwlock), (rwlock)); 1140 1141static __always_inline 1142int pthread_rwlock_wrlock_intercept(pthread_rwlock_t* rwlock) 1143{ 1144 int ret; 1145 OrigFn fn; 1146 VALGRIND_GET_ORIG_FN(fn); 1147 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_WRLOCK, 1148 rwlock, 0, 0, 0, 0); 1149 CALL_FN_W_W(ret, fn, rwlock); 1150 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_WRLOCK, 1151 rwlock, ret == 0, 0, 0, 0); 1152 return ret; 1153} 1154 1155PTH_FUNCS(int, 1156 pthreadZurwlockZuwrlock, pthread_rwlock_wrlock_intercept, 1157 (pthread_rwlock_t* rwlock), (rwlock)); 1158 1159static __always_inline 1160int pthread_rwlock_timedrdlock_intercept(pthread_rwlock_t* rwlock) 1161{ 1162 int ret; 1163 OrigFn fn; 1164 VALGRIND_GET_ORIG_FN(fn); 1165 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_RDLOCK, 1166 rwlock, 0, 0, 0, 0); 1167 CALL_FN_W_W(ret, fn, rwlock); 1168 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_RDLOCK, 1169 rwlock, ret == 0, 0, 0, 0); 1170 return ret; 1171} 1172 1173PTH_FUNCS(int, 1174 pthreadZurwlockZutimedrdlock, pthread_rwlock_timedrdlock_intercept, 1175 (pthread_rwlock_t* rwlock), (rwlock)); 1176 1177static __always_inline 1178int pthread_rwlock_timedwrlock_intercept(pthread_rwlock_t* rwlock) 1179{ 1180 int ret; 1181 OrigFn fn; 1182 VALGRIND_GET_ORIG_FN(fn); 1183 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_WRLOCK, 1184 rwlock, 0, 0, 0, 0); 1185 CALL_FN_W_W(ret, fn, rwlock); 1186 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_WRLOCK, 1187 rwlock, ret == 0, 0, 0, 0); 1188 return ret; 1189} 1190 1191PTH_FUNCS(int, 1192 pthreadZurwlockZutimedwrlock, pthread_rwlock_timedwrlock_intercept, 1193 (pthread_rwlock_t* rwlock), (rwlock)); 1194 1195static __always_inline 1196int pthread_rwlock_tryrdlock_intercept(pthread_rwlock_t* rwlock) 1197{ 1198 int ret; 1199 OrigFn fn; 1200 VALGRIND_GET_ORIG_FN(fn); 1201 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_RDLOCK, 1202 rwlock, 0, 0, 0, 0); 1203 CALL_FN_W_W(ret, fn, rwlock); 1204 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_RDLOCK, 1205 rwlock, ret == 0, 0, 0, 0); 1206 return ret; 1207} 1208 1209PTH_FUNCS(int, 1210 pthreadZurwlockZutryrdlock, pthread_rwlock_tryrdlock_intercept, 1211 (pthread_rwlock_t* rwlock), (rwlock)); 1212 1213static __always_inline 1214int pthread_rwlock_trywrlock_intercept(pthread_rwlock_t* rwlock) 1215{ 1216 int ret; 1217 OrigFn fn; 1218 VALGRIND_GET_ORIG_FN(fn); 1219 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_WRLOCK, 1220 rwlock, 0, 0, 0, 0); 1221 CALL_FN_W_W(ret, fn, rwlock); 1222 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_WRLOCK, 1223 rwlock, ret == 0, 0, 0, 0); 1224 return ret; 1225} 1226 1227PTH_FUNCS(int, 1228 pthreadZurwlockZutrywrlock, pthread_rwlock_trywrlock_intercept, 1229 (pthread_rwlock_t* rwlock), (rwlock)); 1230 1231static __always_inline 1232int pthread_rwlock_unlock_intercept(pthread_rwlock_t* rwlock) 1233{ 1234 int ret; 1235 OrigFn fn; 1236 VALGRIND_GET_ORIG_FN(fn); 1237 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__PRE_RWLOCK_UNLOCK, 1238 rwlock, 0, 0, 0, 0); 1239 CALL_FN_W_W(ret, fn, rwlock); 1240 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__POST_RWLOCK_UNLOCK, 1241 rwlock, ret == 0, 0, 0, 0); 1242 return ret; 1243} 1244 1245PTH_FUNCS(int, 1246 pthreadZurwlockZuunlock, pthread_rwlock_unlock_intercept, 1247 (pthread_rwlock_t* rwlock), (rwlock)); 1248 1249#endif /* defined(HAVE_PTHREAD_RWLOCK_T) */ 1250