malloc instrumentation: remove dependency on pthread
[lttng-ust.git] / liblttng-ust-libc-wrapper / lttng-ust-malloc.c
1 /*
2 * Copyright (C) 2009 Pierre-Marc Fournier
3 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
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
20 #define _GNU_SOURCE
21 #include <dlfcn.h>
22 #include <sys/types.h>
23 #include <stdio.h>
24 #include <urcu/system.h>
25 #include <urcu/uatomic.h>
26
27 #define TRACEPOINT_DEFINE
28 #define TRACEPOINT_CREATE_PROBES
29 #include "ust_libc.h"
30
31 #define STATIC_CALLOC_LEN 4096
32 static char static_calloc_buf[STATIC_CALLOC_LEN];
33 static unsigned long static_calloc_buf_offset;
34
35 static void *static_calloc(size_t nmemb, size_t size)
36 {
37 unsigned long prev_offset, new_offset, res_offset;
38
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);
54 return &static_calloc_buf[prev_offset];
55 }
56
57 void *malloc(size_t size)
58 {
59 static void *(*plibc_malloc)(size_t size);
60 void *retval;
61
62 if (plibc_malloc == NULL) {
63 plibc_malloc = dlsym(RTLD_NEXT, "malloc");
64 if (plibc_malloc == NULL) {
65 fprintf(stderr, "mallocwrap: unable to find malloc\n");
66 return NULL;
67 }
68 }
69 retval = plibc_malloc(size);
70 tracepoint(ust_libc, malloc, size, retval);
71 return retval;
72 }
73
74 void free(void *ptr)
75 {
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 }
86
87 if (plibc_free == NULL) {
88 plibc_free = dlsym(RTLD_NEXT, "free");
89 if (plibc_free == NULL) {
90 fprintf(stderr, "mallocwrap: unable to find free\n");
91 return;
92 }
93 }
94 tracepoint(ust_libc, free, ptr);
95 plibc_free(ptr);
96 }
97
98 void *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
120 void *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.035567 seconds and 5 git commands to generate.