31
31
// Author: Paul Menage <opensource@google.com>
33
//-------------------------------------------------------------------
34
33
// Some wrappers for pthread functions so that we can be LD_PRELOADed
35
34
// against non-pthreads apps.
36
//-------------------------------------------------------------------
36
// This module will behave very strangely if some pthreads functions
37
// exist and others don't.
38
39
#include "config.h"
39
40
#include <assert.h>
41
#include <string.h> // for memcmp
41
42
// We don't actually need strings. But including this header seems to
42
43
// stop the compiler trying to short-circuit our pthreads existence
43
44
// tests and claiming that the address of a function is always
44
45
// non-zero. I have no idea why ...
46
47
#include "maybe_threads.h"
48
#include "base/basictypes.h"
50
// __THROW is defined in glibc systems. It means, counter-intuitively,
51
// "This function will never throw an exception." It's an optional
52
// optimization tool, but we may need to use it to match glibc prototypes.
53
#ifndef __THROW // I guess we're not on a glibc system
54
# define __THROW // __THROW is just an optimization, so ok to make it ""
57
// These are the methods we're going to conditionally include.
59
int pthread_key_create (pthread_key_t*, void (*)(void*))
60
__THROW ATTRIBUTE_WEAK;
61
void *pthread_getspecific(pthread_key_t)
62
__THROW ATTRIBUTE_WEAK;
63
int pthread_setspecific(pthread_key_t, const void*)
64
__THROW ATTRIBUTE_WEAK;
65
int pthread_once(pthread_once_t *, void (*)(void))
66
__THROW ATTRIBUTE_WEAK;
48
69
#define MAX_PERTHREAD_VALS 16
49
70
static void *perftools_pthread_specific_vals[MAX_PERTHREAD_VALS];
50
static pthread_key_t next_key;
52
// This module will behave very strangely if some pthreads functions
53
// exist and others don't
55
int perftools_pthread_key_create(pthread_key_t *key,
73
int perftools_pthread_key_create(pthread_key_t *key,
56
74
void (*destr_function) (void *)) {
57
75
if (pthread_key_create) {
58
76
return pthread_key_create(key, destr_function);
60
78
assert(next_key < MAX_PERTHREAD_VALS);
79
*key = (pthread_key_t)(next_key++);
66
void *perftools_pthread_getspecific(pthread_key_t key) {
84
void *perftools_pthread_getspecific(pthread_key_t key) {
67
85
if (pthread_getspecific) {
68
86
return pthread_getspecific(key);
70
return perftools_pthread_specific_vals[key];
88
return perftools_pthread_specific_vals[(int)key];
75
93
if (pthread_setspecific) {
76
94
return pthread_setspecific(key, val);
78
perftools_pthread_specific_vals[key] = val;
96
perftools_pthread_specific_vals[(int)key] = val;
83
int perftools_pthread_once(pthread_once_t *ctl,
84
void (*init_routine) (void)) {
101
static pthread_once_t pthread_once_init = PTHREAD_ONCE_INIT;
102
int perftools_pthread_once(pthread_once_t *ctl,
103
void (*init_routine) (void)) {
85
104
if (pthread_once) {
86
105
return pthread_once(ctl, init_routine);
88
if (*ctl == PTHREAD_ONCE_INIT) {
107
if (memcmp(ctl, &pthread_once_init, sizeof(*ctl)) == 0) {
109
++*(char*)(ctl); // make it so it's no longer equal to init