comparison src/free-hook.c @ 380:8626e4521993 r21-2-5

Import from CVS: tag r21-2-5
author cvs
date Mon, 13 Aug 2007 11:07:10 +0200
parents cc15677e0335
children bbff43aa5eb7
comparison
equal deleted inserted replaced
379:76b7d63099ad 380:8626e4521993
60 at any time. Another possibility is to report on what allocated 60 at any time. Another possibility is to report on what allocated
61 storage is still in use when the process is exited. Typically 61 storage is still in use when the process is exited. Typically
62 there will be a large amount, so this might not be very useful. 62 there will be a large amount, so this might not be very useful.
63 */ 63 */
64 64
65 #if defined (EMACS_BTL) && defined (sun4) && !defined (__lucid)
66 /* currently only works in this configuration */
67 # define SAVE_STACK
68 #endif
69
70 #ifdef emacs 65 #ifdef emacs
71 #ifdef SAVE_STACK
72 #include "cadillac-btl.h"
73 #endif
74 #include <config.h> 66 #include <config.h>
75 #include "lisp.h" 67 #include "lisp.h"
76 #else 68 #else
77 void *malloc (unsigned long); 69 void *malloc (unsigned long);
78 #endif 70 #endif
91 #include <sys/types.h> 83 #include <sys/types.h>
92 84
93 /* System function prototypes don't belong in C source files */ 85 /* System function prototypes don't belong in C source files */
94 /* extern void free (void *); */ 86 /* extern void free (void *); */
95 87
96 c_hashtable pointer_table; 88 struct hash_table *pointer_table;
97 89
98 extern void (*__free_hook) (void *); 90 extern void (*__free_hook) (void *);
99 extern void *(*__malloc_hook) (unsigned long); 91 extern void *(*__malloc_hook) (unsigned long);
100 92
101 static void *check_malloc (unsigned long); 93 static void *check_malloc (unsigned long);
102 94
103 typedef void (*fun_ptr) (); 95 typedef void (*fun_ptr) ();
104 96
105 #ifdef SAVE_STACK
106 #define FREE_QUEUE_LIMIT 1000
107 #else
108 /* free_queue is not too useful without backtrace logging */ 97 /* free_queue is not too useful without backtrace logging */
109 #define FREE_QUEUE_LIMIT 1 98 #define FREE_QUEUE_LIMIT 1
110 #endif
111 #define TRACE_LIMIT 20 99 #define TRACE_LIMIT 20
112 100
113 typedef struct { 101 typedef struct {
114 fun_ptr return_pc; 102 fun_ptr return_pc;
115 #ifdef SAVE_ARGS 103 #ifdef SAVE_ARGS
118 } fun_entry; 106 } fun_entry;
119 107
120 typedef struct { 108 typedef struct {
121 void *address; 109 void *address;
122 unsigned long length; 110 unsigned long length;
123 #ifdef SAVE_STACK
124 fun_entry backtrace[TRACE_LIMIT];
125 #endif
126 } free_queue_entry; 111 } free_queue_entry;
127 112
128 free_queue_entry free_queue[FREE_QUEUE_LIMIT]; 113 free_queue_entry free_queue[FREE_QUEUE_LIMIT];
129 114
130 int current_free; 115 int current_free;
131
132 #ifdef SAVE_STACK
133 static void
134 init_frame (FRAME *fptr)
135 {
136 FRAME tmp_frame;
137
138 #ifdef sparc
139 /* Do the system trap ST_FLUSH_WINDOWS */
140 asm ("ta 3");
141 asm ("st %sp, [%i0+0]");
142 asm ("st %fp, [%i0+4]");
143 #endif
144
145 fptr->pc = (char *) init_frame;
146 tmp_frame = *fptr;
147
148 PREVIOUS_FRAME (tmp_frame);
149
150 *fptr = tmp_frame;
151 return;
152 }
153
154 #ifdef SAVE_ARGS
155 static void *
156 frame_arg (FRAME *fptr, int index)
157 {
158 return ((void *) FRAME_ARG(*fptr, index));
159 }
160 #endif
161
162 static void
163 save_backtrace (FRAME *current_frame_ptr, fun_entry *table)
164 {
165 int i = 0;
166 #ifdef SAVE_ARGS
167 int j;
168 #endif
169 FRAME current_frame = *current_frame_ptr;
170
171 /* Get up and out of free() */
172 PREVIOUS_FRAME (current_frame);
173
174 /* now do the basic loop adding data until there is no more */
175 while (PREVIOUS_FRAME (current_frame) && i < TRACE_LIMIT)
176 {
177 table[i].return_pc = (void (*)())FRAME_PC (current_frame);
178 #ifdef SAVE_ARGS
179 for (j = 0; j < 3; j++)
180 table[i].arg[j] = frame_arg (&current_frame, j);
181 #endif
182 i++;
183 }
184 memset (&table[i], 0, sizeof (fun_entry) * (TRACE_LIMIT - i));
185 }
186
187 free_queue_entry *
188 find_backtrace (void *ptr)
189 {
190 int i;
191
192 for (i = 0; i < FREE_QUEUE_LIMIT; i++)
193 if (free_queue[i].address == ptr)
194 return &free_queue[i];
195
196 return 0;
197 }
198 #endif /* SAVE_STACK */
199 116
200 int strict_free_check; 117 int strict_free_check;
201 118
202 static void 119 static void
203 check_free (void *ptr) 120 check_free (void *ptr)
204 { 121 {
205 #ifdef SAVE_STACK
206 FRAME start_frame;
207
208 init_frame (&start_frame);
209 #endif
210
211 __free_hook = 0; 122 __free_hook = 0;
212 __malloc_hook = 0; 123 __malloc_hook = 0;
213 if (!pointer_table) 124 if (!pointer_table)
214 pointer_table = make_hashtable (max (100, FREE_QUEUE_LIMIT * 2)); 125 pointer_table = make_hash_table (max (100, FREE_QUEUE_LIMIT * 2));
215 if (ptr != 0) 126 if (ptr != 0)
216 { 127 {
217 long size; 128 long size;
218 #ifdef UNMAPPED_FREE 129 #ifdef UNMAPPED_FREE
219 unsigned long rounded_up_size; 130 unsigned long rounded_up_size;
271 ((unsigned long *) ptr)[i] = 0xdeadbeef; 182 ((unsigned long *) ptr)[i] = 0xdeadbeef;
272 } 183 }
273 #endif 184 #endif
274 free_queue[current_free].address = ptr; 185 free_queue[current_free].address = ptr;
275 free_queue[current_free].length = size; 186 free_queue[current_free].length = size;
276 #ifdef SAVE_STACK 187
277 save_backtrace (&start_frame,
278 free_queue[current_free].backtrace);
279 #endif
280 current_free++; 188 current_free++;
281 if (current_free >= FREE_QUEUE_LIMIT) 189 if (current_free >= FREE_QUEUE_LIMIT)
282 current_free = 0; 190 current_free = 0;
283 /* Really free this if there's something there */ 191 /* Really free this if there's something there */
284 { 192 {
322 #else 230 #else
323 rounded_up_size = size; 231 rounded_up_size = size;
324 #endif 232 #endif
325 result = malloc (rounded_up_size); 233 result = malloc (rounded_up_size);
326 if (!pointer_table) 234 if (!pointer_table)
327 pointer_table = make_hashtable (FREE_QUEUE_LIMIT * 2); 235 pointer_table = make_hash_table (FREE_QUEUE_LIMIT * 2);
328 puthash (result, (void *)size, pointer_table); 236 puthash (result, (void *)size, pointer_table);
329 __free_hook = check_free; 237 __free_hook = check_free;
330 __malloc_hook = check_malloc; 238 __malloc_hook = check_malloc;
331 end: 239 end:
332 return result; 240 return result;
517 { 425 {
518 char *file; 426 char *file;
519 int line; 427 int line;
520 blocktype type; 428 blocktype type;
521 int value; 429 int value;
522 #ifdef SAVE_STACK
523 fun_entry backtrace[TRACE_LIMIT];
524 #endif
525 }; 430 };
526 431
527 typedef struct block_input_history_struct block_input_history; 432 typedef struct block_input_history_struct block_input_history;
528 433
529 #endif 434 #endif
552 note_block (file, line, totally_type); 457 note_block (file, line, totally_type);
553 } 458 }
554 459
555 note_block (char *file, int line, blocktype type) 460 note_block (char *file, int line, blocktype type)
556 { 461 {
557 #ifdef SAVE_STACK
558 FRAME start_frame;
559
560 init_frame (&start_frame);
561 #endif
562
563 blhist[blhistptr].file = file; 462 blhist[blhistptr].file = file;
564 blhist[blhistptr].line = line; 463 blhist[blhistptr].line = line;
565 blhist[blhistptr].type = type; 464 blhist[blhistptr].type = type;
566 blhist[blhistptr].value = interrupt_input_blocked; 465 blhist[blhistptr].value = interrupt_input_blocked;
567
568 #ifdef SAVE_STACK
569 save_backtrace (&start_frame,
570 blhist[blhistptr].backtrace);
571 #endif
572 466
573 blhistptr++; 467 blhistptr++;
574 if (blhistptr >= BLHISTLIMIT) 468 if (blhistptr >= BLHISTLIMIT)
575 blhistptr = 0; 469 blhistptr = 0;
576 } 470 }
599 if (! gcprolist->next->next) abort (); 493 if (! gcprolist->next->next) abort ();
600 if (value == gcprolist->next->next->next) goto OK; 494 if (value == gcprolist->next->next->next) goto OK;
601 abort (); 495 abort ();
602 OK:; 496 OK:;
603 } 497 }
604 #ifdef SAVE_STACK
605 init_frame (&start_frame);
606 #endif
607 gcprohist[gcprohistptr].file = file; 498 gcprohist[gcprohistptr].file = file;
608 gcprohist[gcprohistptr].line = line; 499 gcprohist[gcprohistptr].line = line;
609 gcprohist[gcprohistptr].type = type; 500 gcprohist[gcprohistptr].type = type;
610 gcprohist[gcprohistptr].value = (int) value; 501 gcprohist[gcprohistptr].value = (int) value;
611 #ifdef SAVE_STACK
612 save_backtrace (&start_frame, gcprohist[gcprohistptr].backtrace);
613 #endif
614 gcprohistptr++; 502 gcprohistptr++;
615 if (gcprohistptr >= GCPROHISTLIMIT) 503 if (gcprohistptr >= GCPROHISTLIMIT)
616 gcprohistptr = 0; 504 gcprohistptr = 0;
617 } 505 }
618 506