beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / luaprofiler / function_meter.c
blob2636ee16028bf68180a5d54cdbe4023183feb41f
1 /*
2 ** LuaProfiler
3 ** Copyright Kepler Project 2005-2007 (http://www.keplerproject.org/luaprofiler)
4 ** $Id: function_meter.c,v 1.9 2008/05/19 18:36:23 mascarenhas Exp $
5 */
7 /*****************************************************************************
8 function_meter.c:
9 Module to compute the times for functions (local times and total times)
11 Design:
12 'lprofM_init' set up the function times meter service
13 'lprofM_enter_function' called when the function stack increases one level
14 'lprofM_leave_function' called when the function stack decreases one level
16 'lprofM_resume_function' called when the profiler is returning from a time
17 consuming task
18 'lprofM_resume_total_time' idem
19 'lprofM_resume_local_time' called when a child function returns the execution
20 to it's caller (current function)
21 'lprofM_pause_function' called when the profiler need to do things that
22 may take too long (writing a log, for example)
23 'lprofM_pause_total_time' idem
24 'lprofM_pause_local_time' called when the current function has called
25 another one or when the function terminates
26 *****************************************************************************/
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include "clocks.h"
33 /* #include "stack.h" is done by function_meter.h */
34 #include "function_meter.h"
36 #ifdef DEBUG
37 #include <stdlib.h>
38 #define ASSERT(e, msg) if (!e) { \
39 fprintf(stdout, \
40 "function_meter.c: assertion failed: %s\n", \
41 msg); \
42 exit(1); }
43 #else
44 #define ASSERT(e, msg)
45 #endif
47 /* structures to receive stack elements, declared globals */
48 /* in the hope they will perform faster */
49 static lprofS_STACK_RECORD newf; /* used in 'enter_function' */
50 static lprofS_STACK_RECORD leave_ret; /* used in 'leave_function' */
54 /* sum the seconds based on the time marker */
55 static void compute_local_time(lprofS_STACK_RECORD *e) {
56 ASSERT(e, "local time null");
57 e->local_time += lprofC_get_seconds(e->time_marker_function_local_time);
61 /* sum the seconds based on the time marker */
62 static void compute_total_time(lprofS_STACK_RECORD *e) {
63 ASSERT(e, "total time null");
64 e->total_time += lprofC_get_seconds(e->time_marker_function_total_time);
68 /* compute the local time for the current function */
69 void lprofM_pause_local_time(lprofP_STATE* S) {
70 compute_local_time(S->stack_top);
74 /* pause the total timer for all the functions that are in the stack */
75 void lprofM_pause_total_time(lprofP_STATE* S) {
76 lprofS_STACK aux;
78 ASSERT(S->stack_top, "pause_total_time: stack_top null");
80 /* auxiliary stack */
81 aux = S->stack_top;
83 /* pause */
84 while (aux) {
85 compute_total_time(aux);
86 aux = aux->next;
91 /* pause the local and total timers for all functions in the stack */
92 void lprofM_pause_function(lprofP_STATE* S) {
94 ASSERT(S->stack_top, "pause_function: stack_top null");
96 lprofM_pause_local_time(S);
97 lprofM_pause_total_time(S);
101 /* resume the local timer for the current function */
102 void lprofM_resume_local_time(lprofP_STATE* S) {
104 ASSERT(S->stack_top, "resume_local_time: stack_top null");
106 /* the function is in the top of the stack */
107 lprofC_start_timer(&(S->stack_top->time_marker_function_local_time));
111 /* resume the total timer for all the functions in the stack */
112 void lprofM_resume_total_time(lprofP_STATE* S) {
113 lprofS_STACK aux;
115 ASSERT(S->stack_top, "resume_total_time: stack_top null");
117 /* auxiliary stack */
118 aux = S->stack_top;
120 /* resume */
121 while (aux) {
122 lprofC_start_timer(&(aux->time_marker_function_total_time));
123 aux = aux->next;
128 /* resume the local and total timers for all functions in the stack */
129 void lprofM_resume_function(lprofP_STATE* S) {
131 ASSERT(S->stack_top, "resume_function: stack_top null");
133 lprofM_resume_local_time(S);
134 lprofM_resume_total_time(S);
138 /* the local time for the parent function is paused */
139 /* and the local and total time markers are started */
140 void lprofM_enter_function(lprofP_STATE* S, char *file_defined, char *fcn_name, long linedefined, long currentline) {
141 char* prev_name;
142 char* cur_name;
143 /* the flow has changed to another function: */
144 /* pause the parent's function timer timer */
145 if (S->stack_top) {
146 lprofM_pause_local_time(S);
147 prev_name = S->stack_top->function_name;
148 } else prev_name = "top level";
149 /* measure new function */
150 lprofC_start_timer(&(newf.time_marker_function_local_time));
151 lprofC_start_timer(&(newf.time_marker_function_total_time));
152 newf.file_defined = file_defined;
153 if(fcn_name != NULL) {
154 newf.function_name = fcn_name;
155 } else if(strcmp(file_defined, "=[C]") == 0) {
156 cur_name = (char*)malloc(sizeof(char)*(strlen("called from ")+strlen(prev_name)+1));
157 sprintf(cur_name, "called from %s", prev_name);
158 newf.function_name = cur_name;
159 } else {
160 cur_name = (char*)malloc(sizeof(char)*(strlen(file_defined)+12));
161 sprintf(cur_name, "%s:%li", file_defined, linedefined);
162 newf.function_name = cur_name;
164 newf.line_defined = linedefined;
165 newf.current_line = currentline;
166 newf.local_time = 0.0;
167 newf.total_time = 0.0;
168 lprofS_push(&(S->stack_top), newf);
172 /* computes times and remove the top of the stack */
173 /* 'isto_resume' specifies if the parent function's timer */
174 /* should be restarted automatically. If it's false, */
175 /* 'resume_local_time()' must be called when the resume */
176 /* should be done */
177 /* returns the funcinfo structure */
178 /* warning: use it before another call to this function, */
179 /* because the funcinfo will be overwritten */
180 lprofS_STACK_RECORD *lprofM_leave_function(lprofP_STATE* S, int isto_resume) {
182 ASSERT(S->stack_top, "leave_function: stack_top null");
184 leave_ret = lprofS_pop(&(S->stack_top));
185 compute_local_time(&leave_ret);
186 compute_total_time(&leave_ret);
187 /* resume the timer for the parent function ? */
188 if (isto_resume)
189 lprofM_resume_local_time(S);
190 return &leave_ret;
194 /* init stack */
195 lprofP_STATE* lprofM_init() {
196 lprofP_STATE *S;
197 S = (lprofP_STATE*)malloc(sizeof(lprofP_STATE));
198 if(S) {
199 S->stack_level = 0;
200 S->stack_top = NULL;
201 return S;
202 } else return NULL;