ardour
gprofhelper.c
Go to the documentation of this file.
1 /* gprof-helper.c -- preload library to profile pthread-enabled programs
2  *
3  * Authors: Sam Hocevar <sam at zoy dot org>
4  * Daniel Jönsson <danieljo at fagotten dot org>
5  *
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.
10  *
11  * Compilation example:
12  * gcc -shared -nostdlib -fPIC gprof-helper.c -o gprof-helper.so -lpthread -ldl
13  *
14  * Usage example:
15  * LD_PRELOAD=./gprof-helper.so your_program
16  */
17 
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>
24 
25 static void * wrapper_routine(void *);
26 
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;
32 
33 /* Library initialization function */
34 void _init(void)
35 {
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)
39  {
40  char *error = dlerror();
41  if(error == NULL)
42  {
43  error = "pthread_create is NULL";
44  }
45  fprintf(stderr, "%s", error);
46  exit(EXIT_FAILURE);
47  }
48 }
49 
50 /* Our data structure passed to the wrapper */
51 typedef struct wrapper_s
52 {
53  void * (*start_routine)(void *);
54  void * arg;
55 
56  pthread_mutex_t lock;
57  pthread_cond_t wait;
58 
59  struct itimerval itimer;
60 
61 } wrapper_t;
62 
63 /* The wrapper function in charge for setting the itimer value */
64 static void * wrapper_routine(void * data)
65 {
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;
69 
70  /* Set the profile timer value */
71  setitimer(ITIMER_PROF, &((wrapper_t*)data)->itimer, NULL);
72 
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);
77 
78  /* Call the real function */
79  return start_routine(arg);
80 }
81 
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)
87 {
88  wrapper_t wrapper_data;
89  int i_return;
90 
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);
98 
99  /* The real pthread_create call */
100  i_return = pthread_create_orig(thread,
101  attr,
103  &wrapper_data);
104 
105  /* If the thread was successfully spawned, wait for the data
106  * to be released */
107  if(i_return == 0)
108  {
109  pthread_cond_wait(&wrapper_data.wait, &wrapper_data.lock);
110  }
111 
112  pthread_mutex_unlock(&wrapper_data.lock);
113  pthread_mutex_destroy(&wrapper_data.lock);
114  pthread_cond_destroy(&wrapper_data.wait);
115 
116  return i_return;
117 }
struct wrapper_s wrapper_t
LIBPBD_API Transmitter error
static void * wrapper_routine(void *)
Definition: gprofhelper.c:64
void *(* start_routine)(void *)
Definition: gprofhelper.c:53
pthread_mutex_t lock
Definition: gprofhelper.c:56
static int(* pthread_create_orig)(pthread_t *__restrict, __const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict)
Definition: gprofhelper.c:28
void * arg
Definition: gprofhelper.c:54
struct itimerval itimer
Definition: gprofhelper.c:59
pthread_cond_t wait
Definition: gprofhelper.c:57
int pthread_create(pthread_t *__restrict thread, __const pthread_attr_t *__restrict attr, void *(*start_routine)(void *), void *__restrict arg)
Definition: gprofhelper.c:83
void _init(void)
Definition: gprofhelper.c:34