summaryrefslogtreecommitdiff
path: root/staging/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'staging/time.c')
-rw-r--r--staging/time.c211
1 files changed, 211 insertions, 0 deletions
diff --git a/staging/time.c b/staging/time.c
new file mode 100644
index 0000000..4225b9e
--- /dev/null
+++ b/staging/time.c
@@ -0,0 +1,211 @@
+/*
+ * Mausezahn - A fast versatile traffic generator
+ * Copyright (C) 2008-2010 Herbert Haas
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html
+ *
+*/
+
+
+#include "mz.h"
+
+
+// Check if current system supports the nanosecond timer functions.
+// Additionally, measure the precision.
+// This function should be called upon program start.
+//
+int check_timer()
+{
+ struct timespec res;
+ int r;
+
+// Check if the glibc is recent enough:
+#ifdef _POSIX_C_SOURCE
+
+ if (_POSIX_C_SOURCE >= 199309L) {
+ r = clock_getres(CLOCK_MONOTONIC, &res);
+ if (r!=0) perror(" mz/check_timer:");
+ if (verbose) {
+ fprintf(stderr, " This system supports a high resolution clock.\n");
+ fprintf(stderr, " The clock resolution is %li nanoseconds.\n",
+ res.tv_nsec);
+ }
+ }
+ else {
+ fprintf(stderr,
+ " WARNING: Your system does NOT support the newer high resolution clock\n"
+ " Please inform the author: herbert@perihel.at\n");
+ exit(1);
+ }
+#endif
+ return 0;
+}
+
+
+
+
+// This is the replacement for gettimeofday() which would result in 'jumps' if
+// the system clock is adjusted (e. g. via a NTP process) and finally the jitter
+// measurement would include wrong datapoints.
+//
+// Furthermore the function below utilizes the newer hi-res nanosecond timers.
+inline void getcurtime (struct mz_timestamp *t)
+{
+ struct timespec ct;
+ clock_gettime(CLOCK_MONOTONIC, &ct);
+ t->sec = ct.tv_sec;
+ t->nsec = ct.tv_nsec;
+}
+
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+// Purpose: Calculate time deltas of two timestamps stored in struct timeval.
+//
+// Subtract the "struct timeval" values X and Y, storing the result in RESULT,
+// i. e. X-Y=RESULT.
+//
+// RETURN VALUES:
+//
+// Sign: 1 = negative, 0 = positive
+// Error: -1 due to a wrong timestamp (i. e. nsec > 999999999L)
+//
+inline int timestamp_subtract (struct mz_timestamp *x, struct mz_timestamp *y, struct mz_timestamp *result)
+{
+ int32_t ndiff;
+ int sign=0, carry=0;
+
+ // Check for wrong timestamps
+ if ((x->nsec>999999999L) || (y->nsec>999999999L)) return -1;
+
+ if (y->sec > x->sec) sign=1;
+ else if ((y->sec == x->sec) && (y->nsec > x->nsec)) sign=1;
+
+ ndiff = x->nsec - y->nsec;
+ if ((ndiff>0) && (sign)) carry=1;
+ if ((ndiff<0) && (sign)) ndiff = y->nsec - x->nsec;
+ if ((ndiff<0) && (!sign)) {
+ ndiff = 1000000000L + ndiff;
+ carry=1;
+ }
+
+ if (sign)
+ result->sec = y->sec - x->sec - carry;
+ else
+ result->sec = x->sec - y->sec - carry;
+
+ result->nsec = ndiff;
+ return sign;
+}
+
+
+// Add two variables of type struct mz_timestamp: x+y=result.
+//
+inline void timestamp_add (struct mz_timestamp *x, struct mz_timestamp *y, struct mz_timestamp *result)
+{
+ int carry=0;
+ u_int32_t c;
+
+ c = x->nsec + y->nsec;
+ if (c>999999999L) {
+ carry=1;
+ result->nsec =c-1000000000;
+ } else result->nsec =c;
+
+ result->sec = x->sec + y->sec + carry;
+}
+
+
+
+// Returns a human readable timestamp in the string result.
+// Optionally a prefix can be specified, for example if the
+// timestamp is part of a filename.
+//
+// Example:
+// char myTimeStamp[128];
+//
+// timestamp_human(myTimeStamp, NULL);
+//
+// => "20080718_155521"
+//
+// /* or with prefix */
+//
+// timestamp_human(myTimeStamp, "MZ_RTP_jitter_");
+//
+// => "MZ_RTP_jitter_20080718_155521"
+//
+int timestamp_human(char* result, const char* prefix)
+{
+ time_t curtime;
+ struct tm curtime_broken;
+ char curtime_str[32];
+
+ time(&curtime);
+ localtime_r (&curtime, &curtime_broken);
+
+ sprintf(curtime_str, "%4i%02i%02i-%02i%02i%02i",
+ curtime_broken.tm_year+1900,
+ curtime_broken.tm_mon+1,
+ curtime_broken.tm_mday,
+ curtime_broken.tm_hour,
+ curtime_broken.tm_min,
+ curtime_broken.tm_sec);
+
+ if (prefix==NULL)
+ {
+ strncpy(result, curtime_str, 32);
+ }
+ else
+ {
+ strncpy(result, prefix, 32);
+ strncat(result, curtime_str, 32);
+ }
+
+ return 0;
+}
+
+
+// Creates a human readable timestamp in the string result.
+// Optionally a prefix can be specified, for example if the
+// timestamp is part of a filename.
+//
+// Example:
+// char myTimeStamp[9];
+//
+// timestamp_hms (myTimeStamp);
+//
+// => "15:55:21"
+int timestamp_hms(char* result)
+{
+ time_t curtime;
+ struct tm curtime_broken;
+ char curtime_str[32];
+
+ time(&curtime);
+ localtime_r (&curtime, &curtime_broken);
+
+ sprintf(curtime_str, "%02i:%02i:%02i",
+ curtime_broken.tm_hour,
+ curtime_broken.tm_min,
+ curtime_broken.tm_sec);
+
+ strncpy(result, curtime_str, 9);
+
+ return 0;
+}
+
+
+
+
+