[t][TT #1119] Convert t/op/bitwise.t to PIR
[parrot.git] / src / gc / malloc_trace.c
blob066bb50ff5e6dd8f5d90dba7957f009e3576fbe7
1 /* malloc-trace.c
3 * by Wolfram Gloger 1995.
5 * $Id$
6 * Copyright (C) 2002-2007, Parrot 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 open_log_file()>
57 Open a logfile for storing debugging information.
59 =cut
63 static void
64 open_log_file()
66 char name[128];
67 const unsigned version = MTRACE_VERSION;
68 #ifdef __linux__
69 char cmdline[128], *s;
70 int count, fd2;
71 #endif
73 tracing = 0;
74 pid = getpid();
75 #ifdef __linux__
76 sprintf(name, "/proc/%d/cmdline", pid);
77 fd2 = open(name, O_RDONLY);
78 if (fd2>=0 && (count = read(fd2, cmdline, 127)) > 0) {
79 close(fd2);
80 cmdline[count] = 0;
81 for (s=cmdline; *s++;); s--;
82 while (--s>cmdline && *s!='/');
83 if (*s == '/') s++;
84 sprintf(name, LOG_NAME ".%.12s.%d", s, pid);
86 else {
87 sprintf(name, LOG_NAME ".%d", pid);
89 #else
90 sprintf(name, LOG_NAME ".%d", pid);
91 #endif
92 fd = open(name, O_WRONLY|O_CREAT, 0600);
93 if (fd >= 0) {
94 write(fd, &version, sizeof (version));
95 write(fd, &initial_brk, sizeof (initial_brk));
97 tracing = 1;
102 =item C<static void malloc_trace_destructor(void)>
104 Print out a final timestamp and message to the log file.
106 =cut
110 static void
111 malloc_trace_destructor(void)
113 struct timeval t;
115 /* produce final timestamp */
116 gettimeofday(&t, NULL);
117 buffer[buffer_i].code = CODE_TIMESTAMP;
118 buffer[buffer_i].size = t.tv_sec;
119 buffer[buffer_i].ptr = (void *)t.tv_usec;
120 buffer[buffer_i].ptr2 = NULL;
121 buffer_i++;
122 if (fd < 0) open_log_file();
123 if (getpid() != pid) { /* Oops, must have forked... */
124 if (fd >= 0) close(fd);
125 return;
127 if (fd >= 0) write(fd, buffer, buffer_i*sizeof (ACTION));
128 write(2, "<end malloc trace>\n", 19);
129 if (fd >= 0) close(fd);
132 #ifdef __linux__
136 =item C<static void malloc_segv_handler(int i, struct sigcontext_struct sc)>
138 Catch a segfault signal, print an error message, and end the logfile.
140 =cut
144 static void
145 malloc_segv_handler(int i, struct sigcontext_struct sc)
147 tracing = 0;
148 fprintf(stderr, "malloc-trace: caught SEGV signal.\n");
149 fprintf(stderr, "sc.cr2 = %8lx\n", (unsigned long)sc.cr2);
150 malloc_trace_destructor();
153 #endif
157 =item C<static void malloc_record(int code, size_t size, void *ptr, void *ptr2)>
159 Record information about the allocation into the logfile.
161 =cut
165 static void
166 malloc_record(int code, size_t size, void *ptr, void *ptr2)
168 static long count = 0;
169 struct timeval t;
171 if (!tracing) return;
172 #ifdef __linux__
173 if (count == 0) signal(SIGSEGV, (void (*)(int))malloc_segv_handler);
174 #endif
175 if ((count++ % TIMESTAMP_FREQ) == 0) {
176 gettimeofday(&t, NULL);
177 buffer[buffer_i].code = CODE_TIMESTAMP;
178 buffer[buffer_i].size = t.tv_sec;
179 buffer[buffer_i].ptr = (void *)t.tv_usec;
180 buffer[buffer_i].ptr2 = NULL;
181 buffer_i++;
183 buffer[buffer_i].code = code;
184 buffer[buffer_i].size = size;
185 buffer[buffer_i].ptr = ptr;
186 buffer[buffer_i].ptr2 = ptr2;
187 if (++buffer_i >= ACTION_BUF_SIZE) {
188 if (fd < 0) open_log_file();
189 if (getpid() != pid) { /* Oops, must have forked... */
190 tracing = 0;
191 return;
193 if (fd >= 0) write(fd, buffer, buffer_i*sizeof (ACTION));
194 buffer_i = 0;
198 void* _real_malloc(size_t bytes);
202 =item C<void* malloc(size_t bytes)>
204 Allocate memory with the specified size in bytes. Record information about it
205 in the logfile.
207 =cut
211 void* malloc(size_t bytes)
213 void *ptr;
215 if (initial_brk == 0) { /* Must be the first time. */
216 initial_brk = sbrk(0);
217 atexit(malloc_trace_destructor);
219 ptr = _real_malloc(bytes);
220 malloc_record(CODE_MALLOC, bytes, ptr, 0);
221 return ptr;
223 #define malloc _real_malloc
225 void _real_free(void* mem);
229 =item C<void free(void* mem)>
231 Record information about the free in the logfile, and free the memory.
233 =cut
237 void free(void* mem)
239 malloc_record(CODE_FREE, 0, mem, 0);
240 _real_free(mem);
242 #define free _real_free
244 void* _real_realloc(void* mem, size_t bytes);
248 =item C<void* realloc(void* mem, size_t bytes)>
250 Resize the allocated memory buffer to the new size.
252 =cut
256 void* realloc(void* mem, size_t bytes)
258 void *ptr;
260 ptr = _real_realloc(mem, bytes);
261 malloc_record(CODE_REALLOC, bytes, mem, ptr);
262 return ptr;
264 #define realloc _real_realloc
266 void* _real_memalign(size_t alignment, size_t bytes);
270 =item C<void* memalign(size_t alignment, size_t bytes)>
272 Return an allocated memory buffer that's of at least the given size in bytes
273 and is aligned along the given boundary.
275 =cut
279 void* memalign(size_t alignment, size_t bytes)
281 void *ptr;
283 if (initial_brk == 0) { /* Must be the first time. */
284 initial_brk = sbrk(0);
285 atexit(malloc_trace_destructor);
287 ptr = _real_memalign(alignment, bytes);
288 malloc_record(CODE_MEMALIGN, bytes, ptr, (void*)alignment);
289 return ptr;
291 #define memalign _real_memalign
293 void* _real_calloc(size_t n, size_t elem_size);
297 =item C<void* calloc(size_t n, size_t elem_size)>
299 Allocate memory of the given size, initializing the memory to the given value.
301 =cut
305 void* calloc(size_t n, size_t elem_size)
307 void *ptr;
309 if (initial_brk == 0) { /* Must be the first time. */
310 initial_brk = sbrk(0);
311 atexit(malloc_trace_destructor);
313 ptr = _real_calloc(n, elem_size);
314 malloc_record(CODE_CALLOC, n*elem_size, ptr, 0);
315 return ptr;
317 #define calloc _real_calloc
319 void _real_cfree(void *mem);
323 =item C<void cfree(void *mem)>
325 free the given buffer, recording information about it in the log.
327 =cut
331 void cfree(void *mem)
333 malloc_record(CODE_CFREE, 0, mem, 0);
334 _real_cfree(mem);
336 #define cfree _real_cfree
338 #include "malloc.c"
342 =back
344 =cut
349 * Local variables:
350 * c-file-style: "parrot"
351 * End:
352 * vim: expandtab shiftwidth=4: