* src/pbc_merge.c:
[parrot.git] / src / malloc-trace.c
blob7669f9b0789e5e01cb0224d746401361857c957a
1 /* malloc-trace.c
3 * by Wolfram Gloger 1995.
5 * $Id$
6 * Copyright (C) 2002-2007, The Perl Foundation.
7 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <fcntl.h>
13 #include <string.h>
14 #include <sys/time.h>
15 #ifdef __linux__
16 # include <signal.h>
17 # include <asm/signal.h>
18 #endif
20 #include "malloc-trace.h"
22 #define ACTION_BUF_SIZE 1024
23 #define TIMESTAMP_FREQ 50
24 #define LOG_NAME "/tmp/mtrace"
26 static void malloc_trace_destructor(void);
28 static ACTION buffer[ACTION_BUF_SIZE+1];
29 static int buffer_i = 0;
30 static int fd = -1;
31 static int tracing = 1;
32 static int pid = 0;
33 static char *initial_brk = 0;
37 =head1 NAME
39 src/malloc-trace.c
41 =head1 DESCRIPTION
43 RT#48264
45 =head2 Functions
47 =over 4
49 =cut
55 =item C<static void
56 open_log_file()>
58 RT#48260: Not yet documented!!!
60 =cut
64 static void
65 open_log_file()
67 char name[128];
68 const unsigned version = MTRACE_VERSION;
69 #ifdef __linux__
70 char cmdline[128], *s;
71 int count, fd2;
72 #endif
74 tracing = 0;
75 pid = getpid();
76 #ifdef __linux__
77 sprintf(name, "/proc/%d/cmdline", pid);
78 fd2 = open(name, O_RDONLY);
79 if (fd2>=0 && (count = read(fd2, cmdline, 127)) > 0) {
80 close(fd2);
81 cmdline[count] = 0;
82 for (s=cmdline; *s++;); s--;
83 while (--s>cmdline && *s!='/');
84 if (*s == '/') s++;
85 sprintf(name, LOG_NAME ".%.12s.%d", s, pid);
87 else {
88 sprintf(name, LOG_NAME ".%d", pid);
90 #else
91 sprintf(name, LOG_NAME ".%d", pid);
92 #endif
93 fd = open(name, O_WRONLY|O_CREAT, 0600);
94 if (fd >= 0) {
95 write(fd, &version, sizeof (version));
96 write(fd, &initial_brk, sizeof (initial_brk));
98 tracing = 1;
103 =item C<static void
104 malloc_trace_destructor(void)>
106 RT#48260: Not yet documented!!!
108 =cut
112 static void
113 malloc_trace_destructor(void)
115 struct timeval t;
117 /* produce final timestamp */
118 gettimeofday(&t, NULL);
119 buffer[buffer_i].code = CODE_TIMESTAMP;
120 buffer[buffer_i].size = t.tv_sec;
121 buffer[buffer_i].ptr = (void *)t.tv_usec;
122 buffer[buffer_i].ptr2 = NULL;
123 buffer_i++;
124 if (fd < 0) open_log_file();
125 if (getpid() != pid) { /* Oops, must have forked... */
126 if (fd >= 0) close(fd);
127 return;
129 if (fd >= 0) write(fd, buffer, buffer_i*sizeof (ACTION));
130 write(2, "<end malloc trace>\n", 19);
131 if (fd >= 0) close(fd);
134 #ifdef __linux__
138 =item C<static void
139 malloc_segv_handler(int i, struct sigcontext_struct sc)>
141 RT#48260: Not yet documented!!!
143 =cut
147 static void
148 malloc_segv_handler(int i, struct sigcontext_struct sc)
150 tracing = 0;
151 fprintf(stderr, "malloc-trace: caught SEGV signal.\n");
152 fprintf(stderr, "sc.cr2 = %8lx\n", (unsigned long)sc.cr2);
153 malloc_trace_destructor();
156 #endif
160 =item C<static void
161 malloc_record(int code, size_t size, void *ptr, void *ptr2)>
163 RT#48260: Not yet documented!!!
165 =cut
169 static void
170 malloc_record(int code, size_t size, void *ptr, void *ptr2)
172 static long count = 0;
173 struct timeval t;
175 if (!tracing) return;
176 #ifdef __linux__
177 if (count == 0) signal(SIGSEGV, (void (*)(int))malloc_segv_handler);
178 #endif
179 if ((count++ % TIMESTAMP_FREQ) == 0) {
180 gettimeofday(&t, NULL);
181 buffer[buffer_i].code = CODE_TIMESTAMP;
182 buffer[buffer_i].size = t.tv_sec;
183 buffer[buffer_i].ptr = (void *)t.tv_usec;
184 buffer[buffer_i].ptr2 = NULL;
185 buffer_i++;
187 buffer[buffer_i].code = code;
188 buffer[buffer_i].size = size;
189 buffer[buffer_i].ptr = ptr;
190 buffer[buffer_i].ptr2 = ptr2;
191 if (++buffer_i >= ACTION_BUF_SIZE) {
192 if (fd < 0) open_log_file();
193 if (getpid() != pid) { /* Oops, must have forked... */
194 tracing = 0;
195 return;
197 if (fd >= 0) write(fd, buffer, buffer_i*sizeof (ACTION));
198 buffer_i = 0;
202 void* _real_malloc(size_t bytes);
206 =item C<void* malloc(size_t bytes)>
208 RT#48260: Not yet documented!!!
210 =cut
214 void* malloc(size_t bytes)
216 void *ptr;
218 if (initial_brk == 0) { /* Must be the first time. */
219 initial_brk = sbrk(0);
220 atexit(malloc_trace_destructor);
222 ptr = _real_malloc(bytes);
223 malloc_record(CODE_MALLOC, bytes, ptr, 0);
224 return ptr;
226 #define malloc _real_malloc
228 void _real_free(void* mem);
232 =item C<void free(void* mem)>
234 RT#48260: Not yet documented!!!
236 =cut
240 void free(void* mem)
242 malloc_record(CODE_FREE, 0, mem, 0);
243 _real_free(mem);
245 #define free _real_free
247 void* _real_realloc(void* mem, size_t bytes);
251 =item C<void* realloc(void* mem, size_t bytes)>
253 RT#48260: Not yet documented!!!
255 =cut
259 void* realloc(void* mem, size_t bytes)
261 void *ptr;
263 ptr = _real_realloc(mem, bytes);
264 malloc_record(CODE_REALLOC, bytes, mem, ptr);
265 return ptr;
267 #define realloc _real_realloc
269 void* _real_memalign(size_t alignment, size_t bytes);
273 =item C<void* memalign(size_t alignment, size_t bytes)>
275 RT#48260: Not yet documented!!!
277 =cut
281 void* memalign(size_t alignment, size_t bytes)
283 void *ptr;
285 if (initial_brk == 0) { /* Must be the first time. */
286 initial_brk = sbrk(0);
287 atexit(malloc_trace_destructor);
289 ptr = _real_memalign(alignment, bytes);
290 malloc_record(CODE_MEMALIGN, bytes, ptr, (void*)alignment);
291 return ptr;
293 #define memalign _real_memalign
295 void* _real_calloc(size_t n, size_t elem_size);
299 =item C<void* calloc(size_t n, size_t elem_size)>
301 RT#48260: Not yet documented!!!
303 =cut
307 void* calloc(size_t n, size_t elem_size)
309 void *ptr;
311 if (initial_brk == 0) { /* Must be the first time. */
312 initial_brk = sbrk(0);
313 atexit(malloc_trace_destructor);
315 ptr = _real_calloc(n, elem_size);
316 malloc_record(CODE_CALLOC, n*elem_size, ptr, 0);
317 return ptr;
319 #define calloc _real_calloc
321 void _real_cfree(void *mem);
325 =item C<void cfree(void *mem)>
327 RT#48260: Not yet documented!!!
329 =cut
333 void cfree(void *mem)
335 malloc_record(CODE_CFREE, 0, mem, 0);
336 _real_cfree(mem);
338 #define cfree _real_cfree
340 #include "malloc.c"
344 =back
346 =cut
351 * Local variables:
352 * c-file-style: "parrot"
353 * End:
354 * vim: expandtab shiftwidth=4: