try to name/number new routes-from-templates to avoid colliding names if adding more...
[ardour2.git] / gtk2_ardour / gprofhelper.c
blobb806a073c6dec25e6aa211f750a6fbd915047548
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 -nostdlib -fPIC gprof-helper.c -o gprof-helper.so -lpthread -ldl
14 * Usage example:
15 * LD_PRELOAD=./gprof-helper.so your_program
18 #define _GNU_SOURCE
19 #include <sys/time.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <dlfcn.h>
23 #include <pthread.h>
25 static void * wrapper_routine(void *);
27 /* Original pthread function */
28 static int (*pthread_create_orig)(pthread_t *__restrict,
29 __const pthread_attr_t *__restrict,
30 void *(*)(void *),
31 void *__restrict) = NULL;
33 /* Library initialization function */
34 void _init(void)
36 pthread_create_orig = dlsym(RTLD_NEXT, "pthread_create");
37 fprintf(stderr, "pthreads: using profiling hooks for gprof\n");
38 if(pthread_create_orig == NULL)
40 char *error = dlerror();
41 if(error == NULL)
43 error = "pthread_create is NULL";
45 fprintf(stderr, "%s", error);
46 exit(EXIT_FAILURE);
50 /* Our data structure passed to the wrapper */
51 typedef struct wrapper_s
53 void * (*start_routine)(void *);
54 void * arg;
56 pthread_mutex_t lock;
57 pthread_cond_t wait;
59 struct itimerval itimer;
61 } wrapper_t;
63 /* The wrapper function in charge for setting the itimer value */
64 static void * wrapper_routine(void * data)
66 /* Put user data in thread-local variables */
67 void * (*start_routine)(void *) = ((wrapper_t*)data)->start_routine;
68 void * arg = ((wrapper_t*)data)->arg;
70 /* Set the profile timer value */
71 setitimer(ITIMER_PROF, &((wrapper_t*)data)->itimer, NULL);
73 /* Tell the calling thread that we don't need its data anymore */
74 pthread_mutex_lock(&((wrapper_t*)data)->lock);
75 pthread_cond_signal(&((wrapper_t*)data)->wait);
76 pthread_mutex_unlock(&((wrapper_t*)data)->lock);
78 /* Call the real function */
79 return start_routine(arg);
82 /* Our wrapper function for the real pthread_create() */
83 int pthread_create(pthread_t *__restrict thread,
84 __const pthread_attr_t *__restrict attr,
85 void * (*start_routine)(void *),
86 void *__restrict arg)
88 wrapper_t wrapper_data;
89 int i_return;
91 /* Initialize the wrapper structure */
92 wrapper_data.start_routine = start_routine;
93 wrapper_data.arg = arg;
94 getitimer(ITIMER_PROF, &wrapper_data.itimer);
95 pthread_cond_init(&wrapper_data.wait, NULL);
96 pthread_mutex_init(&wrapper_data.lock, NULL);
97 pthread_mutex_lock(&wrapper_data.lock);
99 /* The real pthread_create call */
100 i_return = pthread_create_orig(thread,
101 attr,
102 &wrapper_routine,
103 &wrapper_data);
105 /* If the thread was successfully spawned, wait for the data
106 * to be released */
107 if(i_return == 0)
109 pthread_cond_wait(&wrapper_data.wait, &wrapper_data.lock);
112 pthread_mutex_unlock(&wrapper_data.lock);
113 pthread_mutex_destroy(&wrapper_data.lock);
114 pthread_cond_destroy(&wrapper_data.wait);
116 return i_return;