1 #ifdef WANT_PROFILE_LINUX
2 #ifndef __profile_h
3 #define __profile_h
4 
5 #include <pthread.h>
6 #include <sys/time.h>
7 
8 /* functions useful for profiling
9  *
10  *
11  * the pthread wrapper/fix on linux is from sam.zoy.org
12  */
13 
14 typedef struct wrapper_s
15 {
16 	void *(*start_routine)(void *);
17 	void *arg;
18 
19 	pthread_mutex_t lock;
20 	pthread_cond_t  wait;
21 
22 	struct itimerval itimer;
23 
24 } wrapper_t;
25 
26 static void *wrapper_routine(void *);
27 
28 /* Same prototype as pthread_create; use some #define magic to
29  *  * transparently replace it in other files */
gprof_pthread_create(pthread_t * thread,pthread_attr_t * attr,void * (* start_routine)(void *),void * arg)30 int gprof_pthread_create(pthread_t *thread, pthread_attr_t *attr,
31                          void *(*start_routine)(void *), void *arg)
32 {
33 	wrapper_t wrapper_data;
34 	int i_return;
35 
36 	/* Initialize the wrapper structure */
37 	wrapper_data.start_routine = start_routine;
38 	wrapper_data.arg = arg;
39 	getitimer(ITIMER_PROF, &wrapper_data.itimer);
40 	pthread_cond_init(&wrapper_data.wait, NULL);
41 	pthread_mutex_init(&wrapper_data.lock, NULL);
42 	pthread_mutex_lock(&wrapper_data.lock);
43 
44 	/* The real pthread_create call */
45 	i_return = pthread_create(thread, attr, &wrapper_routine,
46 		&wrapper_data);
47 
48 	/* If the thread was successfully spawned, wait for the data
49 	*      * to be released */
50 	if(i_return == 0) {
51 		pthread_cond_wait(&wrapper_data.wait, &wrapper_data.lock);
52 	}
53 
54 	pthread_mutex_unlock(&wrapper_data.lock);
55 	pthread_mutex_destroy(&wrapper_data.lock);
56 	pthread_cond_destroy(&wrapper_data.wait);
57 
58 	return i_return;
59 }
60 
61 /* The wrapper function in charge for setting the itimer value */
wrapper_routine(void * data)62 static void *wrapper_routine(void *data)
63 {
64 	/* Put user data in thread-local variables */
65 	void * (*start_routine)(void *) = ((wrapper_t*)data)->start_routine;
66 	void * arg = ((wrapper_t*)data)->arg;
67 
68 	/* Set the profile timer value */
69 	setitimer(ITIMER_PROF, &((wrapper_t*)data)->itimer, NULL);
70 
71 	/* Tell the calling thread that we don't need its data anymore */
72 	pthread_mutex_lock(&((wrapper_t*)data)->lock);
73 	pthread_cond_signal(&((wrapper_t*)data)->wait);
74 	pthread_mutex_unlock(&((wrapper_t*)data)->lock);
75 
76 	/* Call the real function */
77 	return start_routine(arg);
78 }
79 
80 #define pthread_create(a,b,c,d) gprof_pthread_create(a,b,c,d)
81 #endif
82 #endif
83