00001 /* 00002 * Copyright (C) 1997-2004 The CDG Team <cdg@nats.informatik.uni-hamburg.de> 00003 * 00004 * This file is free software; as a special exception the author gives 00005 * unlimited permission to copy and/or distribute it, with or without 00006 * modifications, as long as this notice is preserved. 00007 * 00008 * This program is distributed in the hope that it will be useful, but 00009 * WITHOUT ANY WARRANTY, to the extent permitted by law; without even the 00010 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00011 * 00012 * $Id: timer.c,v 1.28 2004/09/27 17:07:06 micha Exp $ 00013 */ 00014 00015 /* ------------------------------------------------------------------------- 00016 * @addtogroup Timer Timer - timekeeping functions 00017 * @author Michael Schulz 00018 * @date somewhen in 1998 00019 * 00020 * 00021 * This module exports functions for measuring the time spent in various 00022 * parts of the application. The time measured is always user time + kernel 00023 * time. 00024 * @{ 00025 */ 00026 00027 /* ---------------------------------------------------------------------- */ 00028 #include <config.h> 00029 #include <sys/time.h> 00030 #include <time.h> 00031 #include <stdio.h> 00032 #include <stdlib.h> 00033 #include <sys/resource.h> 00034 #include <signal.h> 00035 #include <blah.h> 00036 #include <limits.h> 00037 #include "hook.h" 00038 #include "timer.h" 00039 00040 /* -- VARIABLES --------------------------------------------------------- */ 00041 00042 /* ------------------------------------------------------------------------- 00043 * This variable \b timerExpired= is a flag to be set after a 00044 * user-defined timespan has elapsed. 00045 */ 00046 Boolean timerExpired; 00047 00048 static double timerClockTicks = -1; /**< initialized correctly in 00049 * timerInitialize */ 00050 00051 /* ---------------------------------------------------------------------------- 00052 * The fast timer -- faster, but expires over 2470 sec 00053 */ 00054 00055 /* ---------------------------------------------------------------------------- 00056 * return clocks elapse since program start (user + system) 00057 * 00058 * this function returns the time used so far by the process, as computed 00059 * by the system function \b clock()=. 00060 */ 00061 TimerFast timerStartFast(void) 00062 { 00063 return clock(); 00064 } 00065 00066 /* ---------------------------------------------------------------------------- 00067 * return milliseconds elapsed since last timerStartFast 00068 * 00069 * this function returns the difference between the time used so far and 00070 * a time determined earlier by \b timerstartfast() in milliseconds. 00071 */ 00072 unsigned long timerElapsedFast(TimerFast timer) 00073 { 00074 return (unsigned long)((double)(clock() - timer) / timerClockTicks); 00075 } 00076 00077 /* ---------------------------------------------------------------------------- 00078 The standard timer -- slower, but only expires over 2,470,000 sec 00079 */ 00080 00081 /* ---------------------------------------------------------------------------- 00082 * Store number of cycles elapsed since program start (user + system) 00083 in timer. 00084 00085 * This function performs a call to \b getrusage() and fills the 00086 * corresponding fields in the \b Timer structure. 00087 */ 00088 void timerStart(Timer timer) 00089 { 00090 struct rusage t; 00091 00092 if (timer == NULL) { 00093 return; 00094 } 00095 getrusage(RUSAGE_SELF, &t); 00096 timer->tv_sec = t.ru_utime.tv_sec + t.ru_stime.tv_sec; 00097 timer->tv_usec = t.ru_utime.tv_usec + t.ru_stime.tv_usec; 00098 } 00099 00100 /* ---------------------------------------------------------------------------- 00101 * allocates memory for the timer and calls timerStart 00102 */ 00103 Timer timerNew(void) 00104 { 00105 Timer timer = (Timer) memMalloc(sizeof (TimerStruct)); 00106 00107 timerStart(timer); 00108 return timer; 00109 } 00110 00111 /* ---------------------------------------------------------------------------- 00112 * frees the timer memory 00113 * 00114 * this function deallocates a \b timer. 00115 */ 00116 void timerFree(Timer timer) 00117 { 00118 if (timer == NULL) { 00119 return; 00120 } 00121 memFree(timer); 00122 } 00123 00124 /* ---------------------------------------------------------------------------- 00125 * Return milliseconds elapsed since last timerStart() on this timer. 00126 * 00127 * this function returns the difference between the time used so far and 00128 * a time determined earlier by \b timerstart() in milliseconds. 00129 */ 00130 unsigned long timerElapsed(Timer timer) 00131 { 00132 struct rusage t; 00133 long s, u; 00134 00135 getrusage(RUSAGE_SELF, &t); 00136 s = t.ru_utime.tv_sec + t.ru_stime.tv_sec - timer->tv_sec; 00137 u = t.ru_utime.tv_usec + t.ru_stime.tv_usec - timer->tv_usec; 00138 00139 if (u < 0) { 00140 u += 1000000; 00141 s--; 00142 } 00143 if ((s < LONG_MAX / 1000) || ((s == LONG_MAX / 1000) && (LONG_MAX - s * 1000 >= u / 1000))) { 00144 return (unsigned long)(s) * 1000 + u / 1000; 00145 } else { 00146 cdgPrintf(CDG_ERROR, "ERROR: the timer has overflow\n"); 00147 return 0; 00148 } 00149 } 00150 00151 /* ---------------------------------------------------------------------------- 00152 * Signal handler for when timer expires. 00153 * 00154 * this function sets \b timerexpired. 00155 */ 00156 static void expire(int n) 00157 { 00158 timerExpired = TRUE; 00159 } 00160 00161 /* ---------------------------------------------------------------------------- 00162 * Set an alarm-clock that will set the flag timerExpired after ``limit'' 00163 * milliseconds. 00164 * 00165 * this function sets a time limit for the completion of a task. after 00166 * \b limit milliseconds the variable \b timerexpired is 00167 * asynchronously set to~1 by \b expire(). this can be used as follows: 00168 * 00169 * <i> 00170 * \/\* build lvs for one second \*\/ 00171 * 00172 * void fastbuildvalues( 00173 * constraintnet net, 00174 * leveldecl level, 00175 * ConstraintNode cn, 00176 * List modifiers) { 00177 * 00178 * LexemNode modifiee; 00179 * * LevelValue lv; 00180 * 00181 * int i; 00182 * List l; 00183 * String label; 00184 * 00185 * timerSetAlarm(1000); 00186 * 00187 * for (i = 0; i < vectorSize(net->lexemgraph->nodes); i++) { 00188 * modifiee = (LexemNode) vectorElement(net->lexemgraph->nodes, i) 00189 * 00190 * for (l = level->labels; l != NULL; l = l->next) { 00191 * label = (String) l->item; 00192 * 00193 * lv = lvNew(modifiers, level, label, modifiee); 00194 * vectorAddElement(node->values, lv); 00195 * } 00196 * 00197 * if(timerExpired) { break; } 00198 * 00199 * } 00200 * 00201 * } 00202 * </i> 00203 */ 00204 void timerSetAlarm(long unsigned int limit) 00205 { 00206 struct itimerval value; 00207 ldiv_t l; 00208 #ifdef NO_SIG_PROF 00209 return; 00210 #endif 00211 timerExpired = FALSE; 00212 00213 value.it_interval.tv_sec = 0; 00214 value.it_interval.tv_usec = 0; 00215 00216 l = ldiv(limit, 1000); 00217 value.it_value.tv_sec = l.quot; 00218 value.it_value.tv_usec = l.rem * 1000; 00219 00220 signal(SIGPROF, expire); 00221 setitimer(ITIMER_PROF, &value, (struct itimerval *)NULL); 00222 } 00223 00224 /* ---------------------------------------------------------------------------- 00225 * stop the alarm clock 00226 * 00227 * This function cancels the alarm set by \b timerSetAlarm(). 00228 */ 00229 void timerStopAlarm(void) 00230 { 00231 #ifdef NO_SIG_PROF 00232 return; 00233 #endif 00234 signal(SIGPROF, SIG_IGN); 00235 timerExpired = FALSE; 00236 } 00237 00238 /* ---------------------------------------------------------------------------- 00239 * timerInitialize 00240 * 00241 * this function stops any alarms pending and initializes the variable 00242 * \b timerclockticks. 00243 */ 00244 void timerInitialize(void) 00245 { 00246 timerStopAlarm(); 00247 00248 /* get system clock ticks */ 00249 timerClockTicks = CLOCKS_PER_SEC / 1000.0; 00250 }