]>
git.proxmox.com Git - ceph.git/blob - ceph/src/test/gprof-helper.c
1 /* gprof-helper.c -- preload library to profile pthread-enabled programs
3 * Authors: Sam Hocevar <sam at zoy dot org>
4 * Daniel Jönsson <danieljo at fagotten dot org>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the Do What The Fuck You Want To
8 * Public License as published by Banlu Kemiyatorn. See
9 * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
11 * Compilation example:
12 * gcc -shared -fPIC gprof-helper.c -o gprof-helper.so -lpthread -ldl
15 * LD_PRELOAD=./gprof-helper.so your_program
24 static void * wrapper_routine(void *);
26 /* Original pthread function */
27 static int (*pthread_create_orig
)(pthread_t
*__restrict
,
28 __const pthread_attr_t
*__restrict
,
30 void *__restrict
) = NULL
;
32 /* Library initialization function */
33 void wooinit(void) __attribute__((constructor
));
37 pthread_create_orig
= dlsym(RTLD_NEXT
, "pthread_create");
38 fprintf(stderr
, "pthreads: using profiling hooks for gprof\n");
39 if(pthread_create_orig
== NULL
)
41 char *error
= dlerror();
44 error
= "pthread_create is NULL";
46 fprintf(stderr
, "%s\n", error
);
51 /* Our data structure passed to the wrapper */
52 typedef struct wrapper_s
54 void * (*start_routine
)(void *);
60 struct itimerval itimer
;
64 /* The wrapper function in charge for setting the itimer value */
65 static void * wrapper_routine(void * data
)
67 /* Put user data in thread-local variables */
68 void * (*start_routine
)(void *) = ((wrapper_t
*)data
)->start_routine
;
69 void * arg
= ((wrapper_t
*)data
)->arg
;
71 /* Set the profile timer value */
72 setitimer(ITIMER_PROF
, &((wrapper_t
*)data
)->itimer
, NULL
);
74 /* Tell the calling thread that we don't need its data anymore */
75 pthread_mutex_lock(&((wrapper_t
*)data
)->lock
);
76 pthread_cond_signal(&((wrapper_t
*)data
)->wait
);
77 pthread_mutex_unlock(&((wrapper_t
*)data
)->lock
);
79 /* Call the real function */
80 return start_routine(arg
);
83 /* Our wrapper function for the real pthread_create() */
84 int pthread_create(pthread_t
*__restrict thread
,
85 __const pthread_attr_t
*__restrict attr
,
86 void * (*start_routine
)(void *),
89 wrapper_t wrapper_data
;
92 /* Initialize the wrapper structure */
93 wrapper_data
.start_routine
= start_routine
;
94 wrapper_data
.arg
= arg
;
95 getitimer(ITIMER_PROF
, &wrapper_data
.itimer
);
96 pthread_cond_init(&wrapper_data
.wait
, NULL
);
97 pthread_mutex_init(&wrapper_data
.lock
, NULL
);
98 pthread_mutex_lock(&wrapper_data
.lock
);
100 /* The real pthread_create call */
101 i_return
= pthread_create_orig(thread
,
106 /* If the thread was successfully spawned, wait for the data
110 pthread_cond_wait(&wrapper_data
.wait
, &wrapper_data
.lock
);
113 pthread_mutex_unlock(&wrapper_data
.lock
);
114 pthread_mutex_destroy(&wrapper_data
.lock
);
115 pthread_cond_destroy(&wrapper_data
.wait
);