/** Shared library initialization function: the _init() function is called * after dlopen() has loaded the shared library. This function must not * be declared static. */ static void init(void) { check_threading_library(); vg_set_main_thread_state(); /* glibc up to and including version 2.7 triggers conflicting accesses */ /* on stdout and stderr when sending output to one of these streams from */ /* more than one thread. Suppress data race reports on these objects. */ DRD_IGNORE_VAR(*stdout); DRD_IGNORE_VAR(*stderr); }
GCC_ATTR_CONSTRUCT __init static void init_hzp_free_lock(void) { #ifdef DRD_ME DRD_IGNORE_VAR(nr_free); DRD_IGNORE_VAR(hzp_threads); DRD_IGNORE_VAR(hzp_freelist); #endif if((errno = mutex_init(&hzp_free_lock))) diedie("couldn't init hzp free lock"); }
/** Shared library initialization function: the _init() function is called * after dlopen() has loaded the shared library. This function must not * be declared static. */ static void init(void) { check_threading_library(); vg_set_main_thread_state(); /* glibc up to and including version 2.8 triggers conflicting accesses */ /* on stdout and stderr when sending output to one of these streams from */ /* more than one thread. Suppress data race reports on these objects. */ DRD_IGNORE_VAR(*stdout); DRD_IGNORE_VAR(*stderr); #if defined(HAVE_LIBC_FILE_LOCK) DRD_IGNORE_VAR(*(pthread_mutex_t*)(stdout->_lock)); DRD_IGNORE_VAR(*(pthread_mutex_t*)(stderr->_lock)); #endif }
static void DRD_(sema_init)(DrdSema* sema) { DRD_IGNORE_VAR(sema->counter); pthread_mutex_init(&sema->mutex, NULL); sema->counter = 0; sema->waiters = 0; }
static void rwlock_init(rwlock_t* p) { DRD_IGNORE_VAR(*p); p->locked = 0; p->writer_count = 0; p->reader_count = 0; ANNOTATE_RWLOCK_CREATE(p); }
static void DRD_(sema_init)(DrdSema* sema) { DRD_IGNORE_VAR(*sema); pthread_mutex_init(&sema->mutex, NULL); DRD_(ignore_mutex_ordering)(&sema->mutex); sema->counter = 0; sema->waiters = 0; }
/* * hzp_alloc - lay TLS hzp struct in the TSD * * returns: true - everythings fine * false - ooops */ bool hzp_alloc(void) { #ifdef DRD_ME DRD_IGNORE_VAR(local_hzp); #endif local_hzp.flags.used = true; atomic_push(&hzp_threads.head, &local_hzp.lst); return true; }
// pthread_once PTH_FUNC(int, pthreadZuonceZa, // pthread_once* pthread_once_t *once_control, void (*init_routine)(void)) { int ret; OrigFn fn; VALGRIND_GET_ORIG_FN(fn); /* * Ignore any data races triggered by the implementation of pthread_once(). * Necessary for Darwin. This is not necessary for Linux but doesn't have * any known adverse effects. */ DRD_IGNORE_VAR(*once_control); CALL_FN_W_WW(ret, fn, once_control, init_routine); DRD_STOP_IGNORING_VAR(*once_control); return ret; }
static __always_inline int pthread_once_intercept(pthread_once_t *once_control, void (*init_routine)(void)) { int ret; OrigFn fn; VALGRIND_GET_ORIG_FN(fn); /* * Ignore any data races triggered by the implementation of pthread_once(). * Necessary for Darwin. This is not necessary for Linux but doesn't have * any known adverse effects. */ DRD_IGNORE_VAR(*once_control); ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); CALL_FN_W_WW(ret, fn, once_control, init_routine); ANNOTATE_IGNORE_READS_AND_WRITES_END(); DRD_STOP_IGNORING_VAR(*once_control); return ret; }
// pthread_create PTH_FUNC(int, pthreadZucreateZa, // pthread_create* pthread_t *thread, const pthread_attr_t *attr, void *(*start) (void *), void *arg) { int res; int ret; OrigFn fn; #if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK) DrdPosixThreadArgs thread_args; #endif DrdPosixThreadArgs* thread_args_p; VALGRIND_GET_ORIG_FN(fn); #if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK) thread_args_p = &thread_args; #else thread_args_p = malloc(sizeof(*thread_args_p)); #endif assert(thread_args_p); thread_args_p->start = start; thread_args_p->arg = arg; #if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) DRD_IGNORE_VAR(thread_args_p->wrapper_started); thread_args_p->wrapper_started = 0; #endif /* * Find out whether the thread will be started as a joinable thread * or as a detached thread. If no thread attributes have been specified, * this means that the new thread will be started as a joinable thread. */ thread_args_p->detachstate = PTHREAD_CREATE_JOINABLE; if (attr) { if (pthread_attr_getdetachstate(attr, &thread_args_p->detachstate) != 0) { assert(0); } } assert(thread_args_p->detachstate == PTHREAD_CREATE_JOINABLE || thread_args_p->detachstate == PTHREAD_CREATE_DETACHED); DRD_(entering_pthread_create)(); CALL_FN_W_WWWW(ret, fn, thread, attr, DRD_(thread_wrapper), thread_args_p); DRD_(left_pthread_create)(); #if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) if (ret == 0) { /* * Wait until the thread wrapper started. * @todo Find out why some regression tests fail if thread arguments are * passed via dynamically allocated memory and if the loop below is * removed. */ while (! thread_args_p->wrapper_started) { sched_yield(); } } #if defined(ALLOCATE_THREAD_ARGS_DYNAMICALLY) free(thread_args_p); #endif #endif VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_START_NEW_SEGMENT, pthread_self(), 0, 0, 0, 0); return ret; }