malloc instrumentation: remove dependency on pthread
[lttng-ust.git] / liblttng-ust-libc-wrapper / lttng-ust-malloc.c
CommitLineData
b27f8e75
MD
1/*
2 * Copyright (C) 2009 Pierre-Marc Fournier
1622ba22 3 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
c39c72ee
PMF
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
e541a28d
PMF
20#define _GNU_SOURCE
21#include <dlfcn.h>
22#include <sys/types.h>
23#include <stdio.h>
4c3536e0
MD
24#include <urcu/system.h>
25#include <urcu/uatomic.h>
1622ba22
MD
26
27#define TRACEPOINT_DEFINE
28#define TRACEPOINT_CREATE_PROBES
29#include "ust_libc.h"
fbd8191b 30
f95b2888
SS
31#define STATIC_CALLOC_LEN 4096
32static char static_calloc_buf[STATIC_CALLOC_LEN];
4c3536e0 33static unsigned long static_calloc_buf_offset;
f95b2888
SS
34
35static void *static_calloc(size_t nmemb, size_t size)
36{
4c3536e0 37 unsigned long prev_offset, new_offset, res_offset;
f95b2888 38
4c3536e0
MD
39 /*
40 * Protect static_calloc_buf_offset from concurrent updates
41 * using a cmpxchg loop rather than a mutex to remove a
42 * dependency on pthread. This will minimize the risk of bad
43 * interaction between mutex and malloc instrumentation.
44 */
45 res_offset = CMM_LOAD_SHARED(static_calloc_buf_offset);
46 do {
47 prev_offset = res_offset;
48 if (nmemb * size > sizeof(static_calloc_buf) - prev_offset) {
49 return NULL;
50 }
51 new_offset = prev_offset + nmemb * size;
52 } while ((res_offset = uatomic_cmpxchg(&static_calloc_buf_offset,
53 prev_offset, new_offset)) != prev_offset);
f95b2888
SS
54 return &static_calloc_buf[prev_offset];
55}
56
e541a28d
PMF
57void *malloc(size_t size)
58{
f95b2888 59 static void *(*plibc_malloc)(size_t size);
1c184644
PMF
60 void *retval;
61
b27f8e75 62 if (plibc_malloc == NULL) {
e541a28d 63 plibc_malloc = dlsym(RTLD_NEXT, "malloc");
b27f8e75 64 if (plibc_malloc == NULL) {
e541a28d
PMF
65 fprintf(stderr, "mallocwrap: unable to find malloc\n");
66 return NULL;
67 }
68 }
1c184644 69 retval = plibc_malloc(size);
1622ba22 70 tracepoint(ust_libc, malloc, size, retval);
1c184644
PMF
71 return retval;
72}
73
74void free(void *ptr)
75{
f95b2888
SS
76 static void (*plibc_free)(void *ptr);
77
78 /* Check whether the memory was allocated with
79 * static_calloc, in which case there is nothing
80 * to free.
81 */
82 if ((char *)ptr >= static_calloc_buf &&
83 (char *)ptr < static_calloc_buf + STATIC_CALLOC_LEN) {
84 return;
85 }
1c184644 86
b27f8e75 87 if (plibc_free == NULL) {
1c184644 88 plibc_free = dlsym(RTLD_NEXT, "free");
b27f8e75 89 if (plibc_free == NULL) {
1c184644 90 fprintf(stderr, "mallocwrap: unable to find free\n");
eb0f0951 91 return;
1c184644
PMF
92 }
93 }
1622ba22 94 tracepoint(ust_libc, free, ptr);
eb0f0951 95 plibc_free(ptr);
e541a28d 96}
f95b2888
SS
97
98void *calloc(size_t nmemb, size_t size)
99{
100 static void *(*volatile plibc_calloc)(size_t nmemb, size_t size);
101 void *retval;
102
103 if (plibc_calloc == NULL) {
104 /*
105 * Temporarily redirect to static_calloc,
106 * until the dlsym lookup has completed.
107 */
108 plibc_calloc = static_calloc;
109 plibc_calloc = dlsym(RTLD_NEXT, "calloc");
110 if (plibc_calloc == NULL) {
111 fprintf(stderr, "callocwrap: unable to find calloc\n");
112 return NULL;
113 }
114 }
115 retval = plibc_calloc(nmemb, size);
116 tracepoint(ust_libc, calloc, nmemb, size, retval);
117 return retval;
118}
119
120void *realloc(void *ptr, size_t size)
121{
122 static void *(*plibc_realloc)(void *ptr, size_t size);
123 void *retval;
124
125 if (plibc_realloc == NULL) {
126 plibc_realloc = dlsym(RTLD_NEXT, "realloc");
127 if (plibc_realloc == NULL) {
128 fprintf(stderr, "reallocwrap: unable to find realloc\n");
129 return NULL;
130 }
131 }
132 retval = plibc_realloc(ptr, size);
133 tracepoint(ust_libc, realloc, ptr, size, retval);
134 return retval;
135}
This page took 0.035943 seconds and 4 git commands to generate.