Mercurial > hg > xemacs-beta
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 (¤t_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 |