comparison src/profile.c @ 44:8d2a9b52c682 r19-15prefinal

Import from CVS: tag r19-15prefinal
author cvs
date Mon, 13 Aug 2007 08:55:10 +0200
parents 859a2309aef8
children c0965ff3b039
comparison
equal deleted inserted replaced
43:23cafc5d2038 44:8d2a9b52c682
61 Lisp_Object QSin_redisplay; 61 Lisp_Object QSin_redisplay;
62 Lisp_Object QSin_garbage_collection; 62 Lisp_Object QSin_garbage_collection;
63 Lisp_Object QSprocessing_events_at_top_level; 63 Lisp_Object QSprocessing_events_at_top_level;
64 Lisp_Object QSunknown; 64 Lisp_Object QSunknown;
65 65
66 /* We use inside_profiling to prevent the handler from writing to
67 the table while another routine is operating on it. We also set
68 inside_profiling in case the timeout between signal calls is short
69 enough to catch us while we're already in there. */
70 volatile static int inside_profiling;
71
66 static SIGTYPE 72 static SIGTYPE
67 sigprof_handler (int signo) 73 sigprof_handler (int signo)
68 { 74 {
69 Lisp_Object fun; 75 /* Don't do anything if we are shutting down, or are doing a maphash
70 76 or clrhash on the table. */
71 if (profiling_redisplay_flag) 77 if (!inside_profiling && !preparing_for_armageddon)
72 fun = QSin_redisplay; 78 {
73 else if (gc_in_progress) 79 Lisp_Object fun;
74 fun = QSin_garbage_collection; 80
75 else if (backtrace_list) 81 /* If something below causes an error to be signaled, we'll
76 { 82 not correctly reset this flag. But we'll be in worse shape
77 fun = *backtrace_list->function; 83 than that anyways, since we'll longjmp back to the last
78 84 condition case. */
79 XUNMARK (fun); 85 inside_profiling = 1;
80 if (!GC_SYMBOLP (fun) && !GC_COMPILED_FUNCTIONP (fun)) 86
81 fun = QSunknown; 87 if (profiling_redisplay_flag)
82 } 88 fun = QSin_redisplay;
83 else 89 else if (gc_in_progress)
84 fun = QSprocessing_events_at_top_level; 90 fun = QSin_garbage_collection;
85 91 else if (backtrace_list)
86 { 92 {
87 long count; 93 fun = *backtrace_list->function;
88 CONST void *vval; 94
95 /* #### dmoore - why do we need to unmark it, we aren't in GC. */
96 XUNMARK (fun);
97 if (!GC_SYMBOLP (fun) && !GC_COMPILED_FUNCTIONP (fun))
98 fun = QSunknown;
99 }
100 else
101 fun = QSprocessing_events_at_top_level;
102
103 {
104 /* #### see comment about memory allocation in start-profiling.
105 Allocating memory in a signal handler is BAD BAD BAD.
106 If you are using the non-mmap rel-alloc code, you might
107 lose because of this. Even worse, if the memory allocation
108 fails, the `error' generated whacks everything hard. */
109 long count;
110 CONST void *vval;
89 111
90 if (gethash (LISP_TO_VOID (fun), big_profile_table, &vval)) 112 if (gethash (LISP_TO_VOID (fun), big_profile_table, &vval))
91 count = (long) vval; 113 count = (long) vval;
92 else 114 else
93 count = 0; 115 count = 0;
94 count++; 116 count++;
95 vval = (CONST void *) count; 117 vval = (CONST void *) count;
96 puthash (LISP_TO_VOID (fun), (void *) vval, big_profile_table); 118 puthash (LISP_TO_VOID (fun), (void *) vval, big_profile_table);
97 } 119 }
120
121 inside_profiling = 0;
122 }
98 } 123 }
99 124
100 DEFUN ("start-profiling", Fstart_profiling, 0, 1, 0, /* 125 DEFUN ("start-profiling", Fstart_profiling, 0, 1, 0, /*
101 Start profiling, with profile queries every MICROSECS. 126 Start profiling, with profile queries every MICROSECS.
102 If MICROSECS is nil or omitted, the value of `default-profiling-interval' 127 If MICROSECS is nil or omitted, the value of `default-profiling-interval'
108 info. Thus you can start and stop as many times as you want and everything 133 info. Thus you can start and stop as many times as you want and everything
109 will be properly accumulated. 134 will be properly accumulated.
110 */ 135 */
111 (microsecs)) 136 (microsecs))
112 { 137 {
138 /* This function can GC */
113 int msecs; 139 int msecs;
114 struct itimerval foo; 140 struct itimerval foo;
115 141
116 /* #### The hash code can safely be called from a signal handler 142 /* #### The hash code can safely be called from a signal handler
117 except when it has to grow the hashtable. In this case, it calls 143 except when it has to grow the hashtable. In this case, it calls
134 foo.it_value.tv_sec = 0; 160 foo.it_value.tv_sec = 0;
135 foo.it_value.tv_usec = msecs; 161 foo.it_value.tv_usec = msecs;
136 EMACS_NORMALIZE_TIME (foo.it_value); 162 EMACS_NORMALIZE_TIME (foo.it_value);
137 foo.it_interval = foo.it_value; 163 foo.it_interval = foo.it_value;
138 profiling_active = 1; 164 profiling_active = 1;
165 inside_profiling = 0;
139 setitimer (ITIMER_PROF, &foo, 0); 166 setitimer (ITIMER_PROF, &foo, 0);
140 return Qnil; 167 return Qnil;
141 } 168 }
142 169
143 DEFUN ("stop-profiling", Fstop_profiling, 0, 0, 0, /* 170 DEFUN ("stop-profiling", Fstop_profiling, 0, 0, 0, /*
144 Stop profiling. 171 Stop profiling.
145 */ 172 */
146 ()) 173 ())
147 { 174 {
175 /* This function does not GC */
148 struct itimerval foo; 176 struct itimerval foo;
149 177
150 foo.it_value.tv_sec = 0; 178 foo.it_value.tv_sec = 0;
151 foo.it_value.tv_usec = 0; 179 foo.it_value.tv_usec = 0;
152 foo.it_interval = foo.it_value; 180 foo.it_interval = foo.it_value;
154 profiling_active = 0; 182 profiling_active = 0;
155 signal (SIGPROF, fatal_error_signal); 183 signal (SIGPROF, fatal_error_signal);
156 return Qnil; 184 return Qnil;
157 } 185 }
158 186
187 static Lisp_Object
188 profile_lock_unwind (Lisp_Object ignore)
189 {
190 inside_profiling = 0;
191 return Qnil;
192 }
193
159 struct get_profiling_info_closure 194 struct get_profiling_info_closure
160 { 195 {
161 Lisp_Object accum; 196 Lisp_Object accum;
162 }; 197 };
163 198
164 static void 199 static void
165 get_profiling_info_maphash (CONST void *void_key, 200 get_profiling_info_maphash (CONST void *void_key,
166 void *void_val, 201 void *void_val,
167 void *void_closure) 202 void *void_closure)
168 { 203 {
169 /* This function can GC */ 204 /* This function does not GC */
170 Lisp_Object key; 205 Lisp_Object key;
171 struct get_profiling_info_closure *closure = void_closure; 206 struct get_profiling_info_closure *closure = void_closure;
172 EMACS_INT val; 207 EMACS_INT val;
173 208
174 CVOID_TO_LISP (key, void_key); 209 CVOID_TO_LISP (key, void_key);
181 DEFUN ("get-profiling-info", Fget_profiling_info, 0, 0, 0, /* 216 DEFUN ("get-profiling-info", Fget_profiling_info, 0, 0, 0, /*
182 Return the profiling info as an alist. 217 Return the profiling info as an alist.
183 */ 218 */
184 ()) 219 ())
185 { 220 {
221 /* This function does not GC */
186 struct get_profiling_info_closure closure; 222 struct get_profiling_info_closure closure;
187 223
188 closure.accum = Qnil; 224 closure.accum = Qnil;
189 if (big_profile_table) 225 if (big_profile_table)
190 maphash (get_profiling_info_maphash, big_profile_table, &closure); 226 {
227 int count = specpdl_depth ();
228 record_unwind_protect (profile_lock_unwind, Qnil);
229 inside_profiling = 1;
230 maphash (get_profiling_info_maphash, big_profile_table, &closure);
231 unbind_to (count, Qnil);
232 }
191 return closure.accum; 233 return closure.accum;
192 } 234 }
193 235
194 struct mark_profiling_info_closure 236 struct mark_profiling_info_closure
195 { 237 {
199 static void 241 static void
200 mark_profiling_info_maphash (CONST void *void_key, 242 mark_profiling_info_maphash (CONST void *void_key,
201 void *void_val, 243 void *void_val,
202 void *void_closure) 244 void *void_closure)
203 { 245 {
204 /* This function can GC */
205 Lisp_Object key; 246 Lisp_Object key;
206 struct mark_profiling_info_closure *closure = void_closure; 247 struct mark_profiling_info_closure *closure = void_closure;
207 248
208 CVOID_TO_LISP (key, void_key); 249 CVOID_TO_LISP (key, void_key);
209 (closure->markfun) (key); 250 (closure->markfun) (key);
210 } 251 }
211 252
212 void 253 void
213 mark_profiling_info (void (*markfun) (Lisp_Object)) 254 mark_profiling_info (void (*markfun) (Lisp_Object))
214 { 255 {
256 /* This function does not GC (if markfun doesn't) */
215 struct mark_profiling_info_closure closure; 257 struct mark_profiling_info_closure closure;
216 258
217 closure.markfun = markfun; 259 closure.markfun = markfun;
218 if (big_profile_table) 260 if (big_profile_table)
219 maphash (mark_profiling_info_maphash, big_profile_table, &closure); 261 {
262 inside_profiling = 1;
263 maphash (mark_profiling_info_maphash, big_profile_table, &closure);
264 inside_profiling = 0;
265 }
220 } 266 }
221 267
222 DEFUN ("clear-profiling-info", Fclear_profiling_info, 0, 0, 0, /* 268 DEFUN ("clear-profiling-info", Fclear_profiling_info, 0, 0, 0, /*
223 Clear out the recorded profiling info. 269 Clear out the recorded profiling info.
224 */ 270 */
225 ()) 271 ())
226 { 272 {
273 /* This function does not GC */
227 if (big_profile_table) 274 if (big_profile_table)
228 clrhash (big_profile_table); 275 {
276 inside_profiling = 1;
277 clrhash (big_profile_table);
278 inside_profiling = 0;
279 }
229 return Qnil; 280 return Qnil;
230 } 281 }
231 282
232 DEFUN ("profiling-active-p", Fprofiling_active_p, 0, 0, 0, /* 283 DEFUN ("profiling-active-p", Fprofiling_active_p, 0, 0, 0, /*
233 Return non-nil if profiling information is currently being recorded. 284 Return non-nil if profiling information is currently being recorded.
255 Used when the argument to `start-profiling' is nil or omitted. 306 Used when the argument to `start-profiling' is nil or omitted.
256 Note that the time in question is CPU time (when the program is executing 307 Note that the time in question is CPU time (when the program is executing
257 or the kernel is executing on behalf of the program) and not real time. 308 or the kernel is executing on behalf of the program) and not real time.
258 */ ); 309 */ );
259 default_profiling_interval = 1000; 310 default_profiling_interval = 1000;
311
312 inside_profiling = 0;
260 313
261 QSin_redisplay = build_string ("(in redisplay)"); 314 QSin_redisplay = build_string ("(in redisplay)");
262 staticpro (&QSin_redisplay); 315 staticpro (&QSin_redisplay);
263 QSin_garbage_collection = build_string ("(in garbage collection)"); 316 QSin_garbage_collection = build_string ("(in garbage collection)");
264 staticpro (&QSin_garbage_collection); 317 staticpro (&QSin_garbage_collection);