www.pudn.com > geosteiner-3.1.zip > cputime.c
/*********************************************************************** File: cputime.c Rev: a-1 Date: 04/16/93 Copyright (c) 1993, 2001 by David M. Warme ************************************************************************ This file contains routines for computing CPU time consumption for the program. ************************************************************************ Modification Log: a-1: 04/16/93 warme : Created. ************************************************************************/ #include "config.h" #include "steiner.h" #ifdef UNIX_CPU_TIME #include#include #include #endif #include /* * Global Routines */ cpu_time_t get_cpu_time (void); void convert_cpu_time (cpu_time_t, char *); /* * Define API_CLOCKS_PER_SECOND to be the tick rate presented to the * program by the chosen API. */ #ifdef UNIX_CPU_TIME #define API_CLOCKS_PER_SECOND CLK_TCK /* The Posix value */ #else #define API_CLOCKS_PER_SECOND CLOCKS_PER_SEC /* The ANSI C value */ #endif /* * This routine gets the current amount of CPU time that the program has * used. It is returned in a format we define that is independent of the * operating system (i.e. hundreth's of a second). * * Because the times we are measuring can be quite long (several days), * we can run into overflow problems if the operating system gives us * a CPU timer with too high a resolution (i.e. microseconds). This * code can be compiled to use either the standard interfaces defined * by ANSI C, or the native UNIX interface. Choose the one that has * a resolution closest to our own TICKS_PER_SEC units. * * The basic conversion formula is: * * sys_ticks * our_ticks_per_sec 1 * our_ticks = floor (----------------------------- + ---) * sys_ticks_per_sec 2 * * which can be re-written * * 2 * sys_ticks * our_tps + sys_tps * our_ticks = floor (---------------------------------) * 2 * sys_tps * * We compute this using one of several methods, depending upon the * relationship between sys_ticks_per_sec and our_ticks_per_sec. * The idea of it all is to minimize the chance of arithmetic overflow. */ cpu_time_t get_cpu_time (void) { clock_t total; int32u seconds; int32u ticks; cpu_time_t cpu_time; static clock_t clocks_per_sec = 0; static int32u Q, R, method; #ifdef UNIX_CPU_TIME { struct tms t; times (&t); total = t.tms_utime + t.tms_stime + t.tms_cutime + t.tms_cstime; } #else /* Using the ANSI C defined interface... */ total = clock (); #endif if (clocks_per_sec EQ 0) { /* On some systems this is a system call. Do only once! */ clocks_per_sec = API_CLOCKS_PER_SECOND; /* Now pick the conversion method and parameters. */ if (TICKS_PER_SEC >= clocks_per_sec) { Q = TICKS_PER_SEC / clocks_per_sec; R = TICKS_PER_SEC % clocks_per_sec; method = (R EQ 0) ? 0 : 1; } else { R = clocks_per_sec % TICKS_PER_SEC; if (R EQ 0) { Q = clocks_per_sec / TICKS_PER_SEC; method = 2; } else { method = 3; } } } seconds = total / clocks_per_sec; ticks = total % clocks_per_sec; /* Convert the fractions of a second ticks into .01 second units. */ switch (method) { case 0: ticks *= Q; break; case 1: ticks = ticks * Q + (2 * ticks * R + clocks_per_sec) / (2 * clocks_per_sec); break; case 2: ticks = (2 * ticks + Q) / (2 * Q); break; case 3: ticks = ((2 * TICKS_PER_SEC) * ticks + clocks_per_sec) / (2 * clocks_per_sec); break; default: fatal ("get_cpu_time: Bug 1."); break; } cpu_time = seconds * TICKS_PER_SEC + ticks; return (cpu_time); } /* * This routine will convert the given CPU time into a printable * null-terminated ASCII string. The answer contains two decimal places. */ void convert_cpu_time ( cpu_time_t time, char * out_buf ) { cpu_time_t secs; cpu_time_t ticks; char * p; char buf [20]; #define ZERO ((cpu_time_t) 0) #define TEN ((cpu_time_t) 10) secs = time / TICKS_PER_SEC; ticks = time % TICKS_PER_SEC; p = &buf [0]; if (secs <= ZERO) { *p++ = '0'; } else { while (secs > ZERO) { *p++ = (secs % TEN) + '0'; secs /= TEN; } } while (p > &buf [0]) { *out_buf++ = *--p; } *out_buf++ = '.'; ticks *= TEN; *out_buf++ = (ticks / TICKS_PER_SEC) + '0'; ticks %= TICKS_PER_SEC; ticks *= TEN; *out_buf++ = (ticks / TICKS_PER_SEC) + '0'; *out_buf++ = '\0'; #undef ZERO #undef TEN }