Changeset View
Changeset View
Standalone View
Standalone View
contrib/top/utils.c
Property | Old Value | New Value |
---|---|---|
svn:eol-style | null | native \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
/* | /* | ||||
* Top users/processes display for Unix | * Copyright (c) 1984 through 2008, William LeFebvre | ||||
* Version 3 | * All rights reserved. | ||||
* | * | ||||
* This program may be freely redistributed, | * Redistribution and use in source and binary forms, with or without | ||||
* but this entire comment MUST remain intact. | * modification, are permitted provided that the following conditions are met: | ||||
* | * | ||||
* Copyright (c) 1984, 1989, William LeFebvre, Rice University | * * Redistributions of source code must retain the above copyright | ||||
* Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University | * notice, this list of conditions and the following disclaimer. | ||||
* | * | ||||
* * Redistributions in binary form must reproduce the above | |||||
* copyright notice, this list of conditions and the following disclaimer | |||||
* in the documentation and/or other materials provided with the | |||||
* distribution. | |||||
* | |||||
* * Neither the name of William LeFebvre nor the names of other | |||||
* contributors may be used to endorse or promote products derived from | |||||
* this software without specific prior written permission. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
* | |||||
* $FreeBSD$ | * $FreeBSD$ | ||||
*/ | */ | ||||
/* | /* | ||||
* Top users/processes display for Unix | |||||
* Version 3 | |||||
*/ | |||||
/* | |||||
* This file contains various handy utilities used by top. | * This file contains various handy utilities used by top. | ||||
*/ | */ | ||||
#include "top.h" | |||||
#include "os.h" | #include "os.h" | ||||
#include <ctype.h> | |||||
#ifdef HAVE_STDARG_H | |||||
#include <stdarg.h> | |||||
#else | |||||
#undef DEBUG | |||||
#endif | |||||
#include "top.h" | |||||
#include "utils.h" | |||||
int atoiwi(str) | static int | ||||
alldigits(char *s) | |||||
char *str; | { | ||||
int ch; | |||||
while ((ch = *s++) != '\0') | |||||
{ | { | ||||
if (!isdigit(ch)) | |||||
{ | |||||
return 0; | |||||
} | |||||
} | |||||
return 1; | |||||
} | |||||
int | |||||
atoiwi(char *str) | |||||
{ | |||||
register int len; | register int len; | ||||
len = strlen(str); | len = strlen(str); | ||||
if (len != 0) | if (len != 0) | ||||
{ | { | ||||
if (strncmp(str, "infinity", len) == 0 || | if (strncmp(str, "infinity", len) == 0 || | ||||
strncmp(str, "all", len) == 0 || | strncmp(str, "all", len) == 0 || | ||||
strncmp(str, "maximum", len) == 0) | strncmp(str, "maximum", len) == 0) | ||||
{ | { | ||||
return(Infinity); | return(Infinity); | ||||
} | } | ||||
else if (str[0] == '-') | else if (alldigits(str)) | ||||
{ | { | ||||
return(Invalid); | return(atoi(str)); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
return(atoi(str)); | return(Invalid); | ||||
} | } | ||||
} | } | ||||
return(0); | return(0); | ||||
} | } | ||||
/* | /* | ||||
* itoa - convert integer (decimal) to ascii string for positive numbers | * itoa - convert integer (decimal) to ascii string for positive numbers | ||||
* only (we don't bother with negative numbers since we know we | * only (we don't bother with negative numbers since we know we | ||||
* don't use them). | * don't use them). | ||||
*/ | */ | ||||
/* | /* | ||||
* How do we know that 16 will suffice? | * How do we know that 16 will suffice? | ||||
* Because the biggest number that we will | * Because the biggest number that we will | ||||
* ever convert will be 2^32-1, which is 10 | * ever convert will be 2^32-1, which is 10 | ||||
* digits. | * digits. | ||||
*/ | */ | ||||
/* If ints are ever wider than this, the following code will buffer overflow */ | |||||
_Static_assert(sizeof(int) <= 4, "buffer too small for this sized int"); | _Static_assert(sizeof(int) <= 4, "buffer too small for this sized int"); | ||||
char *itoa(val) | char * | ||||
itoa(int val) | |||||
register int val; | |||||
{ | { | ||||
register char *ptr; | register char *ptr; | ||||
static char buffer[16]; /* result is built here */ | static char buffer[16]; /* result is built here */ | ||||
/* 16 is sufficient since the largest number | /* 16 is sufficient since the largest number | ||||
we will ever convert will be 2^32-1, | we will ever convert will be 2^32-1, | ||||
which is 10 digits. */ | which is 10 digits. */ | ||||
ptr = buffer + sizeof(buffer); | ptr = buffer + sizeof(buffer); | ||||
Show All 11 Lines | |||||
} | } | ||||
/* | /* | ||||
* itoa7(val) - like itoa, except the number is right justified in a 7 | * itoa7(val) - like itoa, except the number is right justified in a 7 | ||||
* character field. This code is a duplication of itoa instead of | * character field. This code is a duplication of itoa instead of | ||||
* a front end to a more general routine for efficiency. | * a front end to a more general routine for efficiency. | ||||
*/ | */ | ||||
char *itoa7(val) | char * | ||||
itoa_w(int val, int w) | |||||
register int val; | |||||
{ | { | ||||
register char *ptr; | char *ptr; | ||||
char *eptr; | |||||
static char buffer[16]; /* result is built here */ | static char buffer[16]; /* result is built here */ | ||||
/* 16 is sufficient since the largest number | /* 16 is sufficient since the largest number | ||||
we will ever convert will be 2^32-1, | we will ever convert will be 2^32-1, | ||||
which is 10 digits. */ | which is 10 digits. */ | ||||
ptr = buffer + sizeof(buffer); | if (w > 15) | ||||
{ | |||||
w = 15; | |||||
} | |||||
eptr = ptr = buffer + sizeof(buffer); | |||||
*--ptr = '\0'; | *--ptr = '\0'; | ||||
if (val == 0) | if (val == 0) | ||||
{ | { | ||||
*--ptr = '0'; | *--ptr = '0'; | ||||
} | } | ||||
else while (val != 0) | else while (val != 0) | ||||
{ | { | ||||
*--ptr = (val % 10) + '0'; | *--ptr = (val % 10) + '0'; | ||||
val /= 10; | val /= 10; | ||||
} | } | ||||
while (ptr > buffer + sizeof(buffer) - 7) | while (ptr >= eptr - w) | ||||
{ | { | ||||
*--ptr = ' '; | *--ptr = ' '; | ||||
} | } | ||||
return(ptr); | return(ptr); | ||||
} | } | ||||
char * | |||||
itoa7(int val) | |||||
{ | |||||
return itoa_w(val, 7); | |||||
} | |||||
/* | /* | ||||
* digits(val) - return number of decimal digits in val. Only works for | * digits(val) - return number of decimal digits in val. Only works for | ||||
* positive numbers. If val <= 0 then digits(val) == 0. | * positive numbers. If val < 0 then digits(val) == 0, but | ||||
* digits(0) == 1. | |||||
*/ | */ | ||||
int digits(val) | int | ||||
digits(int val) | |||||
int val; | |||||
{ | { | ||||
register int cnt = 0; | register int cnt = 0; | ||||
if (val == 0) | |||||
{ | |||||
return 1; | |||||
} | |||||
while (val > 0) | while (val > 0) | ||||
{ | { | ||||
cnt++; | cnt++; | ||||
val /= 10; | val /= 10; | ||||
} | } | ||||
return(cnt); | return(cnt); | ||||
} | } | ||||
/* | /* | ||||
* strecpy(to, from) - copy string "from" into "to" and return a pointer | * printable(char *str) - make the string pointed to by "str" into one that is | ||||
* to the END of the string "to". | * printable (i.e.: all ascii), by converting all non-printable | ||||
* characters into '?'. Replacements are done in place and a pointer | |||||
* to the original buffer is returned. | |||||
*/ | */ | ||||
char *strecpy(to, from) | char * | ||||
printable(char *str) | |||||
register char *to; | { | ||||
register char *from; | register char *ptr; | ||||
register int ch; | |||||
ptr = str; | |||||
while ((ch = *ptr) != '\0') | |||||
{ | { | ||||
if (!isprint(ch)) | |||||
{ | |||||
*ptr = '?'; | |||||
} | |||||
ptr++; | |||||
} | |||||
return(str); | |||||
} | |||||
/* | |||||
* strcpyend(to, from) - copy string "from" into "to" and return a pointer | |||||
* to the END of the string "to". | |||||
*/ | |||||
char * | |||||
strcpyend(char *to, char *from) | |||||
{ | |||||
while ((*to++ = *from++) != '\0'); | while ((*to++ = *from++) != '\0'); | ||||
return(--to); | return(--to); | ||||
} | } | ||||
/* | /* | ||||
* string_index(string, array) - find string in array and return index | * char * | ||||
* homogenize(char *str) | |||||
* | |||||
* Remove unwanted characters from "str" and make everything lower case. | |||||
* Newly allocated string is returned: the original is not altered. | |||||
*/ | */ | ||||
int string_index(string, array) | char *homogenize(char *str) | ||||
char *string; | { | ||||
char **array; | char *ans; | ||||
char *fr; | |||||
char *to; | |||||
int ch; | |||||
to = fr = ans = strdup(str); | |||||
while ((ch = *fr++) != '\0') | |||||
{ | { | ||||
if (isalnum(ch)) | |||||
{ | |||||
*to++ = tolower(ch); | |||||
} | |||||
} | |||||
*to = '\0'; | |||||
return ans; | |||||
} | |||||
/* | |||||
* string_index(string, array) - find string in array and return index | |||||
*/ | |||||
int | |||||
string_index(char *string, char **array) | |||||
{ | |||||
register int i = 0; | register int i = 0; | ||||
while (*array != NULL) | while (*array != NULL) | ||||
{ | { | ||||
if (strcmp(string, *array) == 0) | if (strcmp(string, *array) == 0) | ||||
{ | { | ||||
return(i); | return(i); | ||||
} | } | ||||
array++; | array++; | ||||
i++; | i++; | ||||
} | } | ||||
return(-1); | return(-1); | ||||
} | } | ||||
/* | /* | ||||
* char *string_list(char **strings) | |||||
* | |||||
* Create a comma-separated list of the strings in the NULL-terminated | |||||
* "strings". Returned string is malloc-ed and should be freed when the | |||||
* caller is done. Note that this is not an efficient function. | |||||
*/ | |||||
char *string_list(char **strings) | |||||
{ | |||||
int cnt = 0; | |||||
char **pp; | |||||
char *p; | |||||
char *result = NULL; | |||||
char *resp = NULL; | |||||
pp = strings; | |||||
while ((p = *pp++) != NULL) | |||||
{ | |||||
cnt += strlen(p) + 2; | |||||
} | |||||
if (cnt > 0) | |||||
{ | |||||
resp = result = (char *)malloc(cnt); | |||||
pp = strings; | |||||
while ((p = *pp++) != NULL) | |||||
{ | |||||
resp = strcpyend(resp, p); | |||||
if (*pp != NULL) | |||||
{ | |||||
resp = strcpyend(resp, ", "); | |||||
} | |||||
} | |||||
} | |||||
return result; | |||||
} | |||||
/* | |||||
* argparse(line, cntp) - parse arguments in string "line", separating them | * argparse(line, cntp) - parse arguments in string "line", separating them | ||||
* out into an argv-like array, and setting *cntp to the number of | * out into an argv-like array, and setting *cntp to the number of | ||||
* arguments encountered. This is a simple parser that doesn't understand | * arguments encountered. This is a simple parser that doesn't understand | ||||
* squat about quotes. | * squat about quotes. | ||||
*/ | */ | ||||
char **argparse(line, cntp) | char ** | ||||
argparse(char *line, int *cntp) | |||||
char *line; | |||||
int *cntp; | |||||
{ | { | ||||
register char *from; | register char *from; | ||||
register char *to; | register char *to; | ||||
register int cnt; | register int cnt; | ||||
register int ch; | register int ch; | ||||
int length; | int length; | ||||
int lastch; | int lastch; | ||||
register char **argv; | register char **argv; | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | |||||
* percentages(cnt, out, new, old, diffs) - calculate percentage change | * percentages(cnt, out, new, old, diffs) - calculate percentage change | ||||
* between array "old" and "new", putting the percentages i "out". | * between array "old" and "new", putting the percentages i "out". | ||||
* "cnt" is size of each array and "diffs" is used for scratch space. | * "cnt" is size of each array and "diffs" is used for scratch space. | ||||
* The array "old" is updated on each call. | * The array "old" is updated on each call. | ||||
* The routine assumes modulo arithmetic. This function is especially | * The routine assumes modulo arithmetic. This function is especially | ||||
* useful on BSD mchines for calculating cpu state percentages. | * useful on BSD mchines for calculating cpu state percentages. | ||||
*/ | */ | ||||
long percentages(cnt, out, new, old, diffs) | long | ||||
percentages(int cnt, int *out, long *new, long *old, long *diffs) | |||||
int cnt; | |||||
int *out; | |||||
register long *new; | |||||
register long *old; | |||||
long *diffs; | |||||
{ | { | ||||
register int i; | register int i; | ||||
register long change; | register long change; | ||||
register long total_change; | register long total_change; | ||||
register long *dp; | register long *dp; | ||||
long half_total; | long half_total; | ||||
/* initialization */ | /* initialization */ | ||||
Show All 16 Lines | *old++ = *new++; | ||||
/* avoid divide by zero potential */ | /* avoid divide by zero potential */ | ||||
if (total_change == 0) | if (total_change == 0) | ||||
{ | { | ||||
total_change = 1; | total_change = 1; | ||||
} | } | ||||
/* calculate percentages based on overall change, rounding up */ | /* calculate percentages based on overall change, rounding up */ | ||||
half_total = total_change / 2l; | half_total = total_change / 2l; | ||||
/* Do not divide by 0. Causes Floating point exception */ | |||||
if(total_change) { | |||||
for (i = 0; i < cnt; i++) | for (i = 0; i < cnt; i++) | ||||
{ | { | ||||
*out++ = (int)((*diffs++ * 1000 + half_total) / total_change); | *out++ = (int)((*diffs++ * 1000 + half_total) / total_change); | ||||
} | } | ||||
} | |||||
/* return the total in case the caller wants to use it */ | /* return the total in case the caller wants to use it */ | ||||
return(total_change); | return(total_change); | ||||
} | } | ||||
/* | /* | ||||
* errmsg(errnum) - return an error message string appropriate to the | * errmsg(errnum) - return an error message string appropriate to the | ||||
* error number "errnum". This is a substitute for the System V | * error number "errnum". This is a substitute for the System V | ||||
* function "strerror". There appears to be no reliable way to | * function "strerror". There appears to be no reliable way to | ||||
* determine if "strerror" exists at compile time, so I make do | * determine if "strerror" exists at compile time, so I make do | ||||
* by providing something of similar functionality. For those | * by providing something of similar functionality. For those | ||||
* systems that have strerror and NOT errlist, define | * systems that have strerror and NOT errlist, define | ||||
* -DHAVE_STRERROR in the module file and this function will | * -DHAVE_STRERROR in the module file and this function will | ||||
* use strerror. | * use strerror. | ||||
*/ | */ | ||||
/* externs referenced by errmsg */ | /* externs referenced by errmsg */ | ||||
#ifndef HAVE_STRERROR | #ifndef HAVE_STRERROR | ||||
#ifndef SYS_ERRLIST_DECLARED | #if !HAVE_DECL_SYS_ERRLIST | ||||
#define SYS_ERRLIST_DECLARED | |||||
extern char *sys_errlist[]; | extern char *sys_errlist[]; | ||||
#endif | #endif | ||||
extern int sys_nerr; | extern int sys_nerr; | ||||
#endif | #endif | ||||
char *errmsg(errnum) | char * | ||||
errmsg(int errnum) | |||||
int errnum; | |||||
{ | { | ||||
#ifdef HAVE_STRERROR | #ifdef HAVE_STRERROR | ||||
char *msg = strerror(errnum); | char *msg = strerror(errnum); | ||||
if (msg != NULL) | if (msg != NULL) | ||||
{ | { | ||||
return msg; | return msg; | ||||
} | } | ||||
#else | #else | ||||
if (errnum > 0 && errnum < sys_nerr) | if (errnum > 0 && errnum < sys_nerr) | ||||
{ | { | ||||
return((char *)sys_errlist[errnum]); | return((char *)(sys_errlist[errnum])); | ||||
} | } | ||||
#endif | #endif | ||||
return("No error"); | return("No error"); | ||||
} | } | ||||
/* format_percent(v) - format a double as a percentage in a manner that | |||||
* does not exceed 5 characters (excluding any trailing | |||||
* percent sign). Since it is possible for the value | |||||
* to exceed 100%, we format such values with no fractional | |||||
* component to fit within the 5 characters. | |||||
*/ | |||||
char * | |||||
format_percent(double v) | |||||
{ | |||||
static char result[10]; | |||||
/* enumerate the possibilities */ | |||||
if (v < 0 || v >= 100000.) | |||||
{ | |||||
/* we dont want to try extreme values */ | |||||
strcpy(result, " ???"); | |||||
} | |||||
else if (v > 99.99) | |||||
{ | |||||
sprintf(result, "%5.0f", v); | |||||
} | |||||
else | |||||
{ | |||||
sprintf(result, "%5.2f", v); | |||||
} | |||||
return result; | |||||
} | |||||
/* format_time(seconds) - format number of seconds into a suitable | /* format_time(seconds) - format number of seconds into a suitable | ||||
* display that will fit within 6 characters. Note that this | * display that will fit within 6 characters. Note that this | ||||
* routine builds its string in a static area. If it needs | * routine builds its string in a static area. If it needs | ||||
* to be called more than once without overwriting previous data, | * to be called more than once without overwriting previous data, | ||||
* then we will need to adopt a technique similar to the | * then we will need to adopt a technique similar to the | ||||
* one used for format_k. | * one used for format_k. | ||||
*/ | */ | ||||
/* Explanation: | /* Explanation: | ||||
We want to keep the output within 6 characters. For low values we use | We want to keep the output within 6 characters. For low values we use | ||||
the format mm:ss. For values that exceed 999:59, we switch to a format | the format mm:ss. For values that exceed 999:59, we switch to a format | ||||
that displays hours and fractions: hhh.tH. For values that exceed | that displays hours and fractions: hhh.tH. For values that exceed | ||||
999.9, we use hhhh.t and drop the "H" designator. For values that | 999.9, we use hhhh.t and drop the "H" designator. For values that | ||||
exceed 9999.9, we use "???". | exceed 9999.9, we use "???". | ||||
*/ | */ | ||||
char *format_time(seconds) | char * | ||||
format_time(long seconds) | |||||
long seconds; | |||||
{ | { | ||||
register int value; | |||||
register int digit; | |||||
register char *ptr; | |||||
static char result[10]; | static char result[10]; | ||||
/* sanity protection */ | /* sanity protection */ | ||||
if (seconds < 0 || seconds > (99999l * 360l)) | if (seconds < 0 || seconds > (99999l * 360l)) | ||||
{ | { | ||||
strcpy(result, " ???"); | strcpy(result, " ???"); | ||||
} | } | ||||
else if (seconds >= (1000l * 60l)) | else if (seconds >= (1000l * 60l)) | ||||
{ | { | ||||
/* alternate (slow) method displaying hours and tenths */ | /* alternate (slow) method displaying hours and tenths */ | ||||
sprintf(result, "%5.1fH", (double)seconds / (double)(60l * 60l)); | sprintf(result, "%5.1fH", (double)seconds / (double)(60l * 60l)); | ||||
/* It is possible that the sprintf took more than 6 characters. | /* It is possible that the sprintf took more than 6 characters. | ||||
If so, then the "H" appears as result[6]. If not, then there | If so, then the "H" appears as result[6]. If not, then there | ||||
is a \0 in result[6]. Either way, it is safe to step on. | is a \0 in result[6]. Either way, it is safe to step on. | ||||
*/ | */ | ||||
result[6] = '\0'; | result[6] = '\0'; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
/* standard method produces MMM:SS */ | /* standard method produces MMM:SS */ | ||||
/* we avoid printf as must as possible to make this quick */ | /* we avoid printf as must as possible to make this quick */ | ||||
sprintf(result, "%3ld:%02ld", | sprintf(result, "%3ld:%02ld", seconds / 60l, seconds % 60l); | ||||
(long)(seconds / 60), (long)(seconds % 60)); | |||||
} | } | ||||
return(result); | return(result); | ||||
} | } | ||||
/* | /* | ||||
* format_k(amt) - format a kilobyte memory value, returning a string | * format_k(amt) - format a kilobyte memory value, returning a string | ||||
* suitable for display. Returns a pointer to a static | * suitable for display. Returns a pointer to a static | ||||
* area that changes each call. "amt" is converted to a | * area that changes each call. "amt" is converted to a | ||||
Show All 13 Lines | |||||
* NUM_STRINGS defines the number of strings in this array: we can tolerate | * NUM_STRINGS defines the number of strings in this array: we can tolerate | ||||
* up to NUM_STRINGS calls before we start overwriting old information. | * up to NUM_STRINGS calls before we start overwriting old information. | ||||
* Keeping NUM_STRINGS a power of two will allow an intelligent optimizer | * Keeping NUM_STRINGS a power of two will allow an intelligent optimizer | ||||
* to convert the modulo operation into something quicker. What a hack! | * to convert the modulo operation into something quicker. What a hack! | ||||
*/ | */ | ||||
#define NUM_STRINGS 8 | #define NUM_STRINGS 8 | ||||
char *format_k(amt) | char * | ||||
format_k(long amt) | |||||
int amt; | |||||
{ | { | ||||
static char retarray[NUM_STRINGS][16]; | static char retarray[NUM_STRINGS][16]; | ||||
static int index = 0; | static int index = 0; | ||||
register char *p; | |||||
register char *ret; | register char *ret; | ||||
register char tag = 'K'; | register char tag = 'K'; | ||||
p = ret = retarray[index]; | ret = retarray[index]; | ||||
index = (index + 1) % NUM_STRINGS; | index = (index + 1) % NUM_STRINGS; | ||||
if (amt >= 10000) | if (amt >= 10000) | ||||
{ | { | ||||
amt = (amt + 512) / 1024; | amt = (amt + 512) / 1024; | ||||
tag = 'M'; | tag = 'M'; | ||||
if (amt >= 10000) | if (amt >= 10000) | ||||
{ | { | ||||
amt = (amt + 512) / 1024; | amt = (amt + 512) / 1024; | ||||
tag = 'G'; | tag = 'G'; | ||||
} | } | ||||
} | } | ||||
p = strecpy(p, itoa(amt)); | snprintf(ret, sizeof(retarray[index])-1, "%ld%c", amt, tag); | ||||
*p++ = tag; | |||||
*p = '\0'; | |||||
return(ret); | return(ret); | ||||
} | } | ||||
char *format_k2(amt) | /* | ||||
* Time keeping functions. | |||||
*/ | |||||
unsigned long long amt; | static struct timeval lasttime = { 0, 0 }; | ||||
static unsigned int elapsed_msecs = 0; | |||||
void | |||||
time_get(struct timeval *tv) | |||||
{ | { | ||||
static char retarray[NUM_STRINGS][16]; | /* get the current time */ | ||||
static int index = 0; | #ifdef HAVE_GETTIMEOFDAY | ||||
register char *p; | gettimeofday(tv, NULL); | ||||
register char *ret; | #else | ||||
register char tag = 'K'; | tv->tv_sec = (long)time(NULL); | ||||
tv->tv_usec = 0; | |||||
#endif | |||||
} | |||||
p = ret = retarray[index]; | void | ||||
index = (index + 1) % NUM_STRINGS; | time_mark(struct timeval *tv) | ||||
if (amt >= 100000) | |||||
{ | { | ||||
amt = (amt + 512) / 1024; | struct timeval thistime; | ||||
tag = 'M'; | struct timeval timediff; | ||||
if (amt >= 100000) | |||||
/* if the caller didnt provide one then use our own */ | |||||
if (tv == NULL) | |||||
{ | { | ||||
amt = (amt + 512) / 1024; | tv = &thistime; | ||||
tag = 'G'; | |||||
} | } | ||||
/* get the current time */ | |||||
#ifdef HAVE_GETTIMEOFDAY | |||||
gettimeofday(tv, NULL); | |||||
#else | |||||
tv->tv_sec = (long)time(NULL); | |||||
tv->tv_usec = 0; | |||||
#endif | |||||
/* calculate the difference */ | |||||
timediff.tv_sec = tv->tv_sec - lasttime.tv_sec; | |||||
timediff.tv_usec = tv->tv_usec - lasttime.tv_usec; | |||||
if (timediff.tv_usec < 0) { | |||||
timediff.tv_sec--; | |||||
timediff.tv_usec += 1000000; | |||||
} | } | ||||
p = strecpy(p, itoa((int)amt)); | /* convert to milliseconds */ | ||||
*p++ = tag; | elapsed_msecs = timediff.tv_sec * 1000 + timediff.tv_usec / 1000; | ||||
*p = '\0'; | if (elapsed_msecs == 0) | ||||
{ | |||||
elapsed_msecs = 1; | |||||
} | |||||
return(ret); | /* save for next time */ | ||||
lasttime = *tv; | |||||
} | } | ||||
unsigned int | |||||
time_elapsed() | |||||
{ | |||||
return elapsed_msecs; | |||||
} | |||||
unsigned int | |||||
diff_per_second(unsigned int x, unsigned int y) | |||||
{ | |||||
return (y > x ? UINT_MAX - y + x + 1 : x - y) * 1000 / elapsed_msecs; | |||||
} | |||||
static int debug_on = 0; | |||||
#ifdef DEBUG | |||||
FILE *debugfile; | |||||
#endif | |||||
void | |||||
debug_set(int i) | |||||
{ | |||||
debug_on = i; | |||||
#ifdef DEBUG | |||||
debugfile = fopen("/tmp/top.debug", "w"); | |||||
#endif | |||||
} | |||||
#ifdef DEBUG | |||||
void | |||||
xdprintf(char *fmt, ...) | |||||
{ | |||||
va_list argp; | |||||
va_start(argp, fmt); | |||||
if (debug_on) | |||||
{ | |||||
vfprintf(debugfile, fmt, argp); | |||||
fflush(debugfile); | |||||
} | |||||
va_end(argp); | |||||
} | |||||
#endif | |||||