summaryrefslogtreecommitdiff
path: root/staging/time.c
blob: 5ad3658fecffe7cedc07d5c2199dac5811bd4f37 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
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(void)
{
	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;
}