~ubuntu-branches/ubuntu/utopic/ardour3/utopic

« back to all changes in this revision

Viewing changes to gtk2_ardour/gprofhelper.c

  • Committer: Package Import Robot
  • Author(s): Felipe Sateler
  • Date: 2013-09-21 19:05:02 UTC
  • Revision ID: package-import@ubuntu.com-20130921190502-8gsftrku6jnzhd7v
Tags: upstream-3.4~dfsg
Import upstream version 3.4~dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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,
 
102
                                   &wrapper_routine,
 
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
}